diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..211c2b8563 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,52 @@ +/*! + * Copyright 2020 Google Inc. + * + * 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. + */ + +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + ], + rules: { + // Following checks are temporarily disabled. We shall incrementally enable them in the + // future, fixing any violations as we go. + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-use-before-define": 0, + "@typescript-eslint/explicit-function-return-type": 0, + "@typescript-eslint/camelcase": 0, + "@typescript-eslint/no-inferrable-types": 0, + "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/no-inferrable-types": 0, + "@typescript-eslint/no-var-requires": 0, + "@typescript-eslint/no-unused-vars": 0, + "@typescript-eslint/member-delimiter-style": 0, + "@typescript-eslint/no-empty-interface": 0, + "@typescript-eslint/no-array-constructor": 0, + "@typescript-eslint/ban-types": 0, + "no-case-declarations": 0, + "no-useless-escape": 0, + "no-prototype-builtins": 0, + "no-var": 0, + + // Required checks + "indent": ["error", 2] + } +}; diff --git a/package-lock.json b/package-lock.json index 69fd1341fc..60a964a4bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -383,8 +383,7 @@ "@google-cloud/promisify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.2.tgz", - "integrity": "sha512-7WfV4R/3YV5T30WRZW0lqmvZy9hE2/p9MvpI34WuKa2Wz62mLu5XplGTFEMK6uTbJCLWUxTcZ4J4IyClKucE5g==", - "optional": true + "integrity": "sha512-7WfV4R/3YV5T30WRZW0lqmvZy9hE2/p9MvpI34WuKa2Wz62mLu5XplGTFEMK6uTbJCLWUxTcZ4J4IyClKucE5g==" }, "@google-cloud/storage": { "version": "4.1.2", @@ -473,7 +472,6 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -483,14 +481,12 @@ "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "optional": true + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "optional": true, "requires": { "safe-buffer": "~5.2.0" } @@ -527,32 +523,27 @@ "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=", - "optional": true + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" }, "@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "optional": true + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "optional": true + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=", - "optional": true + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -561,32 +552,27 @@ "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=", - "optional": true + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=", - "optional": true + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=", - "optional": true + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=", - "optional": true + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", - "optional": true + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, "@sinonjs/commons": { "version": "1.4.0", @@ -665,6 +651,12 @@ "@types/promises-a-plus": "*" } }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/firebase-token-generator": { "version": "2.0.28", "resolved": "http://registry.npmjs.org/@types/firebase-token-generator/-/firebase-token-generator-2.0.28.tgz", @@ -680,6 +672,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/jsonwebtoken": { "version": "7.2.8", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz", @@ -698,8 +696,7 @@ "@types/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", - "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==", - "optional": true + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" }, "@types/minimatch": { "version": "3.0.3", @@ -792,6 +789,114 @@ "integrity": "sha512-Set5ZdrAaKI/qHdFlVMgm/GsAv/wkXhSTuZFkJ+JI7HK+wIkIlOaUXSXieIvJ0+OvGIqtREFoE+NHJtEq0gtEw==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.20.0.tgz", + "integrity": "sha512-cimIdVDV3MakiGJqMXw51Xci6oEDEoPkvh8ggJe2IIzcc0fYqAxOXN6Vbeanahz6dLZq64W+40iUEc9g32FLDQ==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "2.20.0", + "eslint-utils": "^1.4.3", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.20.0.tgz", + "integrity": "sha512-fEBy9xYrwG9hfBLFEwGW2lKwDRTmYzH3DwTmYbT+SMycmxAoPl0eGretnBFj/s+NfYBG63w/5c3lsvqqz5mYag==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.20.0", + "eslint-scope": "^5.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.20.0.tgz", + "integrity": "sha512-o8qsKaosLh2qhMZiHNtaHKTHyCHc3Triq6aMnwnWj7budm3xAY9owSZzV1uon5T9cWmJRJGzTFa90aex4m77Lw==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.20.0", + "@typescript-eslint/typescript-estree": "2.20.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.20.0.tgz", + "integrity": "sha512-WlFk8QtI8pPaE7JGQGxU7nGcnk1ccKAJkhbVookv94ZcAef3m6oCE/jEDL6dGte3JcD7reKrA0o55XhBRiVT3A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -802,7 +907,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "optional": true, "requires": { "event-target-shim": "^5.0.0" } @@ -823,6 +927,12 @@ "acorn-walk": "^6.0.1" } }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, "acorn-walk": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", @@ -833,7 +943,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "optional": true, "requires": { "es6-promisify": "^5.0.0" } @@ -859,6 +968,15 @@ "ansi-wrap": "^0.1.0" } }, + "ansi-escapes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, "ansi-gray": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", @@ -1127,6 +1245,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async-done": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", @@ -1863,8 +1987,7 @@ "bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", - "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==", - "optional": true + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" }, "binary-extensions": { "version": "1.13.1", @@ -2032,6 +2155,12 @@ } } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2077,6 +2206,12 @@ "supports-color": "^2.0.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -2173,6 +2308,21 @@ } } }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -2756,6 +2906,15 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-storage": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", @@ -2955,14 +3114,12 @@ "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "optional": true + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "optional": true, "requires": { "es6-promise": "^4.0.3" } @@ -3023,12 +3180,248 @@ } } }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "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" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", @@ -3044,8 +3437,7 @@ "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "optional": true + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" }, "execa": { "version": "1.0.0", @@ -3141,6 +3533,17 @@ } } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -3244,8 +3647,7 @@ "fast-text-encoding": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", - "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==", - "optional": true + "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" }, "faye-websocket": { "version": "0.11.3", @@ -3255,6 +3657,24 @@ "websocket-driver": ">=0.5.1" } }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3354,6 +3774,34 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -3572,8 +4020,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -3616,8 +4063,7 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", @@ -3628,8 +4074,7 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3746,8 +4191,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3759,7 +4203,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3782,14 +4225,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3808,7 +4249,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3909,7 +4349,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3995,8 +4434,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -4032,7 +4470,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4052,7 +4489,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4096,14 +4532,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -4115,14 +4549,12 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "optional": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "gaxios": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.1.0.tgz", "integrity": "sha512-Gtpb5sdQmb82sgVkT2GnS2n+Kx4dlFwbeMYcDlD395aEvsLCSQXJJcHt7oJ2LrGxDEAeiOkK79Zv2A8Pzt6CFg==", - "optional": true, "requires": { "abort-controller": "^3.0.0", "extend": "^3.0.2", @@ -4134,8 +4566,7 @@ "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "optional": true + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" } } }, @@ -4143,7 +4574,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.2.1.tgz", "integrity": "sha512-JjDedBWnbXVXWwTpjBdpb9RpVLiowXG4/50rra4hPH8REXAi2si6Xbb48B2SwkQBLz9Wu6+o32GDTvVy2kkLoQ==", - "optional": true, "requires": { "gaxios": "^2.1.0", "json-bigint": "^0.3.0" @@ -4442,7 +4872,6 @@ "version": "5.5.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.5.1.tgz", "integrity": "sha512-zCtjQccWS/EHYyFdXRbfeSGM/gW+d7uMAcVnvXRnjBXON5ijo6s0nsObP0ifqileIDSbZjTlLtgo+UoN8IFJcg==", - "optional": true, "requires": { "arrify": "^2.0.0", "base64-js": "^1.3.0", @@ -4457,8 +4886,7 @@ "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "optional": true + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" } } }, @@ -4496,7 +4924,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.2.tgz", "integrity": "sha512-UfnEARfJKI6pbmC1hfFFm+UAcZxeIwTiEcHfqKe/drMsXD/ilnVjF7zgOGpHXyhuvX6jNJK3S8A0hOQjwtFxEw==", - "optional": true, "requires": { "node-forge": "^0.9.0" }, @@ -4504,8 +4931,7 @@ "node-forge": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz", - "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==", - "optional": true + "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==" } } }, @@ -4524,7 +4950,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.1.tgz", "integrity": "sha512-2FEmEDGi4NdM6u+mtaLjSDDtHiw5wT+nBsI+yrSeFO6fVqPEytYVF6uiIpRaOaZhRP+ozjYWuwwtMlrjAyTcYA==", - "optional": true, "requires": { "gaxios": "^2.1.0", "google-p12-pem": "^2.0.0", @@ -5101,7 +5526,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "optional": true, "requires": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -5122,6 +5546,22 @@ "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5148,6 +5588,115 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inquirer": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -5376,6 +5925,12 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -5709,7 +6264,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", - "optional": true, "requires": { "bignumber.js": "^7.0.0" } @@ -6163,14 +6717,12 @@ "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "optional": true + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "optional": true, "requires": { "yallist": "^3.0.2" } @@ -6336,8 +6888,7 @@ "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "optional": true + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" }, "mime-db": { "version": "1.37.0", @@ -6474,6 +7025,12 @@ "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", "dev": true }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -6510,6 +7067,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", @@ -6610,8 +7173,7 @@ "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "optional": true + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "node-forge": { "version": "0.7.4", @@ -6935,7 +7497,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "optional": true, "requires": { "mimic-fn": "^2.1.0" } @@ -7036,6 +7597,12 @@ "lcid": "^1.0.0" } }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -7088,6 +7655,15 @@ "release-zalgo": "^1.0.0" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -7321,7 +7897,6 @@ "version": "6.8.8", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", - "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -7341,8 +7916,7 @@ "@types/node": { "version": "10.17.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.11.tgz", - "integrity": "sha512-dNd2pp8qTzzNLAs3O8nH3iU9DG9866KHq9L3ISPB7DOGERZN81nW/5/g/KzMJpCU8jrbCiMRBzV9/sCEdRosig==", - "optional": true + "integrity": "sha512-dNd2pp8qTzzNLAs3O8nH3iU9DG9866KHq9L3ISPB7DOGERZN81nW/5/g/KzMJpCU8jrbCiMRBzV9/sCEdRosig==" } } }, @@ -7592,6 +8166,12 @@ } } }, + "regexpp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "dev": true + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -7865,6 +8445,16 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -7942,6 +8532,15 @@ "glob": "^7.0.5" } }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, "run-sequence": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.2.2.tgz", @@ -7952,6 +8551,15 @@ "gulp-util": "*" } }, + "rxjs": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8121,6 +8729,34 @@ "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, "snakeize": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", @@ -8404,7 +9040,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", - "optional": true, "requires": { "stubs": "^3.0.0" } @@ -8505,8 +9140,7 @@ "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", - "optional": true + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" }, "supports-color": { "version": "2.0.0", @@ -8530,6 +9164,70 @@ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", "dev": true }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "teeny-request": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-5.3.1.tgz", @@ -8582,6 +9280,12 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "textextensions": { "version": "1.0.2", "resolved": "http://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", @@ -8606,6 +9310,12 @@ "thenify": ">= 3.1.0 < 4" } }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, "through2": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", @@ -8693,6 +9403,15 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -9014,6 +9733,12 @@ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -9255,6 +9980,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "v8flags": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", @@ -9538,6 +10269,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -9559,6 +10296,15 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "write-file-atomic": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", @@ -9582,8 +10328,7 @@ "xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "optional": true + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, "xml-name-validator": { "version": "3.0.0", @@ -9617,8 +10362,7 @@ "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "optional": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { "version": "13.2.4", diff --git a/package.json b/package.json index a844be1d36..fd3eca8c42 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,14 @@ "scripts": { "build": "gulp build", "prepare": "npm run build", - "lint": "run-p lint:src lint:unit lint:integration", + "lint": "run-p lint:src lint:test", "test": "run-s lint test:unit", "integration": "run-s build test:integration", "test:unit": "mocha test/unit/*.spec.ts --require ts-node/register", "test:integration": "mocha test/integration/*.ts --slow 5000 --timeout 20000 --require ts-node/register", "test:coverage": "nyc npm run test:unit", - "lint:src": "tslint --format stylish -p tsconfig.json", - "lint:unit": "tslint -c tslint-test.json --format stylish test/unit/*.ts test/unit/**/*.ts", - "lint:integration": "tslint -c tslint-test.json --format stylish test/integration/*.ts", + "lint:src": "eslint src/ --ext .ts", + "lint:test": "eslint test/ --ext .ts", "apidocs": "node docgen/generate-docs.js --api node" }, "nyc": { @@ -82,12 +81,15 @@ "@types/scrypt": "^6.0.0", "@types/sinon": "^4.1.3", "@types/sinon-chai": "^2.7.27", + "@typescript-eslint/eslint-plugin": "^2.20.0", + "@typescript-eslint/parser": "^2.20.0", "bcrypt": "^3.0.0", "chai": "^3.5.0", "chai-as-promised": "^6.0.0", "chalk": "^1.1.3", "child-process-promise": "^2.2.1", "del": "^2.2.1", + "eslint": "^6.8.0", "firebase-token-generator": "^2.0.0", "gulp": "^4.0.2", "gulp-header": "^1.8.8", @@ -109,7 +111,6 @@ "sinon": "^4.5.0", "sinon-chai": "^2.14.0", "ts-node": "^3.3.0", - "tslint": "^5.17.0", "typedoc": "^0.15.0", "typescript": "^3.7.3", "yargs": "^13.2.2" diff --git a/src/auth/action-code-settings-builder.ts b/src/auth/action-code-settings-builder.ts index 0961722850..3b1441e3fe 100644 --- a/src/auth/action-code-settings-builder.ts +++ b/src/auth/action-code-settings-builder.ts @@ -68,7 +68,7 @@ export class ActionCodeSettingsBuilder { throw new FirebaseAuthError( AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings" must be a non-null object.', - ); + ); } if (typeof actionCodeSettings.url === 'undefined') { throw new FirebaseAuthError( @@ -84,8 +84,8 @@ export class ActionCodeSettingsBuilder { if (typeof actionCodeSettings.handleCodeInApp !== 'undefined' && !validator.isBoolean(actionCodeSettings.handleCodeInApp)) { throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_ARGUMENT, - '"ActionCodeSettings.handleCodeInApp" must be a boolean.', + AuthClientErrorCode.INVALID_ARGUMENT, + '"ActionCodeSettings.handleCodeInApp" must be a boolean.', ); } this.canHandleCodeInApp = actionCodeSettings.handleCodeInApp || false; diff --git a/src/auth/auth-api-request.ts b/src/auth/auth-api-request.ts index 3b3f7a7f21..e4ae467369 100755 --- a/src/auth/auth-api-request.ts +++ b/src/auth/auth-api-request.ts @@ -135,7 +135,7 @@ class AuthResourceUrlBuilder { if (!validator.isNonEmptyString(projectId)) { throw new FirebaseAuthError( AuthClientErrorCode.INVALID_CREDENTIAL, - 'Failed to determine project ID for Auth. Initialize the ' + 'Failed to determine project ID for Auth. Initialize the ' + 'SDK with service account credentials or set project ID as an app option. ' + 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.', ); @@ -379,8 +379,8 @@ function validateCreateEditRequest(request: any, uploadAccountRequest: boolean = throw new FirebaseAuthError( AuthClientErrorCode.FORBIDDEN_CLAIM, invalidClaims.length > 1 ? - `Developer claims "${invalidClaims.join('", "')}" are reserved and cannot be specified.` : - `Developer claim "${invalidClaims[0]}" is reserved and cannot be specified.`, + `Developer claims "${invalidClaims.join('", "')}" are reserved and cannot be specified.` : + `Developer claim "${invalidClaims[0]}" is reserved and cannot be specified.`, ); } // Check claims payload does not exceed maxmimum size. @@ -416,26 +416,26 @@ function validateCreateEditRequest(request: any, uploadAccountRequest: boolean = /** Instantiates the createSessionCookie endpoint settings. */ export const FIREBASE_AUTH_CREATE_SESSION_COOKIE = new ApiSettings(':createSessionCookie', 'POST') - // Set request validator. - .setRequestValidator((request: any) => { - // Validate the ID token is a non-empty string. - if (!validator.isNonEmptyString(request.idToken)) { - throw new FirebaseAuthError(AuthClientErrorCode.INVALID_ID_TOKEN); - } - // Validate the custom session cookie duration. - if (!validator.isNumber(request.validDuration) || + // Set request validator. + .setRequestValidator((request: any) => { + // Validate the ID token is a non-empty string. + if (!validator.isNonEmptyString(request.idToken)) { + throw new FirebaseAuthError(AuthClientErrorCode.INVALID_ID_TOKEN); + } + // Validate the custom session cookie duration. + if (!validator.isNumber(request.validDuration) || request.validDuration < MIN_SESSION_COOKIE_DURATION_SECS || request.validDuration > MAX_SESSION_COOKIE_DURATION_SECS) { - throw new FirebaseAuthError(AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION); - } - }) - // Set response validator. - .setResponseValidator((response: any) => { - // Response should always contain the session cookie. - if (!validator.isNonEmptyString(response.sessionCookie)) { - throw new FirebaseAuthError(AuthClientErrorCode.INTERNAL_ERROR); - } - }); + throw new FirebaseAuthError(AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION); + } + }) + // Set response validator. + .setResponseValidator((response: any) => { + // Response should always contain the session cookie. + if (!validator.isNonEmptyString(response.sessionCookie)) { + throw new FirebaseAuthError(AuthClientErrorCode.INTERNAL_ERROR); + } + }); /** Instantiates the uploadAccount endpoint settings. */ @@ -505,8 +505,8 @@ export const FIREBASE_AUTH_SET_ACCOUNT_INFO = new ApiSettings('/accounts:update' // Throw error when tenantId is passed in POST body. if (typeof request.tenantId !== 'undefined') { throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_ARGUMENT, - '"tenantId" is an invalid "UpdateRequest" property.'); + AuthClientErrorCode.INVALID_ARGUMENT, + '"tenantId" is an invalid "UpdateRequest" property.'); } validateCreateEditRequest(request); }) @@ -542,8 +542,8 @@ export const FIREBASE_AUTH_SIGN_UP_NEW_USER = new ApiSettings('/accounts', 'POST // Throw error when tenantId is passed in POST body. if (typeof request.tenantId !== 'undefined') { throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_ARGUMENT, - '"tenantId" is an invalid "CreateRequest" property.'); + AuthClientErrorCode.INVALID_ARGUMENT, + '"tenantId" is an invalid "CreateRequest" property.'); } validateCreateEditRequest(request); }) @@ -757,7 +757,7 @@ export abstract class AbstractAuthRequestHandler { validDuration: expiresIn / 1000, }; return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_CREATE_SESSION_COOKIE, request) - .then((response: any) => response.sessionCookie); + .then((response: any) => response.sessionCookie); } /** @@ -825,8 +825,8 @@ export abstract class AbstractAuthRequestHandler { * and no page token are returned. */ public downloadAccount( - maxResults: number = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE, - pageToken?: string): Promise<{users: object[], nextPageToken?: string}> { + maxResults: number = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE, + pageToken?: string): Promise<{users: object[], nextPageToken?: string}> { // Construct request. const request = { maxResults, @@ -837,13 +837,13 @@ export abstract class AbstractAuthRequestHandler { delete request.nextPageToken; } return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_DOWNLOAD_ACCOUNT, request) - .then((response: any) => { - // No more users available. - if (!response.users) { - response.users = []; - } - return response as {users: object[], nextPageToken?: string}; - }); + .then((response: any) => { + // No more users available. + if (!response.users) { + response.users = []; + } + return response as {users: object[], nextPageToken?: string}; + }); } /** @@ -860,7 +860,7 @@ export abstract class AbstractAuthRequestHandler { * of failed uploads and their corresponding errors. */ public uploadAccount( - users: UserImportRecord[], options?: UserImportOptions): Promise { + users: UserImportRecord[], options?: UserImportOptions): Promise { // This will throw if any error is detected in the hash options. // For errors in the list of users, this will not throw and will report the errors and the // corresponding user index in the user import generated response below. @@ -938,9 +938,9 @@ export abstract class AbstractAuthRequestHandler { customAttributes: JSON.stringify(customUserClaims), }; return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_SET_ACCOUNT_INFO, request) - .then((response: any) => { - return response.localId as string; - }); + .then((response: any) => { + return response.localId as string; + }); } /** @@ -1015,9 +1015,9 @@ export abstract class AbstractAuthRequestHandler { delete request.disabled; } return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_SET_ACCOUNT_INFO, request) - .then((response: any) => { - return response.localId as string; - }); + .then((response: any) => { + return response.localId as string; + }); } /** @@ -1044,9 +1044,9 @@ export abstract class AbstractAuthRequestHandler { validSince: Math.ceil(new Date().getTime() / 1000), }; return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_SET_ACCOUNT_INFO, request) - .then((response: any) => { - return response.localId as string; - }); + .then((response: any) => { + return response.localId as string; + }); } /** @@ -1098,8 +1098,8 @@ export abstract class AbstractAuthRequestHandler { * @return {Promise} A promise that resolves with the email action link. */ public getEmailActionLink( - requestType: string, email: string, - actionCodeSettings?: ActionCodeSettings): Promise { + requestType: string, email: string, + actionCodeSettings?: ActionCodeSettings): Promise { let request = {requestType, email, returnOobLink: true}; // ActionCodeSettings required for email link sign-in to determine the url where the sign-in will // be completed. @@ -1153,8 +1153,8 @@ export abstract class AbstractAuthRequestHandler { * configuration and no page token are returned. */ public listOAuthIdpConfigs( - maxResults: number = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE, - pageToken?: string): Promise { + maxResults: number = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE, + pageToken?: string): Promise { const request: {pageSize: number, pageToken?: string} = { pageSize: maxResults, }; @@ -1163,13 +1163,13 @@ export abstract class AbstractAuthRequestHandler { request.pageToken = pageToken; } return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_OAUTH_IDP_CONFIGS, request) - .then((response: any) => { - if (!response.oauthIdpConfigs) { - response.oauthIdpConfigs = []; - delete response.nextPageToken; - } - return response as {oauthIdpConfigs: object[], nextPageToken?: string}; - }); + .then((response: any) => { + if (!response.oauthIdpConfigs) { + response.oauthIdpConfigs = []; + delete response.nextPageToken; + } + return response as {oauthIdpConfigs: object[], nextPageToken?: string}; + }); } /** @@ -1224,7 +1224,7 @@ export abstract class AbstractAuthRequestHandler { * configuration. */ public updateOAuthIdpConfig( - providerId: string, options: OIDCUpdateAuthProviderRequest): Promise { + providerId: string, options: OIDCUpdateAuthProviderRequest): Promise { if (!OIDCConfig.isProviderId(providerId)) { return Promise.reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID)); } @@ -1275,8 +1275,8 @@ export abstract class AbstractAuthRequestHandler { * configuration and no page token are returned. */ public listInboundSamlConfigs( - maxResults: number = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE, - pageToken?: string): Promise { + maxResults: number = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE, + pageToken?: string): Promise { const request: {pageSize: number, pageToken?: string} = { pageSize: maxResults, }; @@ -1285,13 +1285,13 @@ export abstract class AbstractAuthRequestHandler { request.pageToken = pageToken; } return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_INBOUND_SAML_CONFIGS, request) - .then((response: any) => { - if (!response.inboundSamlConfigs) { - response.inboundSamlConfigs = []; - delete response.nextPageToken; - } - return response as {inboundSamlConfigs: object[], nextPageToken?: string}; - }); + .then((response: any) => { + if (!response.inboundSamlConfigs) { + response.inboundSamlConfigs = []; + delete response.nextPageToken; + } + return response as {inboundSamlConfigs: object[], nextPageToken?: string}; + }); } /** @@ -1347,7 +1347,7 @@ export abstract class AbstractAuthRequestHandler { * configuration. */ public updateInboundSamlConfig( - providerId: string, options: SAMLUpdateAuthProviderRequest): Promise { + providerId: string, options: SAMLUpdateAuthProviderRequest): Promise { if (!SAMLConfig.isProviderId(providerId)) { return Promise.reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID)); } @@ -1381,8 +1381,8 @@ export abstract class AbstractAuthRequestHandler { * @return {Promise} A promise that resolves with the response. */ protected invokeRequestHandler( - urlBuilder: AuthResourceUrlBuilder, apiSettings: ApiSettings, - requestData: object, additionalResourceParams?: object): Promise { + urlBuilder: AuthResourceUrlBuilder, apiSettings: ApiSettings, + requestData: object, additionalResourceParams?: object): Promise { return urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams) .then((url) => { // Validate request. @@ -1457,33 +1457,33 @@ export abstract class AbstractAuthRequestHandler { /** Instantiates the getTenant endpoint settings. */ const GET_TENANT = new ApiSettings('/tenants/{tenantId}', 'GET') - // Set response validator. - .setResponseValidator((response: any) => { - // Response should always contain at least the tenant name. - if (!validator.isNonEmptyString(response.name)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - 'INTERNAL ASSERT FAILED: Unable to get tenant', - ); - } - }); +// Set response validator. + .setResponseValidator((response: any) => { + // Response should always contain at least the tenant name. + if (!validator.isNonEmptyString(response.name)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INTERNAL_ERROR, + 'INTERNAL ASSERT FAILED: Unable to get tenant', + ); + } + }); /** Instantiates the deleteTenant endpoint settings. */ const DELETE_TENANT = new ApiSettings('/tenants/{tenantId}', 'DELETE'); /** Instantiates the updateTenant endpoint settings. */ const UPDATE_TENANT = new ApiSettings('/tenants/{tenantId}?updateMask={updateMask}', 'PATCH') - // Set response validator. - .setResponseValidator((response: any) => { - // Response should always contain at least the tenant name. - if (!validator.isNonEmptyString(response.name) || +// Set response validator. + .setResponseValidator((response: any) => { + // Response should always contain at least the tenant name. + if (!validator.isNonEmptyString(response.name) || !Tenant.getTenantIdFromResourceName(response.name)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - 'INTERNAL ASSERT FAILED: Unable to update tenant', - ); - } - }); + throw new FirebaseAuthError( + AuthClientErrorCode.INTERNAL_ERROR, + 'INTERNAL ASSERT FAILED: Unable to update tenant', + ); + } + }); /** Instantiates the listTenants endpoint settings. */ const LIST_TENANTS = new ApiSettings('/tenants', 'GET') @@ -1508,17 +1508,17 @@ const LIST_TENANTS = new ApiSettings('/tenants', 'GET') /** Instantiates the createTenant endpoint settings. */ const CREATE_TENANT = new ApiSettings('/tenants', 'POST') - // Set response validator. - .setResponseValidator((response: any) => { - // Response should always contain at least the tenant name. - if (!validator.isNonEmptyString(response.name) || +// Set response validator. + .setResponseValidator((response: any) => { + // Response should always contain at least the tenant name. + if (!validator.isNonEmptyString(response.name) || !Tenant.getTenantIdFromResourceName(response.name)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - 'INTERNAL ASSERT FAILED: Unable to create new tenant', - ); - } - }); + throw new FirebaseAuthError( + AuthClientErrorCode.INTERNAL_ERROR, + 'INTERNAL ASSERT FAILED: Unable to create new tenant', + ); + } + }); /** @@ -1585,8 +1585,8 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler { * and no page token are returned. */ public listTenants( - maxResults: number = MAX_LIST_TENANT_PAGE_SIZE, - pageToken?: string): Promise<{tenants: TenantServerResponse[], nextPageToken?: string}> { + maxResults: number = MAX_LIST_TENANT_PAGE_SIZE, + pageToken?: string): Promise<{tenants: TenantServerResponse[], nextPageToken?: string}> { const request = { pageSize: maxResults, pageToken, @@ -1596,13 +1596,13 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler { delete request.pageToken; } return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, LIST_TENANTS, request) - .then((response: any) => { - if (!response.tenants) { - response.tenants = []; - delete response.nextPageToken; - } - return response as {tenants: TenantServerResponse[], nextPageToken?: string}; - }); + .then((response: any) => { + if (!response.tenants) { + response.tenants = []; + delete response.nextPageToken; + } + return response as {tenants: TenantServerResponse[], nextPageToken?: string}; + }); } /** @@ -1715,14 +1715,14 @@ export class TenantAwareAuthRequestHandler extends AbstractAuthRequestHandler { * of failed uploads and their corresponding errors. */ public uploadAccount( - users: UserImportRecord[], options?: UserImportOptions): Promise { + users: UserImportRecord[], options?: UserImportOptions): Promise { // Add additional check to match tenant ID of imported user records. users.forEach((user: UserImportRecord, index: number) => { if (validator.isNonEmptyString(user.tenantId) && user.tenantId !== this.tenantId) { throw new FirebaseAuthError( - AuthClientErrorCode.MISMATCHING_TENANT_ID, - `UserRecord of index "${index}" has mismatching tenant ID "${user.tenantId}"`); + AuthClientErrorCode.MISMATCHING_TENANT_ID, + `UserRecord of index "${index}" has mismatching tenant ID "${user.tenantId}"`); } }); return super.uploadAccount(users, options); diff --git a/src/auth/auth-config.ts b/src/auth/auth-config.ts index 0249769128..9842df1023 100755 --- a/src/auth/auth-config.ts +++ b/src/auth/auth-config.ts @@ -284,8 +284,8 @@ export class SAMLConfig implements SAMLAuthProviderConfig { * @return {?SAMLConfigServerRequest} The resulting server request or null if not valid. */ public static buildServerRequest( - options: SAMLAuthProviderRequest, - ignoreMissingFields: boolean = false): SAMLConfigServerRequest | null { + options: SAMLAuthProviderRequest, + ignoreMissingFields: boolean = false): SAMLConfigServerRequest | null { const makeRequest = validator.isNonNullObject(options) && (options.providerId || ignoreMissingFields); if (!makeRequest) { @@ -409,7 +409,7 @@ export class SAMLConfig implements SAMLAuthProviderConfig { !validator.isNonEmptyString(options.rpEntityId)) { throw new FirebaseAuthError( !options.rpEntityId ? AuthClientErrorCode.MISSING_SAML_RELYING_PARTY_CONFIG : - AuthClientErrorCode.INVALID_CONFIG, + AuthClientErrorCode.INVALID_CONFIG, '"SAMLAuthProviderConfig.rpEntityId" must be a valid non-empty string.', ); } @@ -544,8 +544,8 @@ export class OIDCConfig implements OIDCAuthProviderConfig { * @return {?OIDCConfigServerRequest} The resulting server request or null if not valid. */ public static buildServerRequest( - options: OIDCAuthProviderRequest, - ignoreMissingFields: boolean = false): OIDCConfigServerRequest | null { + options: OIDCAuthProviderRequest, + ignoreMissingFields: boolean = false): OIDCConfigServerRequest | null { const makeRequest = validator.isNonNullObject(options) && (options.providerId || ignoreMissingFields); if (!makeRequest) { diff --git a/src/auth/auth.ts b/src/auth/auth.ts index eddea69cb3..434481ea89 100755 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -332,7 +332,7 @@ export class BaseAuth { * of failed uploads and their corresponding errors. */ public importUsers( - users: UserImportRecord[], options?: UserImportOptions): Promise { + users: UserImportRecord[], options?: UserImportOptions): Promise { return this.authRequestHandler.uploadAccount(users, options); } @@ -348,7 +348,7 @@ export class BaseAuth { * @return {Promise} A promise that resolves on success with the created session cookie. */ public createSessionCookie( - idToken: string, sessionCookieOptions: SessionCookieOptions): Promise { + idToken: string, sessionCookieOptions: SessionCookieOptions): Promise { // Return rejected promise if expiresIn is not available. if (!validator.isNonNullObject(sessionCookieOptions) || !validator.isNumber(sessionCookieOptions.expiresIn)) { @@ -371,7 +371,7 @@ export class BaseAuth { * verification. */ public verifySessionCookie( - sessionCookie: string, checkRevoked: boolean = false): Promise { + sessionCookie: string, checkRevoked: boolean = false): Promise { return this.sessionCookieVerifier.verifyJWT(sessionCookie) .then((decodedIdToken: DecodedIdToken) => { // Whether to check if the token was revoked. @@ -475,9 +475,9 @@ export class BaseAuth { }); } return Promise.reject( - new FirebaseAuthError( - AuthClientErrorCode.INVALID_ARGUMENT, - `"AuthProviderConfigFilter.type" must be either "saml' or "oidc"`)); + new FirebaseAuthError( + AuthClientErrorCode.INVALID_ARGUMENT, + `"AuthProviderConfigFilter.type" must be either "saml' or "oidc"`)); } /** @@ -526,7 +526,7 @@ export class BaseAuth { * @return {Promise} A promise that resolves with the updated provider configuration. */ public updateProviderConfig( - providerId: string, updatedConfig: UpdateAuthProviderRequest): Promise { + providerId: string, updatedConfig: UpdateAuthProviderRequest): Promise { if (!validator.isNonNullObject(updatedConfig)) { return Promise.reject(new FirebaseAuthError( AuthClientErrorCode.INVALID_CONFIG, @@ -585,7 +585,7 @@ export class BaseAuth { * verification. */ private verifyDecodedJWTNotRevoked( - decodedIdToken: DecodedIdToken, revocationErrorInfo: ErrorInfo): Promise { + decodedIdToken: DecodedIdToken, revocationErrorInfo: ErrorInfo): Promise { // Get tokens valid after time for the corresponding user. return this.getUser(decodedIdToken.sub) .then((user: UserRecord) => { @@ -662,7 +662,7 @@ export class TenantAwareAuth extends BaseAuth { * @return {Promise} A promise that resolves on success with the created session cookie. */ public createSessionCookie( - idToken: string, sessionCookieOptions: SessionCookieOptions): Promise { + idToken: string, sessionCookieOptions: SessionCookieOptions): Promise { // Validate arguments before processing. if (!validator.isNonEmptyString(idToken)) { return Promise.reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_ID_TOKEN)); @@ -691,7 +691,7 @@ export class TenantAwareAuth extends BaseAuth { * verification. */ public verifySessionCookie( - sessionCookie: string, checkRevoked: boolean = false): Promise { + sessionCookie: string, checkRevoked: boolean = false): Promise { return super.verifySessionCookie(sessionCookie, checkRevoked) .then((decodedClaims) => { if (decodedClaims.firebase.tenant !== this.tenantId) { diff --git a/src/auth/tenant-manager.ts b/src/auth/tenant-manager.ts index 5af985a04a..f92e30fb26 100644 --- a/src/auth/tenant-manager.ts +++ b/src/auth/tenant-manager.ts @@ -86,8 +86,8 @@ export class TenantManager { * empty list of tenants and no page token are returned. */ public listTenants( - maxResults?: number, - pageToken?: string): Promise { + maxResults?: number, + pageToken?: string): Promise { return this.authRequestHandler.listTenants(maxResults, pageToken) .then((response: {tenants: TenantServerResponse[], nextPageToken?: string}) => { // List of tenants to return. diff --git a/src/auth/tenant.ts b/src/auth/tenant.ts index 8fda7d3c7f..4f947aff74 100755 --- a/src/auth/tenant.ts +++ b/src/auth/tenant.ts @@ -62,7 +62,7 @@ export class Tenant { * @return {object} The equivalent server request. */ public static buildServerRequest( - tenantOptions: TenantOptions, createRequest: boolean): TenantOptionsServerRequest { + tenantOptions: TenantOptions, createRequest: boolean): TenantOptionsServerRequest { Tenant.validate(tenantOptions, createRequest); let request: TenantOptionsServerRequest = {}; if (typeof tenantOptions.emailSignInConfig !== 'undefined') { diff --git a/src/auth/token-generator.ts b/src/auth/token-generator.ts index 553874c1b9..f2949a7051 100644 --- a/src/auth/token-generator.ts +++ b/src/auth/token-generator.ts @@ -170,8 +170,8 @@ export class IAMSigner implements CryptoSigner { throw FirebaseAuthError.fromServerError(errorCode, errorMsg, error); } throw new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - 'Error returned from server: ' + error + '. Additionally, an ' + + AuthClientErrorCode.INTERNAL_ERROR, + 'Error returned from server: ' + error + '. Additionally, an ' + 'internal error occurred while attempting to extract the ' + 'errorcode from the error.', ); diff --git a/src/auth/token-verifier.ts b/src/auth/token-verifier.ts index 6a72f1e8a5..cd5138d63f 100644 --- a/src/auth/token-verifier.ts +++ b/src/auth/token-verifier.ts @@ -261,8 +261,8 @@ export class FirebaseTokenVerifier { // is actually correct. if (typeof decodedToken === 'string') { return reject(new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - "Unexpected decodedToken. Expected an object but got a string: '" + decodedToken + "'", + AuthClientErrorCode.INTERNAL_ERROR, + "Unexpected decodedToken. Expected an object but got a string: '" + decodedToken + "'", )); } else { const decodedIdToken = (decodedToken as DecodedIdToken); diff --git a/src/auth/user-import-builder.ts b/src/auth/user-import-builder.ts index 396dfa49da..4e22b5a1ef 100644 --- a/src/auth/user-import-builder.ts +++ b/src/auth/user-import-builder.ts @@ -145,7 +145,7 @@ function getNumberField(obj: any, key: string): number { * @return {UploadAccountUser} The corresponding UploadAccountUser to return. */ function populateUploadAccountUser( - user: UserImportRecord, userValidator?: ValidatorFunction): UploadAccountUser { + user: UserImportRecord, userValidator?: ValidatorFunction): UploadAccountUser { const result: UploadAccountUser = { localId: user.uid, email: user.email, @@ -231,9 +231,9 @@ export class UserImportBuilder { * @constructor */ constructor( - users: UserImportRecord[], - options?: UserImportOptions, - userRequestValidator?: ValidatorFunction) { + users: UserImportRecord[], + options?: UserImportOptions, + userRequestValidator?: ValidatorFunction) { this.requiresHashOptions = false; this.validatedUsers = []; this.userImportResultErrors = []; @@ -261,7 +261,7 @@ export class UserImportBuilder { * uploadAccount response. */ public buildResponse( - failedUploads: Array<{index: number, message: string}>): UserImportResult { + failedUploads: Array<{index: number, message: string}>): UserImportResult { // Initialize user import result. const importResult: UserImportResult = { successCount: this.validatedUsers.length, @@ -296,7 +296,7 @@ export class UserImportBuilder { * @return {UploadAccountOptions} The populated UploadAccount options. */ private populateOptions( - options: UserImportOptions | undefined, requiresHashOptions: boolean): UploadAccountOptions { + options: UserImportOptions | undefined, requiresHashOptions: boolean): UploadAccountOptions { let populatedOptions: UploadAccountOptions; if (!requiresHashOptions) { return {}; @@ -323,152 +323,152 @@ export class UserImportBuilder { let rounds: number; switch (options.hash.algorithm) { - case 'HMAC_SHA512': - case 'HMAC_SHA256': - case 'HMAC_SHA1': - case 'HMAC_MD5': - if (!validator.isBuffer(options.hash.key)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_KEY, - `A non-empty "hash.key" byte buffer must be provided for ` + + case 'HMAC_SHA512': + case 'HMAC_SHA256': + case 'HMAC_SHA1': + case 'HMAC_MD5': + if (!validator.isBuffer(options.hash.key)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_KEY, + `A non-empty "hash.key" byte buffer must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - signerKey: utils.toWebSafeBase64(options.hash.key), - }; - break; - - case 'MD5': - case 'SHA1': - case 'SHA256': - case 'SHA512': - // MD5 is [0,8192] but SHA1, SHA256, and SHA512 are [1,8192] - rounds = getNumberField(options.hash, 'rounds'); - const minRounds = options.hash.algorithm === 'MD5' ? 0 : 1; - if (isNaN(rounds) || rounds < minRounds || rounds > 8192) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_ROUNDS, - `A valid "hash.rounds" number between ${minRounds} and 8192 must be provided for ` + + ); + } + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + signerKey: utils.toWebSafeBase64(options.hash.key), + }; + break; + + case 'MD5': + case 'SHA1': + case 'SHA256': + case 'SHA512': + // MD5 is [0,8192] but SHA1, SHA256, and SHA512 are [1,8192] + rounds = getNumberField(options.hash, 'rounds'); + const minRounds = options.hash.algorithm === 'MD5' ? 0 : 1; + if (isNaN(rounds) || rounds < minRounds || rounds > 8192) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_ROUNDS, + `A valid "hash.rounds" number between ${minRounds} and 8192 must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - rounds, - }; - break; - - case 'PBKDF_SHA1': - case 'PBKDF2_SHA256': - rounds = getNumberField(options.hash, 'rounds'); - if (isNaN(rounds) || rounds < 0 || rounds > 120000) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_ROUNDS, - `A valid "hash.rounds" number between 0 and 120000 must be provided for ` + + ); + } + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + rounds, + }; + break; + + case 'PBKDF_SHA1': + case 'PBKDF2_SHA256': + rounds = getNumberField(options.hash, 'rounds'); + if (isNaN(rounds) || rounds < 0 || rounds > 120000) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_ROUNDS, + `A valid "hash.rounds" number between 0 and 120000 must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - rounds, - }; - break; - - case 'SCRYPT': - if (!validator.isBuffer(options.hash.key)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_KEY, - `A "hash.key" byte buffer must be provided for ` + + ); + } + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + rounds, + }; + break; + + case 'SCRYPT': + if (!validator.isBuffer(options.hash.key)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_KEY, + `A "hash.key" byte buffer must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - rounds = getNumberField(options.hash, 'rounds'); - if (isNaN(rounds) || rounds <= 0 || rounds > 8) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_ROUNDS, - `A valid "hash.rounds" number between 1 and 8 must be provided for ` + + ); + } + rounds = getNumberField(options.hash, 'rounds'); + if (isNaN(rounds) || rounds <= 0 || rounds > 8) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_ROUNDS, + `A valid "hash.rounds" number between 1 and 8 must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - const memoryCost = getNumberField(options.hash, 'memoryCost'); - if (isNaN(memoryCost) || memoryCost <= 0 || memoryCost > 14) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_MEMORY_COST, - `A valid "hash.memoryCost" number between 1 and 14 must be provided for ` + + ); + } + const memoryCost = getNumberField(options.hash, 'memoryCost'); + if (isNaN(memoryCost) || memoryCost <= 0 || memoryCost > 14) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_MEMORY_COST, + `A valid "hash.memoryCost" number between 1 and 14 must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - if (typeof options.hash.saltSeparator !== 'undefined' && + ); + } + if (typeof options.hash.saltSeparator !== 'undefined' && !validator.isBuffer(options.hash.saltSeparator)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR, - `"hash.saltSeparator" must be a byte buffer.`, - ); - } - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - signerKey: utils.toWebSafeBase64(options.hash.key), - rounds, - memoryCost, - saltSeparator: utils.toWebSafeBase64(options.hash.saltSeparator || Buffer.from('')), - }; - break; - - case 'BCRYPT': - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - }; - break; - - case 'STANDARD_SCRYPT': - const cpuMemCost = getNumberField(options.hash, 'memoryCost'); - if (isNaN(cpuMemCost)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_MEMORY_COST, - `A valid "hash.memoryCost" number must be provided for ` + - `hash algorithm ${options.hash.algorithm}.`, - ); - } - const parallelization = getNumberField(options.hash, 'parallelization'); - if (isNaN(parallelization)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_PARALLELIZATION, - `A valid "hash.parallelization" number must be provided for ` + + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR, + `"hash.saltSeparator" must be a byte buffer.`, + ); + } + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + signerKey: utils.toWebSafeBase64(options.hash.key), + rounds, + memoryCost, + saltSeparator: utils.toWebSafeBase64(options.hash.saltSeparator || Buffer.from('')), + }; + break; + + case 'BCRYPT': + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + }; + break; + + case 'STANDARD_SCRYPT': + const cpuMemCost = getNumberField(options.hash, 'memoryCost'); + if (isNaN(cpuMemCost)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_MEMORY_COST, + `A valid "hash.memoryCost" number must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - const blockSize = getNumberField(options.hash, 'blockSize'); - if (isNaN(blockSize)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE, - `A valid "hash.blockSize" number must be provided for ` + + ); + } + const parallelization = getNumberField(options.hash, 'parallelization'); + if (isNaN(parallelization)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_PARALLELIZATION, + `A valid "hash.parallelization" number must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - const dkLen = getNumberField(options.hash, 'derivedKeyLength'); - if (isNaN(dkLen)) { - throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH, - `A valid "hash.derivedKeyLength" number must be provided for ` + + ); + } + const blockSize = getNumberField(options.hash, 'blockSize'); + if (isNaN(blockSize)) { + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE, + `A valid "hash.blockSize" number must be provided for ` + `hash algorithm ${options.hash.algorithm}.`, - ); - } - populatedOptions = { - hashAlgorithm: options.hash.algorithm, - cpuMemCost, - parallelization, - blockSize, - dkLen, - }; - break; - - default: + ); + } + const dkLen = getNumberField(options.hash, 'derivedKeyLength'); + if (isNaN(dkLen)) { throw new FirebaseAuthError( - AuthClientErrorCode.INVALID_HASH_ALGORITHM, - `Unsupported hash algorithm provider "${options.hash.algorithm}".`, + AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH, + `A valid "hash.derivedKeyLength" number must be provided for ` + + `hash algorithm ${options.hash.algorithm}.`, ); + } + populatedOptions = { + hashAlgorithm: options.hash.algorithm, + cpuMemCost, + parallelization, + blockSize, + dkLen, + }; + break; + + default: + throw new FirebaseAuthError( + AuthClientErrorCode.INVALID_HASH_ALGORITHM, + `Unsupported hash algorithm provider "${options.hash.algorithm}".`, + ); } return populatedOptions; } @@ -484,7 +484,7 @@ export class UserImportBuilder { * @return {UploadAccountUser[]} The populated uploadAccount users. */ private populateUsers( - users: UserImportRecord[], userValidator?: ValidatorFunction): UploadAccountUser[] { + users: UserImportRecord[], userValidator?: ValidatorFunction): UploadAccountUser[] { const populatedUsers: UploadAccountUser[] = []; users.forEach((user, index) => { try { diff --git a/src/auth/user-record.ts b/src/auth/user-record.ts index f8c3adafc7..28f63fc972 100644 --- a/src/auth/user-record.ts +++ b/src/auth/user-record.ts @@ -191,7 +191,7 @@ export class UserRecord { utils.addReadonlyGetter(this, 'passwordSalt', response.salt); try { utils.addReadonlyGetter( - this, 'customClaims', JSON.parse(response.customAttributes)); + this, 'customClaims', JSON.parse(response.customAttributes)); } catch (e) { // Ignore error. utils.addReadonlyGetter(this, 'customClaims', undefined); @@ -225,8 +225,8 @@ export class UserRecord { }; json.providerData = []; for (const entry of this.providerData) { - // Convert each provider data to json. - json.providerData.push(entry.toJSON()); + // Convert each provider data to json. + json.providerData.push(entry.toJSON()); } return json; } diff --git a/src/database/database.ts b/src/database/database.ts index 666447f4ae..c8b07f09fa 100644 --- a/src/database/database.ts +++ b/src/database/database.ts @@ -183,11 +183,11 @@ class DatabaseRulesClient { if (!validator.isNonEmptyString(source) && !validator.isBuffer(source) && !validator.isNonNullObject(source)) { - const error = new FirebaseDatabaseError({ - code: 'invalid-argument', - message: 'Source must be a non-empty string, Buffer or an object.', - }); - return Promise.reject(error); + const error = new FirebaseDatabaseError({ + code: 'invalid-argument', + message: 'Source must be a non-empty string, Buffer or an object.', + }); + return Promise.reject(error); } const req: HttpRequestConfig = { diff --git a/src/firebase-namespace.ts b/src/firebase-namespace.ts index 738fc0d4d7..f01d3861b2 100644 --- a/src/firebase-namespace.ts +++ b/src/firebase-namespace.ts @@ -182,10 +182,11 @@ export class FirebaseNamespaceInternals { * @param {AppHook} [appHook] Optional callback that handles app-related events like app creation and deletion. * @return {FirebaseServiceNamespace} The Firebase service's namespace. */ - public registerService(serviceName: string, - createService: FirebaseServiceFactory, - serviceProperties?: object, - appHook?: AppHook): FirebaseServiceNamespace { + public registerService( + serviceName: string, + createService: FirebaseServiceFactory, + serviceProperties?: object, + appHook?: AppHook): FirebaseServiceNamespace { let errorMessage; if (typeof serviceName === 'undefined') { errorMessage = `No service name provided. Service name must be a non-empty string.`; @@ -207,11 +208,9 @@ export class FirebaseNamespaceInternals { this.appHooks_[serviceName] = appHook; } - let serviceNamespace: FirebaseServiceNamespace; - // The service namespace is an accessor function which takes a FirebaseApp instance // or uses the default app if no FirebaseApp instance is provided - serviceNamespace = (appArg?: FirebaseApp) => { + const serviceNamespace: FirebaseServiceNamespace = (appArg?: FirebaseApp) => { if (typeof appArg === 'undefined') { appArg = this.app(); } diff --git a/src/messaging/messaging-api-request.ts b/src/messaging/messaging-api-request.ts index c9aee5cccd..9af1ff8571 100644 --- a/src/messaging/messaging-api-request.ts +++ b/src/messaging/messaging-api-request.ts @@ -83,13 +83,13 @@ export class FirebaseMessagingRequestHandler { // Return entire response. return response.data; }) - .catch((err) => { - if (err instanceof HttpError) { - throw createFirebaseError(err); - } - // Re-throw the error if it already has the proper format. - throw err; - }); + .catch((err) => { + if (err instanceof HttpError) { + throw createFirebaseError(err); + } + // Re-throw the error if it already has the proper format. + throw err; + }); } /** diff --git a/src/messaging/messaging-errors.ts b/src/messaging/messaging-errors.ts index 1fd1809aec..2d937d6f21 100644 --- a/src/messaging/messaging-errors.ts +++ b/src/messaging/messaging-errors.ts @@ -37,22 +37,22 @@ export function createFirebaseError(err: HttpError): FirebaseMessagingError { // Non-JSON response let error: {code: string, message: string}; switch (err.response.status) { - case 400: - error = MessagingClientErrorCode.INVALID_ARGUMENT; - break; - case 401: - case 403: - error = MessagingClientErrorCode.AUTHENTICATION_ERROR; - break; - case 500: - error = MessagingClientErrorCode.INTERNAL_ERROR; - break; - case 503: - error = MessagingClientErrorCode.SERVER_UNAVAILABLE; - break; - default: - // Treat non-JSON responses with unexpected status codes as unknown errors. - error = MessagingClientErrorCode.UNKNOWN_ERROR; + case 400: + error = MessagingClientErrorCode.INVALID_ARGUMENT; + break; + case 401: + case 403: + error = MessagingClientErrorCode.AUTHENTICATION_ERROR; + break; + case 500: + error = MessagingClientErrorCode.INTERNAL_ERROR; + break; + case 503: + error = MessagingClientErrorCode.SERVER_UNAVAILABLE; + break; + default: + // Treat non-JSON responses with unexpected status codes as unknown errors. + error = MessagingClientErrorCode.UNKNOWN_ERROR; } return new FirebaseMessagingError({ code: error.code, diff --git a/src/messaging/messaging-types.ts b/src/messaging/messaging-types.ts index 50bb3a4b37..bd25f164cb 100644 --- a/src/messaging/messaging-types.ts +++ b/src/messaging/messaging-types.ts @@ -402,8 +402,8 @@ function validateApnsFcmOptions(fcmOptions: ApnsFcmOptions | undefined) { if (typeof fcmOptions.imageUrl !== 'undefined' && !validator.isURL(fcmOptions.imageUrl)) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, - 'imageUrl must be a valid URL string'); + MessagingClientErrorCode.INVALID_PAYLOAD, + 'imageUrl must be a valid URL string'); } if (typeof fcmOptions.analyticsLabel !== 'undefined' && !validator.isString(fcmOptions.analyticsLabel)) { @@ -417,8 +417,8 @@ function validateApnsFcmOptions(fcmOptions: ApnsFcmOptions | undefined) { Object.keys(propertyMappings).forEach((key) => { if (key in fcmOptions && propertyMappings[key] in fcmOptions) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, - `Multiple specifications for ${key} in ApnsFcmOptions`); + MessagingClientErrorCode.INVALID_PAYLOAD, + `Multiple specifications for ${key} in ApnsFcmOptions`); } }); renameProperties(fcmOptions, propertyMappings); @@ -453,12 +453,12 @@ function validateNotification(notification: Notification | undefined) { return; } else if (!validator.isNonNullObject(notification)) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, 'notification must be a non-null object'); + MessagingClientErrorCode.INVALID_PAYLOAD, 'notification must be a non-null object'); } if (typeof notification.imageUrl !== 'undefined' && !validator.isURL(notification.imageUrl)) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, 'notification.imageUrl must be a valid URL string'); + MessagingClientErrorCode.INVALID_PAYLOAD, 'notification.imageUrl must be a valid URL string'); } const propertyMappings: {[key: string]: string} = { @@ -467,8 +467,8 @@ function validateNotification(notification: Notification | undefined) { Object.keys(propertyMappings).forEach((key) => { if (key in notification && propertyMappings[key] in notification) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, - `Multiple specifications for ${key} in Notification`); + MessagingClientErrorCode.INVALID_PAYLOAD, + `Multiple specifications for ${key} in Notification`); } }); renameProperties(notification, propertyMappings); @@ -694,8 +694,8 @@ function validateAndroidNotification(notification: AndroidNotification | undefin if (typeof notification.imageUrl !== 'undefined' && !validator.isURL(notification.imageUrl)) { throw new FirebaseMessagingError( - MessagingClientErrorCode.INVALID_PAYLOAD, - 'android.notification.imageUrl must be a valid URL string'); + MessagingClientErrorCode.INVALID_PAYLOAD, + 'android.notification.imageUrl must be a valid URL string'); } if (typeof notification.eventTimestamp !== 'undefined') { diff --git a/src/project-management/android-app.ts b/src/project-management/android-app.ts index 7676d1c603..e51ace8ba3 100644 --- a/src/project-management/android-app.ts +++ b/src/project-management/android-app.ts @@ -27,7 +27,7 @@ export class AndroidApp { private readonly requestHandler: ProjectManagementRequestHandler) { if (!validator.isNonEmptyString(appId)) { throw new FirebaseProjectManagementError( - 'invalid-argument', 'appId must be a non-empty string.'); + 'invalid-argument', 'appId must be a non-empty string.'); } this.resourceName = `projects/-/androidApps/${appId}`; @@ -35,30 +35,30 @@ export class AndroidApp { public getMetadata(): Promise { return this.requestHandler.getResource(this.resourceName) - .then((responseData: any) => { + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + 'getMetadata()\'s responseData must be a non-null object.'); + + const requiredFieldsList = ['name', 'appId', 'projectId', 'packageName']; + requiredFieldsList.forEach((requiredField) => { assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'getMetadata()\'s responseData must be a non-null object.'); - - const requiredFieldsList = ['name', 'appId', 'projectId', 'packageName']; - requiredFieldsList.forEach((requiredField) => { - assertServerResponse( - validator.isNonEmptyString(responseData[requiredField]), - responseData, - `getMetadata()\'s responseData.${requiredField} must be a non-empty string.`); - }); - - const metadata: AndroidAppMetadata = { - platform: AppPlatform.ANDROID, - resourceName: responseData.name, - appId: responseData.appId, - displayName: responseData.displayName || null, - projectId: responseData.projectId, - packageName: responseData.packageName, - }; - return metadata; + validator.isNonEmptyString(responseData[requiredField]), + responseData, + `getMetadata()\'s responseData.${requiredField} must be a non-empty string.`); }); + + const metadata: AndroidAppMetadata = { + platform: AppPlatform.ANDROID, + resourceName: responseData.name, + appId: responseData.appId, + displayName: responseData.displayName || null, + projectId: responseData.projectId, + packageName: responseData.packageName, + }; + return metadata; + }); } public setDisplayName(newDisplayName: string): Promise { @@ -67,35 +67,35 @@ export class AndroidApp { public getShaCertificates(): Promise { return this.requestHandler.getAndroidShaCertificates(this.resourceName) - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'getShaCertificates()\'s responseData must be a non-null object.'); + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + 'getShaCertificates()\'s responseData must be a non-null object.'); - if (!responseData.certificates) { - return []; - } + if (!responseData.certificates) { + return []; + } - assertServerResponse( - validator.isArray(responseData.certificates), - responseData, - '"certificates" field must be present in the getShaCertificates() response data.'); + assertServerResponse( + validator.isArray(responseData.certificates), + responseData, + '"certificates" field must be present in the getShaCertificates() response data.'); - const requiredFieldsList = ['name', 'shaHash']; + const requiredFieldsList = ['name', 'shaHash']; - return responseData.certificates.map((certificateJson: any) => { - requiredFieldsList.forEach((requiredField) => { - assertServerResponse( - validator.isNonEmptyString(certificateJson[requiredField]), - responseData, - `getShaCertificates()\'s responseData.certificates[].${requiredField} must be a ` + return responseData.certificates.map((certificateJson: any) => { + requiredFieldsList.forEach((requiredField) => { + assertServerResponse( + validator.isNonEmptyString(certificateJson[requiredField]), + responseData, + `getShaCertificates()\'s responseData.certificates[].${requiredField} must be a ` + `non-empty string.`); - }); - - return new ShaCertificate(certificateJson.shaHash, certificateJson.name); }); + + return new ShaCertificate(certificateJson.shaHash, certificateJson.name); }); + }); } public addShaCertificate(certificateToAdd: ShaCertificate): Promise { @@ -105,8 +105,8 @@ export class AndroidApp { public deleteShaCertificate(certificateToDelete: ShaCertificate): Promise { if (!certificateToDelete.resourceName) { throw new FirebaseProjectManagementError( - 'invalid-argument', - 'Specified certificate does not include a resourceName. (Use AndroidApp.getShaCertificates() to retrieve ' + + 'invalid-argument', + 'Specified certificate does not include a resourceName. (Use AndroidApp.getShaCertificates() to retrieve ' + 'certificates with a resourceName.'); } return this.requestHandler.deleteResource(certificateToDelete.resourceName); @@ -118,20 +118,20 @@ export class AndroidApp { */ public getConfig(): Promise { return this.requestHandler.getConfig(this.resourceName) - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'getConfig()\'s responseData must be a non-null object.'); - - const base64ConfigFileContents = responseData.configFileContents; - assertServerResponse( - validator.isBase64String(base64ConfigFileContents), - responseData, - `getConfig()\'s responseData.configFileContents must be a base64 string.`); - - return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8'); - }); + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + 'getConfig()\'s responseData must be a non-null object.'); + + const base64ConfigFileContents = responseData.configFileContents; + assertServerResponse( + validator.isBase64String(base64ConfigFileContents), + responseData, + `getConfig()\'s responseData.configFileContents must be a base64 string.`); + + return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8'); + }); } } @@ -153,7 +153,7 @@ export class ShaCertificate { this.certType = 'sha256'; } else { throw new FirebaseProjectManagementError( - 'invalid-argument', 'shaHash must be either a sha256 hash or a sha1 hash.'); + 'invalid-argument', 'shaHash must be either a sha256 hash or a sha1 hash.'); } } } diff --git a/src/project-management/ios-app.ts b/src/project-management/ios-app.ts index f9b553d6df..46672a9306 100644 --- a/src/project-management/ios-app.ts +++ b/src/project-management/ios-app.ts @@ -27,7 +27,7 @@ export class IosApp { private readonly requestHandler: ProjectManagementRequestHandler) { if (!validator.isNonEmptyString(appId)) { throw new FirebaseProjectManagementError( - 'invalid-argument', 'appId must be a non-empty string.'); + 'invalid-argument', 'appId must be a non-empty string.'); } this.resourceName = `projects/-/iosApps/${appId}`; @@ -35,30 +35,30 @@ export class IosApp { public getMetadata(): Promise { return this.requestHandler.getResource(this.resourceName) - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'getMetadata()\'s responseData must be a non-null object.'); - - const requiredFieldsList = ['name', 'appId', 'projectId', 'bundleId']; - requiredFieldsList.forEach((requiredField) => { - assertServerResponse( - validator.isNonEmptyString(responseData[requiredField]), - responseData, - `getMetadata()\'s responseData.${requiredField} must be a non-empty string.`); - }); + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + 'getMetadata()\'s responseData must be a non-null object.'); - const metadata: IosAppMetadata = { - platform: AppPlatform.IOS, - resourceName: responseData.name, - appId: responseData.appId, - displayName: responseData.displayName || null, - projectId: responseData.projectId, - bundleId: responseData.bundleId, - }; - return metadata; + const requiredFieldsList = ['name', 'appId', 'projectId', 'bundleId']; + requiredFieldsList.forEach((requiredField) => { + assertServerResponse( + validator.isNonEmptyString(responseData[requiredField]), + responseData, + `getMetadata()\'s responseData.${requiredField} must be a non-empty string.`); }); + + const metadata: IosAppMetadata = { + platform: AppPlatform.IOS, + resourceName: responseData.name, + appId: responseData.appId, + displayName: responseData.displayName || null, + projectId: responseData.projectId, + bundleId: responseData.bundleId, + }; + return metadata; + }); } public setDisplayName(newDisplayName: string): Promise { @@ -71,19 +71,19 @@ export class IosApp { */ public getConfig(): Promise { return this.requestHandler.getConfig(this.resourceName) - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'getConfig()\'s responseData must be a non-null object.'); + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + 'getConfig()\'s responseData must be a non-null object.'); - const base64ConfigFileContents = responseData.configFileContents; - assertServerResponse( - validator.isBase64String(base64ConfigFileContents), - responseData, - `getConfig()\'s responseData.configFileContents must be a base64 string.`); + const base64ConfigFileContents = responseData.configFileContents; + assertServerResponse( + validator.isBase64String(base64ConfigFileContents), + responseData, + `getConfig()\'s responseData.configFileContents must be a base64 string.`); - return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8'); - }); + return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8'); + }); } } diff --git a/src/project-management/project-management-api-request.ts b/src/project-management/project-management-api-request.ts index 14d533ddb0..6acd692cdd 100644 --- a/src/project-management/project-management-api-request.ts +++ b/src/project-management/project-management-api-request.ts @@ -43,11 +43,11 @@ const CERT_TYPE_API_MAP = { }; export function assertServerResponse( - condition: boolean, responseData: object, message: string): void { + condition: boolean, responseData: object, message: string): void { if (!condition) { throw new FirebaseProjectManagementError( - 'invalid-server-response', - `${message} Response data: ${JSON.stringify(responseData, null, 2)}`); + 'invalid-server-response', + `${message} Response data: ${JSON.stringify(responseData, null, 2)}`); } } @@ -69,45 +69,45 @@ export class ProjectManagementRequestHandler { let errorMessage: string; switch (errStatusCode) { - case 400: - errorCode = 'invalid-argument'; - errorMessage = 'Invalid argument provided.'; - break; - case 401: - case 403: - errorCode = 'authentication-error'; - errorMessage = 'An error occurred when trying to authenticate. Make sure the credential ' + case 400: + errorCode = 'invalid-argument'; + errorMessage = 'Invalid argument provided.'; + break; + case 401: + case 403: + errorCode = 'authentication-error'; + errorMessage = 'An error occurred when trying to authenticate. Make sure the credential ' + 'used to authenticate this SDK has the proper permissions. See ' + 'https://firebase.google.com/docs/admin/setup for setup instructions.'; - break; - case 404: - errorCode = 'not-found'; - errorMessage = 'The specified entity could not be found.'; - break; - case 409: - errorCode = 'already-exists'; - errorMessage = 'The specified entity already exists.'; - break; - case 500: - errorCode = 'internal-error'; - errorMessage = 'An internal error has occurred. Please retry the request.'; - break; - case 503: - errorCode = 'service-unavailable'; - errorMessage = 'The server could not process the request in time. See the error ' + break; + case 404: + errorCode = 'not-found'; + errorMessage = 'The specified entity could not be found.'; + break; + case 409: + errorCode = 'already-exists'; + errorMessage = 'The specified entity already exists.'; + break; + case 500: + errorCode = 'internal-error'; + errorMessage = 'An internal error has occurred. Please retry the request.'; + break; + case 503: + errorCode = 'service-unavailable'; + errorMessage = 'The server could not process the request in time. See the error ' + 'documentation for more details.'; - break; - default: - errorCode = 'unknown-error'; - errorMessage = 'An unknown server error was returned.'; + break; + default: + errorCode = 'unknown-error'; + errorMessage = 'An unknown server error was returned.'; } if (!errText) { errText = ''; } throw new FirebaseProjectManagementError( - errorCode, - `${ errorMessage } Status code: ${ errStatusCode }. Raw server response: "${ errText }".`); + errorCode, + `${ errorMessage } Status code: ${ errStatusCode }. Raw server response: "${ errText }".`); } /** @@ -124,10 +124,10 @@ export class ProjectManagementRequestHandler { */ public listAndroidApps(parentResourceName: string): Promise { return this.invokeRequestHandler( - 'GET', - `${parentResourceName}/androidApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, - /* requestData */ null, - 'v1beta1'); + 'GET', + `${parentResourceName}/androidApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, + /* requestData */ null, + 'v1beta1'); } /** @@ -136,10 +136,10 @@ export class ProjectManagementRequestHandler { */ public listIosApps(parentResourceName: string): Promise { return this.invokeRequestHandler( - 'GET', - `${parentResourceName}/iosApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, - /* requestData */ null, - 'v1beta1'); + 'GET', + `${parentResourceName}/iosApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, + /* requestData */ null, + 'v1beta1'); } /** @@ -148,10 +148,10 @@ export class ProjectManagementRequestHandler { */ public listAppMetadata(parentResourceName: string): Promise { return this.invokeRequestHandler( - 'GET', - `${parentResourceName}:searchApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, - /* requestData */ null, - 'v1beta1'); + 'GET', + `${parentResourceName}:searchApps?page_size=${LIST_APPS_MAX_PAGE_SIZE}`, + /* requestData */ null, + 'v1beta1'); } /** @@ -159,7 +159,7 @@ export class ProjectManagementRequestHandler { * to create the Android app within. */ public createAndroidApp( - parentResourceName: string, packageName: string, displayName?: string): Promise { + parentResourceName: string, packageName: string, displayName?: string): Promise { const requestData: any = { packageName, }; @@ -167,18 +167,18 @@ export class ProjectManagementRequestHandler { requestData.displayName = displayName; } return this - .invokeRequestHandler('POST', `${parentResourceName}/androidApps`, requestData, 'v1beta1') - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - `createAndroidApp's responseData must be a non-null object.`); - assertServerResponse( - validator.isNonEmptyString(responseData.name), - responseData, - `createAndroidApp's responseData.name must be a non-empty string.`); - return this.pollRemoteOperationWithExponentialBackoff(responseData.name); - }); + .invokeRequestHandler('POST', `${parentResourceName}/androidApps`, requestData, 'v1beta1') + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + `createAndroidApp's responseData must be a non-null object.`); + assertServerResponse( + validator.isNonEmptyString(responseData.name), + responseData, + `createAndroidApp's responseData.name must be a non-empty string.`); + return this.pollRemoteOperationWithExponentialBackoff(responseData.name); + }); } /** @@ -186,7 +186,7 @@ export class ProjectManagementRequestHandler { * to create the iOS app within. */ public createIosApp( - parentResourceName: string, bundleId: string, displayName?: string): Promise { + parentResourceName: string, bundleId: string, displayName?: string): Promise { const requestData: any = { bundleId, }; @@ -194,18 +194,18 @@ export class ProjectManagementRequestHandler { requestData.displayName = displayName; } return this - .invokeRequestHandler('POST', `${parentResourceName}/iosApps`, requestData, 'v1beta1') - .then((responseData: any) => { - assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - `createIosApp's responseData must be a non-null object.`); - assertServerResponse( - validator.isNonEmptyString(responseData.name), - responseData, - `createIosApp's responseData.name must be a non-empty string.`); - return this.pollRemoteOperationWithExponentialBackoff(responseData.name); - }); + .invokeRequestHandler('POST', `${parentResourceName}/iosApps`, requestData, 'v1beta1') + .then((responseData: any) => { + assertServerResponse( + validator.isNonNullObject(responseData), + responseData, + `createIosApp's responseData must be a non-null object.`); + assertServerResponse( + validator.isNonEmptyString(responseData.name), + responseData, + `createIosApp's responseData.name must be a non-empty string.`); + return this.pollRemoteOperationWithExponentialBackoff(responseData.name); + }); } /** @@ -217,9 +217,9 @@ export class ProjectManagementRequestHandler { displayName: newDisplayName, }; return this - .invokeRequestHandler( - 'PATCH', `${resourceName}?update_mask=display_name`, requestData, 'v1beta1') - .then(() => undefined); + .invokeRequestHandler( + 'PATCH', `${resourceName}?update_mask=display_name`, requestData, 'v1beta1') + .then(() => undefined); } /** @@ -228,7 +228,7 @@ export class ProjectManagementRequestHandler { */ public getAndroidShaCertificates(parentResourceName: string): Promise { return this.invokeRequestHandler( - 'GET', `${parentResourceName}/sha`, /* requestData */ null, 'v1beta1'); + 'GET', `${parentResourceName}/sha`, /* requestData */ null, 'v1beta1'); } /** @@ -236,14 +236,14 @@ export class ProjectManagementRequestHandler { * want to add the given SHA certificate to. */ public addAndroidShaCertificate( - parentResourceName: string, certificate: ShaCertificate): Promise { + parentResourceName: string, certificate: ShaCertificate): Promise { const requestData = { shaHash: certificate.shaHash, certType: CERT_TYPE_API_MAP[certificate.certType], }; return this - .invokeRequestHandler('POST', `${parentResourceName}/sha`, requestData, 'v1beta1') - .then(() => undefined); + .invokeRequestHandler('POST', `${parentResourceName}/sha`, requestData, 'v1beta1') + .then(() => undefined); } /** @@ -252,7 +252,7 @@ export class ProjectManagementRequestHandler { */ public getConfig(parentResourceName: string): Promise { return this.invokeRequestHandler( - 'GET', `${parentResourceName}/config`, /* requestData */ null, 'v1beta1'); + 'GET', `${parentResourceName}/config`, /* requestData */ null, 'v1beta1'); } /** @@ -269,32 +269,32 @@ export class ProjectManagementRequestHandler { */ public deleteResource(resourceName: string): Promise { return this - .invokeRequestHandler('DELETE', resourceName, /* requestData */ null, 'v1beta1') - .then(() => undefined); + .invokeRequestHandler('DELETE', resourceName, /* requestData */ null, 'v1beta1') + .then(() => undefined); } private pollRemoteOperationWithExponentialBackoff( - operationResourceName: string): Promise { + operationResourceName: string): Promise { const poller = new ExponentialBackoffPoller(); return poller.poll(() => { return this.invokeRequestHandler('GET', operationResourceName, /* requestData */ null) - .then((responseData: any) => { - if (responseData.error) { - const errStatusCode: number = responseData.error.code || 500; - const errText: string = + .then((responseData: any) => { + if (responseData.error) { + const errStatusCode: number = responseData.error.code || 500; + const errText: string = responseData.error.message || JSON.stringify(responseData.error); - ProjectManagementRequestHandler.wrapAndRethrowHttpError(errStatusCode, errText); - } + ProjectManagementRequestHandler.wrapAndRethrowHttpError(errStatusCode, errText); + } - if (!responseData.done) { - // Continue polling. - return null; - } + if (!responseData.done) { + // Continue polling. + return null; + } - // Polling complete. Resolve with operation response JSON. - return responseData.response; - }); + // Polling complete. Resolve with operation response JSON. + return responseData.response; + }); }); } @@ -302,10 +302,10 @@ export class ProjectManagementRequestHandler { * Invokes the request handler with the provided request data. */ private invokeRequestHandler( - method: HttpMethod, - path: string, - requestData: object | null, - apiVersion: ('v1' | 'v1beta1') = 'v1'): Promise { + method: HttpMethod, + path: string, + requestData: object | null, + apiVersion: ('v1' | 'v1beta1') = 'v1'): Promise { const baseUrlToUse = (apiVersion === 'v1') ? this.baseUrl : this.baseBetaUrl; const request: HttpRequestConfig = { method, @@ -316,20 +316,20 @@ export class ProjectManagementRequestHandler { }; return this.httpClient.send(request) - .then((response) => { - // Send non-JSON responses to the catch() below, where they will be treated as errors. - if (!response.isJson()) { - throw new HttpError(response); - } + .then((response) => { + // Send non-JSON responses to the catch() below, where they will be treated as errors. + if (!response.isJson()) { + throw new HttpError(response); + } - return response.data; - }) - .catch((err) => { - if (err instanceof HttpError) { - ProjectManagementRequestHandler.wrapAndRethrowHttpError( - err.response.status, err.response.text); - } - throw err; - }); + return response.data; + }) + .catch((err) => { + if (err instanceof HttpError) { + ProjectManagementRequestHandler.wrapAndRethrowHttpError( + err.response.status, err.response.text); + } + throw err; + }); } } diff --git a/src/project-management/project-management.ts b/src/project-management/project-management.ts index 3ac3d2dd09..218e0a5977 100644 --- a/src/project-management/project-management.ts +++ b/src/project-management/project-management.ts @@ -56,8 +56,8 @@ export class ProjectManagement implements FirebaseServiceInterface { constructor(readonly app: FirebaseApp) { if (!validator.isNonNullObject(app) || !('options' in app)) { throw new FirebaseProjectManagementError( - 'invalid-argument', - 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'invalid-argument', + 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'instance.'); } @@ -109,14 +109,14 @@ export class ProjectManagement implements FirebaseServiceInterface { }) .then((responseData: any) => { assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'createAndroidApp()\'s responseData must be a non-null object.'); + validator.isNonNullObject(responseData), + responseData, + 'createAndroidApp()\'s responseData must be a non-null object.'); assertServerResponse( - validator.isNonEmptyString(responseData.appId), - responseData, - `"responseData.appId" field must be present in createAndroidApp()'s response data.`); + validator.isNonEmptyString(responseData.appId), + responseData, + `"responseData.appId" field must be present in createAndroidApp()'s response data.`); return new AndroidApp(responseData.appId, this.requestHandler); }); } @@ -131,14 +131,14 @@ export class ProjectManagement implements FirebaseServiceInterface { }) .then((responseData: any) => { assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - 'createIosApp()\'s responseData must be a non-null object.'); + validator.isNonNullObject(responseData), + responseData, + 'createIosApp()\'s responseData must be a non-null object.'); assertServerResponse( - validator.isNonEmptyString(responseData.appId), - responseData, - `"responseData.appId" field must be present in createIosApp()'s response data.`); + validator.isNonEmptyString(responseData.appId), + responseData, + `"responseData.appId" field must be present in createIosApp()'s response data.`); return new IosApp(responseData.appId, this.requestHandler); }); } @@ -178,13 +178,13 @@ export class ProjectManagement implements FirebaseServiceInterface { return responseData.apps.map((appJson: any) => { assertServerResponse( - validator.isNonEmptyString(appJson.appId), - responseData, - `"apps[].appId" field must be present in the listAppMetadata() response data.`); + validator.isNonEmptyString(appJson.appId), + responseData, + `"apps[].appId" field must be present in the listAppMetadata() response data.`); assertServerResponse( - validator.isNonEmptyString(appJson.platform), - responseData, - `"apps[].platform" field must be present in the listAppMetadata() response data.`); + validator.isNonEmptyString(appJson.platform), + responseData, + `"apps[].platform" field must be present in the listAppMetadata() response data.`); const metadata: AppMetadata = { appId: appJson.appId, platform: (AppPlatform as any)[appJson.platform] || AppPlatform.PLATFORM_UNKNOWN, @@ -215,8 +215,8 @@ export class ProjectManagement implements FirebaseServiceInterface { // Assert that a specific project ID was provided within the app. if (!validator.isNonEmptyString(projectId)) { throw new FirebaseProjectManagementError( - 'invalid-project-id', - 'Failed to determine project ID. Initialize the SDK with service account credentials, or ' + 'invalid-project-id', + 'Failed to determine project ID. Initialize the SDK with service account credentials, or ' + 'set project ID as an app option. Alternatively, set the GOOGLE_CLOUD_PROJECT ' + 'environment variable.'); } @@ -245,9 +245,9 @@ export class ProjectManagement implements FirebaseServiceInterface { return responseData.apps.map((appJson: any) => { assertServerResponse( - validator.isNonEmptyString(appJson.appId), - responseData, - `"apps[].appId" field must be present in the ${callerName} response data.`); + validator.isNonEmptyString(appJson.appId), + responseData, + `"apps[].appId" field must be present in the ${callerName} response data.`); if (platform === 'android') { return new AndroidApp(appJson.appId, this.requestHandler); } else { @@ -259,15 +259,15 @@ export class ProjectManagement implements FirebaseServiceInterface { private assertListAppsResponseData(responseData: any, callerName: string): void { assertServerResponse( - validator.isNonNullObject(responseData), - responseData, - `${callerName}\'s responseData must be a non-null object.`); + validator.isNonNullObject(responseData), + responseData, + `${callerName}\'s responseData must be a non-null object.`); if (responseData.apps) { assertServerResponse( - validator.isArray(responseData.apps), - responseData, - `"apps" field must be present in the ${callerName} response data.`); - } + validator.isArray(responseData.apps), + responseData, + `"apps" field must be present in the ${callerName} response data.`); + } } } diff --git a/src/utils/api-request.ts b/src/utils/api-request.ts index 0ec85bfe8f..17d56790b8 100644 --- a/src/utils/api-request.ts +++ b/src/utils/api-request.ts @@ -515,8 +515,8 @@ class AsyncHttpCall { if (!res.statusCode) { throw new FirebaseAppError( - AppErrorCodes.INTERNAL_ERROR, - 'Expected a statusCode on the response from a ClientRequest'); + AppErrorCodes.INTERNAL_ERROR, + 'Expected a statusCode on the response from a ClientRequest'); } const response: LowLevelResponse = { @@ -837,7 +837,7 @@ export class ApiSettings { constructor(private endpoint: string, private httpMethod: HttpMethod = 'POST') { this.setRequestValidator(null) - .setResponseValidator(null); + .setResponseValidator(null); } /** @return {string} The backend API endpoint. */ @@ -958,29 +958,29 @@ export class ExponentialBackoffPoller extends EventEmitter { private repoll(): void { this.pollCallback!() - .then((result) => { - if (this.completed) { - return; - } + .then((result) => { + if (this.completed) { + return; + } - if (!result) { - this.repollTimer = + if (!result) { + this.repollTimer = setTimeout(() => this.emit('poll'), this.getPollingDelayMillis()); - this.numTries++; - return; - } - - this.markCompleted(); - this.resolve(result); - }) - .catch((err) => { - if (this.completed) { - return; - } - - this.markCompleted(); - this.reject(err); - }); + this.numTries++; + return; + } + + this.markCompleted(); + this.resolve(result); + }) + .catch((err) => { + if (this.completed) { + return; + } + + this.markCompleted(); + this.reject(err); + }); } private getPollingDelayMillis(): number { diff --git a/src/utils/index.ts b/src/utils/index.ts index a30bc7e3d0..f0d7eee394 100755 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -132,8 +132,8 @@ export function formatString(str: string, params?: object): string { let formatted = str; Object.keys(params || {}).forEach((key) => { formatted = formatted.replace( - new RegExp('{' + key + '}', 'g'), - (params as {[key: string]: string})[key]); + new RegExp('{' + key + '}', 'g'), + (params as {[key: string]: string})[key]); }); return formatted; } diff --git a/test/integration/auth.spec.ts b/test/integration/auth.spec.ts index b78e1e6c43..29279d08d0 100755 --- a/test/integration/auth.spec.ts +++ b/test/integration/auth.spec.ts @@ -192,16 +192,16 @@ describe('admin.auth', () => { expect(listUsersResult.users[0].uid).to.equal(uids[1]); expect( - listUsersResult.users[0].passwordHash, - 'Missing passwordHash field. A common cause would be forgetting to ' + listUsersResult.users[0].passwordHash, + 'Missing passwordHash field. A common cause would be forgetting to ' + 'add the "Firebase Authentication Admin" permission. See ' + 'instructions in CONTRIBUTING.md', ).to.be.ok; expect(listUsersResult.users[0].passwordHash!.length).greaterThan(0); expect( - listUsersResult.users[0].passwordSalt, - 'Missing passwordSalt field. A common cause would be forgetting to ' + listUsersResult.users[0].passwordSalt, + 'Missing passwordSalt field. A common cause would be forgetting to ' + 'add the "Firebase Authentication Admin" permission. See ' + 'instructions in CONTRIBUTING.md', ).to.be.ok; @@ -253,7 +253,7 @@ describe('admin.auth', () => { .then(() => { // New sign-in should succeed. return clientAuth().signInWithEmailAndPassword( - mockUserData.email, mockUserData.password); + mockUserData.email, mockUserData.password); }) .then(({user}) => { // Get new session's ID token. @@ -286,8 +286,8 @@ describe('admin.auth', () => { return user!.getIdToken(); }) .then((idToken) => { - // Verify ID token contents. - return admin.auth().verifyIdToken(idToken); + // Verify ID token contents. + return admin.auth().verifyIdToken(idToken); }) .then((decodedIdToken: {[key: string]: any}) => { // Confirm expected claims set on the user's ID token. @@ -312,15 +312,15 @@ describe('admin.auth', () => { .then((idToken) => { // Verify ID token contents. return admin.auth().verifyIdToken(idToken); - }) - .then((decodedIdToken: {[key: string]: any}) => { - // Confirm all custom claims are cleared. - for (const key in customClaims) { - if (customClaims.hasOwnProperty(key)) { - expect(decodedIdToken[key]).to.be.undefined; - } - } - }); + }) + .then((decodedIdToken: {[key: string]: any}) => { + // Confirm all custom claims are cleared. + for (const key in customClaims) { + if (customClaims.hasOwnProperty(key)) { + expect(decodedIdToken[key]).to.be.undefined; + } + } + }); }); it('updateUser() updates the user record with the given parameters', () => { @@ -371,40 +371,40 @@ describe('admin.auth', () => { return admin.auth().createCustomToken(newUserUid, { isAdmin: true, }) - .then((customToken) => { - return clientAuth().signInWithCustomToken(customToken); - }) - .then(({user}) => { - expect(user).to.exist; - return user!.getIdToken(); - }) - .then((idToken) => { - return admin.auth().verifyIdToken(idToken); - }) - .then((token) => { - expect(token.uid).to.equal(newUserUid); - expect(token.isAdmin).to.be.true; - }); + .then((customToken) => { + return clientAuth().signInWithCustomToken(customToken); + }) + .then(({user}) => { + expect(user).to.exist; + return user!.getIdToken(); + }) + .then((idToken) => { + return admin.auth().verifyIdToken(idToken); + }) + .then((token) => { + expect(token.uid).to.equal(newUserUid); + expect(token.isAdmin).to.be.true; + }); }); it('createCustomToken() can mint JWTs without a service account', () => { return admin.auth(noServiceAccountApp).createCustomToken(newUserUid, { isAdmin: true, }) - .then((customToken) => { - return clientAuth().signInWithCustomToken(customToken); - }) - .then(({user}) => { - expect(user).to.exist; - return user!.getIdToken(); - }) - .then((idToken) => { - return admin.auth(noServiceAccountApp).verifyIdToken(idToken); - }) - .then((token) => { - expect(token.uid).to.equal(newUserUid); - expect(token.isAdmin).to.be.true; - }); + .then((customToken) => { + return clientAuth().signInWithCustomToken(customToken); + }) + .then(({user}) => { + expect(user).to.exist; + return user!.getIdToken(); + }) + .then((idToken) => { + return admin.auth(noServiceAccountApp).verifyIdToken(idToken); + }) + .then((token) => { + expect(token.uid).to.equal(newUserUid); + expect(token.isAdmin).to.be.true; + }); }); it('verifyIdToken() fails when called with an invalid token', () => { @@ -548,8 +548,8 @@ describe('admin.auth', () => { const promises: Array> = []; createdTenants.forEach((tenantId) => { promises.push( - admin.auth().tenantManager().deleteTenant(tenantId) - .catch((error) => {/** Ignore. */})); + admin.auth().tenantManager().deleteTenant(tenantId) + .catch((error) => {/** Ignore. */})); }); return Promise.all(promises); }); @@ -629,12 +629,12 @@ describe('admin.auth', () => { email: updatedEmail, phoneNumber: updatedPhone, }) - .then((userRecord) => { - expect(userRecord.uid).to.equal(createdUserUid); - expect(userRecord.tenantId).to.equal(createdTenantId); - expect(userRecord.email).to.equal(updatedEmail); - expect(userRecord.phoneNumber).to.equal(updatedPhone); - }); + .then((userRecord) => { + expect(userRecord.uid).to.equal(createdUserUid); + expect(userRecord.tenantId).to.equal(createdTenantId); + expect(userRecord.email).to.equal(updatedEmail); + expect(userRecord.phoneNumber).to.equal(updatedPhone); + }); }); it('generateEmailVerificationLink() should generate the link for tenant specific user', () => { @@ -801,7 +801,7 @@ describe('admin.auth', () => { }) .then((config) => { const modifiedConfig = deepExtend( - {providerId: authProviderConfig.providerId}, modifiedConfigOptions); + {providerId: authProviderConfig.providerId}, modifiedConfigOptions); assertDeepEqualUnordered(modifiedConfig, config); return tenantAwareAuth.deleteProviderConfig(authProviderConfig.providerId); }) @@ -809,7 +809,7 @@ describe('admin.auth', () => { return tenantAwareAuth.getProviderConfig(authProviderConfig.providerId) .should.eventually.be.rejected.and.have.property('code', 'auth/configuration-not-found'); }); - }); + }); }); describe('OIDC management APIs', () => { @@ -859,7 +859,7 @@ describe('admin.auth', () => { }) .then((config) => { const modifiedConfig = deepExtend( - {providerId: authProviderConfig.providerId}, modifiedConfigOptions); + {providerId: authProviderConfig.providerId}, modifiedConfigOptions); assertDeepEqualUnordered(modifiedConfig, config); return tenantAwareAuth.deleteProviderConfig(authProviderConfig.providerId); }) @@ -867,7 +867,7 @@ describe('admin.auth', () => { return tenantAwareAuth.getProviderConfig(authProviderConfig.providerId) .should.eventually.be.rejected.and.have.property('code', 'auth/configuration-not-found'); }); - }); + }); }); it('getTenant() should resolve with expected tenant', () => { @@ -1044,7 +1044,7 @@ describe('admin.auth', () => { return admin.auth().updateProviderConfig(authProviderConfig1.providerId, modifiedConfigOptions) .then((config) => { const modifiedConfig = deepExtend( - {providerId: authProviderConfig1.providerId}, modifiedConfigOptions); + {providerId: authProviderConfig1.providerId}, modifiedConfigOptions); assertDeepEqualUnordered(modifiedConfig, config); }); }); @@ -1072,7 +1072,7 @@ describe('admin.auth', () => { return admin.auth().updateProviderConfig(authProviderConfig1.providerId, deltaChanges) .then((config) => { const modifiedConfig = deepExtend( - {providerId: authProviderConfig1.providerId}, modifiedConfigOptions); + {providerId: authProviderConfig1.providerId}, modifiedConfigOptions); assertDeepEqualUnordered(modifiedConfig, config); }); }); @@ -1236,7 +1236,7 @@ describe('admin.auth', () => { expectedExp = Math.floor((new Date().getTime() + expiresIn) / 1000); payloadClaims = decodedIdTokenClaims; payloadClaims.iss = payloadClaims.iss.replace( - 'securetoken.google.com', 'session.firebase.google.com'); + 'securetoken.google.com', 'session.firebase.google.com'); delete payloadClaims.exp; delete payloadClaims.iat; expectedIat = Math.floor(new Date().getTime() / 1000); @@ -1367,7 +1367,7 @@ describe('admin.auth', () => { const currentRawPassword = userImportTest.rawPassword; const currentRawSalt = userImportTest.rawSalt; return crypto.createHmac('sha256', currentHashKey) - .update(currentRawPassword + currentRawSalt).digest(); + .update(currentRawPassword + currentRawSalt).digest(); }, rawPassword, rawSalt, @@ -1400,7 +1400,7 @@ describe('admin.auth', () => { const currentRawPassword = userImportTest.rawPassword; const currentRawSalt = userImportTest.rawSalt; return Buffer.from(crypto.createHash('md5') - .update(currentRawSalt + currentRawPassword).digest('hex')); + .update(currentRawSalt + currentRawPassword).digest('hex')); }, rawPassword, rawSalt, @@ -1447,7 +1447,7 @@ describe('admin.auth', () => { const dkLen = userImportTest.importOptions.hash.derivedKeyLength!; return Buffer.from(scrypt.hashSync( - currentRawPassword, {N, r, p}, dkLen, Buffer.from(currentRawSalt))); + currentRawPassword, {N, r, p}, dkLen, Buffer.from(currentRawSalt))); }, rawPassword, rawSalt, @@ -1467,7 +1467,7 @@ describe('admin.auth', () => { expect(userImportTest.importOptions.hash.rounds).to.exist; const currentRounds = userImportTest.importOptions.hash.rounds!; return crypto.pbkdf2Sync( - currentRawPassword, currentRawSalt, currentRounds, 64, 'sha256'); + currentRawPassword, currentRawSalt, currentRounds, 64, 'sha256'); }, rawPassword, rawSalt, @@ -1591,7 +1591,7 @@ describe('admin.auth', () => { * @retunr {Promise} A promise that resolved on success. */ function testImportAndSignInUser( - importUserRecord: any, importOptions: any, rawPassword: string): Promise { + importUserRecord: any, importOptions: any, rawPassword: string): Promise { const users = [importUserRecord]; // Import the user record. return admin.auth().importUsers(users, importOptions) diff --git a/test/integration/database.spec.ts b/test/integration/database.spec.ts index 3f9818a405..db3fa84e89 100644 --- a/test/integration/database.spec.ts +++ b/test/integration/database.spec.ts @@ -174,11 +174,9 @@ describe('admin.database', () => { // Check for type compilation. This method is not invoked by any // tests. But it will trigger a TS compilation failure if the RTDB // typings were not loaded correctly. -// -// @ts-ignore: purposely unused method. function addValueEventListener( - db: admin.database.Database, - callback: (s: admin.database.DataSnapshot | null) => any) { + db: admin.database.Database, + callback: (s: admin.database.DataSnapshot | null) => any) { const eventType: admin.database.EventType = 'value'; db.ref().on(eventType, callback); } diff --git a/test/integration/project-management.spec.ts b/test/integration/project-management.spec.ts index 4cf269c363..9fbf4c73e0 100644 --- a/test/integration/project-management.spec.ts +++ b/test/integration/project-management.spec.ts @@ -42,10 +42,10 @@ describe('admin.projectManagement', () => { before(() => { const androidPromise = ensureAndroidApp() - .then((app) => { - androidApp = app; - return deleteAllShaCertificates(androidApp); - }); + .then((app) => { + androidApp = app; + return deleteAllShaCertificates(androidApp); + }); const iosPromise = ensureIosApp().then((app) => { iosApp = app; }); @@ -56,28 +56,28 @@ describe('admin.projectManagement', () => { describe('listAndroidApps()', () => { it('successfully lists Android apps', () => { return admin.projectManagement().listAndroidApps() - .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) - .then((metadatas) => { - expect(metadatas.length).to.be.at.least(1); - const metadataOwnedByTest = + .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) + .then((metadatas) => { + expect(metadatas.length).to.be.at.least(1); + const metadataOwnedByTest = metadatas.find((metadata) => isIntegrationTestApp(metadata.packageName)); - expect(metadataOwnedByTest).to.exist; - expect(metadataOwnedByTest!.appId).to.equal(androidApp.appId); - }); + expect(metadataOwnedByTest).to.exist; + expect(metadataOwnedByTest!.appId).to.equal(androidApp.appId); + }); }); }); describe('listIosApps()', () => { it('successfully lists iOS apps', () => { return admin.projectManagement().listIosApps() - .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) - .then((metadatas) => { - expect(metadatas.length).to.be.at.least(1); - const metadataOwnedByTest = + .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) + .then((metadatas) => { + expect(metadatas.length).to.be.at.least(1); + const metadataOwnedByTest = metadatas.find((metadata) => isIntegrationTestApp(metadata.bundleId)); - expect(metadataOwnedByTest).to.exist; - expect(metadataOwnedByTest!.appId).to.equal(iosApp.appId); - }); + expect(metadataOwnedByTest).to.exist; + expect(metadataOwnedByTest!.appId).to.equal(iosApp.appId); + }); }); }); @@ -95,11 +95,11 @@ describe('admin.projectManagement', () => { it('successfully lists metadata of all apps', () => { return admin.projectManagement().listAppMetadata() .then((metadatas) => { - expect(metadatas.length).to.be.at.least(2); - const testAppMetadatas = metadatas.filter((metadata) => - isIntegrationTestAppDisplayName(metadata.displayName) && + expect(metadatas.length).to.be.at.least(2); + const testAppMetadatas = metadatas.filter((metadata) => + isIntegrationTestAppDisplayName(metadata.displayName) && (metadata.appId === androidApp.appId || metadata.appId === iosApp.appId)); - expect(testAppMetadatas).to.have.length(2); + expect(testAppMetadatas).to.have.length(2); }); }); }); @@ -128,10 +128,10 @@ describe('admin.projectManagement', () => { it('successfully sets Android app\'s display name', () => { const newDisplayName = generateUniqueAppDisplayName(); return androidApp.setDisplayName(newDisplayName) - .then(() => androidApp.getMetadata()) - .then((appMetadata) => { - expect(appMetadata.displayName).to.equal(newDisplayName); - }); + .then(() => androidApp.getMetadata()) + .then((appMetadata) => { + expect(appMetadata.displayName).to.equal(newDisplayName); + }); }); }); @@ -139,10 +139,10 @@ describe('admin.projectManagement', () => { it('successfully sets iOS app\'s display name', () => { const newDisplayName = generateUniqueAppDisplayName(); return iosApp.setDisplayName(newDisplayName) - .then(() => iosApp.getMetadata()) - .then((appMetadata) => { - expect(appMetadata.displayName).to.equal(newDisplayName); - }); + .then(() => iosApp.getMetadata()) + .then((appMetadata) => { + expect(appMetadata.displayName).to.equal(newDisplayName); + }); }); }); @@ -155,38 +155,38 @@ describe('admin.projectManagement', () => { // 4. Delete the cert we just created. // 5. Check that this app has no certs. return androidApp.getShaCertificates() - .then((certs) => { - expect(certs.length).to.equal(0); - - const shaCertificate = admin.projectManagement().shaCertificate(SHA_256_HASH); - return androidApp.addShaCertificate(shaCertificate); - }) - .then(() => androidApp.getShaCertificates()) - .then((certs) => { - expect(certs.length).to.equal(1); - expect(certs[0].shaHash).to.equal(SHA_256_HASH); - expect(certs[0].certType).to.equal('sha256'); - expect(certs[0].resourceName).to.not.be.empty; - - return androidApp.deleteShaCertificate(certs[0]); - }) - .then(() => androidApp.getShaCertificates()) - .then((certs) => { - expect(certs.length).to.equal(0); - }); + .then((certs) => { + expect(certs.length).to.equal(0); + + const shaCertificate = admin.projectManagement().shaCertificate(SHA_256_HASH); + return androidApp.addShaCertificate(shaCertificate); + }) + .then(() => androidApp.getShaCertificates()) + .then((certs) => { + expect(certs.length).to.equal(1); + expect(certs[0].shaHash).to.equal(SHA_256_HASH); + expect(certs[0].certType).to.equal('sha256'); + expect(certs[0].resourceName).to.not.be.empty; + + return androidApp.deleteShaCertificate(certs[0]); + }) + .then(() => androidApp.getShaCertificates()) + .then((certs) => { + expect(certs.length).to.equal(0); + }); }); it('add a cert and then remove it fails due to missing resourceName', - () => { - const shaCertificate = + () => { + const shaCertificate = admin.projectManagement().shaCertificate(SHA_256_HASH); - return androidApp.addShaCertificate(shaCertificate) - .then(() => androidApp.deleteShaCertificate(shaCertificate)) - .should.eventually.be - .rejectedWith( - 'Specified certificate does not include a resourceName') - .with.property('code', 'project-management/invalid-argument'); - }); + return androidApp.addShaCertificate(shaCertificate) + .then(() => androidApp.deleteShaCertificate(shaCertificate)) + .should.eventually.be + .rejectedWith( + 'Specified certificate does not include a resourceName') + .with.property('code', 'project-management/invalid-argument'); + }); }); describe('androidApp.getConfig()', () => { @@ -215,18 +215,18 @@ describe('admin.projectManagement', () => { */ function ensureAndroidApp(): Promise { return admin.projectManagement().listAndroidApps() - .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) - .then((metadatas) => { - const metadataOwnedByTest = + .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) + .then((metadatas) => { + const metadataOwnedByTest = metadatas.find((metadata) => isIntegrationTestApp(metadata.packageName)); - if (metadataOwnedByTest) { - return admin.projectManagement().androidApp(metadataOwnedByTest.appId); - } + if (metadataOwnedByTest) { + return admin.projectManagement().androidApp(metadataOwnedByTest.appId); + } - // If no Android app owned by these integration tests was found, then create one. - return admin.projectManagement() - .createAndroidApp(generateUniqueAppNamespace(), generateUniqueAppDisplayName()); - }); + // If no Android app owned by these integration tests was found, then create one. + return admin.projectManagement() + .createAndroidApp(generateUniqueAppNamespace(), generateUniqueAppDisplayName()); + }); } /** @@ -236,18 +236,18 @@ function ensureAndroidApp(): Promise { */ function ensureIosApp(): Promise { return admin.projectManagement().listIosApps() - .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) - .then((metadatas) => { - const metadataOwnedByTest = + .then((apps) => Promise.all(apps.map((app) => app.getMetadata()))) + .then((metadatas) => { + const metadataOwnedByTest = metadatas.find((metadata) => isIntegrationTestApp(metadata.bundleId)); - if (metadataOwnedByTest) { - return admin.projectManagement().iosApp(metadataOwnedByTest.appId); - } + if (metadataOwnedByTest) { + return admin.projectManagement().iosApp(metadataOwnedByTest.appId); + } - // If no iOS app owned by these integration tests was found, then create one. - return admin.projectManagement() - .createIosApp(generateUniqueAppNamespace(), generateUniqueAppDisplayName()); - }); + // If no iOS app owned by these integration tests was found, then create one. + return admin.projectManagement() + .createIosApp(generateUniqueAppNamespace(), generateUniqueAppDisplayName()); + }); } /** @@ -255,10 +255,10 @@ function ensureIosApp(): Promise { */ function deleteAllShaCertificates(androidApp: admin.projectManagement.AndroidApp): Promise { return androidApp.getShaCertificates() - .then((shaCertificates: admin.projectManagement.ShaCertificate[]) => { - return Promise.all(shaCertificates.map((cert) => androidApp.deleteShaCertificate(cert))); - }) - .then(() => undefined); + .then((shaCertificates: admin.projectManagement.ShaCertificate[]) => { + return Promise.all(shaCertificates.map((cert) => androidApp.deleteShaCertificate(cert))); + }) + .then(() => undefined); } /** diff --git a/test/integration/typescript/src/example.test.ts b/test/integration/typescript/src/example.test.ts index d630936e4e..25676d96be 100644 --- a/test/integration/typescript/src/example.test.ts +++ b/test/integration/typescript/src/example.test.ts @@ -24,53 +24,53 @@ import * as admin from 'firebase-admin'; const serviceAccount = require('../mock.key.json'); describe('Init App', () => { - const app: admin.app.App = initApp(serviceAccount, 'TestApp'); + const app: admin.app.App = initApp(serviceAccount, 'TestApp'); - after(() => { - return app.delete(); - }); + after(() => { + return app.delete(); + }); - it('Should return an initialized App', () => { - expect(app.name).to.equal('TestApp'); - }); + it('Should return an initialized App', () => { + expect(app.name).to.equal('TestApp'); + }); - it('Should return a Database client', () => { - const db = admin.database(app); - expect(db).to.be.instanceOf((admin.database as any).Database); - }); + it('Should return a Database client', () => { + const db = admin.database(app); + expect(db).to.be.instanceOf((admin.database as any).Database); + }); - it('Should return a Database client for URL', () => { - const db = app.database('https://other-mock.firebaseio.com'); - expect(db).to.be.instanceOf((admin.database as any).Database); - }); + it('Should return a Database client for URL', () => { + const db = app.database('https://other-mock.firebaseio.com'); + expect(db).to.be.instanceOf((admin.database as any).Database); + }); - it('Should return a Database ServerValue', () => { - const serverValue = admin.database.ServerValue; - expect(serverValue).to.not.be.null; - }); + it('Should return a Database ServerValue', () => { + const serverValue = admin.database.ServerValue; + expect(serverValue).to.not.be.null; + }); - it('Should return a Cloud Storage client', () => { - const bucket: Bucket = app.storage().bucket('TestBucket'); - expect(bucket.name).to.equal('TestBucket') - }); + it('Should return a Cloud Storage client', () => { + const bucket: Bucket = app.storage().bucket('TestBucket'); + expect(bucket.name).to.equal('TestBucket') + }); - it('Should return a Firestore client from the app', () => { - const firestore: Firestore = app.firestore(); - expect(firestore).to.be.instanceOf(admin.firestore.Firestore); - }); + it('Should return a Firestore client from the app', () => { + const firestore: Firestore = app.firestore(); + expect(firestore).to.be.instanceOf(admin.firestore.Firestore); + }); - it('Should return a Firestore client', () => { - const firestore: Firestore = admin.firestore(app); - expect(firestore).to.be.instanceOf(admin.firestore.Firestore); - }); + it('Should return a Firestore client', () => { + const firestore: Firestore = admin.firestore(app); + expect(firestore).to.be.instanceOf(admin.firestore.Firestore); + }); - it('Should return a Firestore FieldValue', () => { - const fieldValue = admin.firestore.FieldValue; - expect(fieldValue).to.not.be.null; - }); + it('Should return a Firestore FieldValue', () => { + const fieldValue = admin.firestore.FieldValue; + expect(fieldValue).to.not.be.null; + }); - it('Should return a DocumentReference', () => { - const ref: admin.firestore.DocumentReference = admin.firestore(app).collection('test').doc(); - expect(ref).to.not.be.null; - }); + it('Should return a DocumentReference', () => { + const ref: admin.firestore.DocumentReference = admin.firestore(app).collection('test').doc(); + expect(ref).to.not.be.null; + }); }); diff --git a/test/integration/typescript/src/example.ts b/test/integration/typescript/src/example.ts index 0de5332cc2..9e75838efa 100644 --- a/test/integration/typescript/src/example.ts +++ b/test/integration/typescript/src/example.ts @@ -17,18 +17,18 @@ import * as firebase from 'firebase-admin'; export function initApp(serviceAcct: any, name: string) { - return firebase.initializeApp({ - credential: firebase.credential.cert(serviceAcct), - databaseURL: 'https://mock.firebaseio.com' - }, name); + return firebase.initializeApp({ + credential: firebase.credential.cert(serviceAcct), + databaseURL: 'https://mock.firebaseio.com' + }, name); } export function addValueEventListener( - // Check for type compilation - db: firebase.database.Database, - callback: (s: firebase.database.DataSnapshot) => any) { - let eventType: firebase.database.EventType = 'value'; - db.ref().on(eventType, callback); + // Check for type compilation + db: firebase.database.Database, + callback: (s: firebase.database.DataSnapshot) => any) { + const eventType: firebase.database.EventType = 'value'; + db.ref().on(eventType, callback); } export default initApp; diff --git a/test/resources/mocks.ts b/test/resources/mocks.ts index bdc87cb3ab..a8e1cbc807 100644 --- a/test/resources/mocks.ts +++ b/test/resources/mocks.ts @@ -32,32 +32,32 @@ import {Credential, GoogleOAuthAccessToken, ServiceAccountCredential} from '../. const ALGORITHM = 'RS256'; const ONE_HOUR_IN_SECONDS = 60 * 60; -export let uid = 'someUid'; -export let projectId = 'project_id'; -export let developerClaims = { +export const uid = 'someUid'; +export const projectId = 'project_id'; +export const developerClaims = { one: 'uno', two: 'dos', }; -export let appName = 'mock-app-name'; +export const appName = 'mock-app-name'; -export let serviceName = 'mock-service-name'; +export const serviceName = 'mock-service-name'; -export let databaseURL = 'https://databaseName.firebaseio.com'; +export const databaseURL = 'https://databaseName.firebaseio.com'; -export let databaseAuthVariableOverride = { 'some#string': 'some#val' }; +export const databaseAuthVariableOverride = { 'some#string': 'some#val' }; -export let storageBucket = 'bucketName.appspot.com'; +export const storageBucket = 'bucketName.appspot.com'; -export let credential = new ServiceAccountCredential(path.resolve(__dirname, './mock.key.json')); +export const credential = new ServiceAccountCredential(path.resolve(__dirname, './mock.key.json')); -export let appOptions: FirebaseAppOptions = { +export const appOptions: FirebaseAppOptions = { credential, databaseURL, storageBucket, }; -export let appOptionsWithOverride: FirebaseAppOptions = { +export const appOptionsWithOverride: FirebaseAppOptions = { credential, databaseAuthVariableOverride, databaseURL, @@ -65,15 +65,15 @@ export let appOptionsWithOverride: FirebaseAppOptions = { projectId, }; -export let appOptionsNoAuth: FirebaseAppOptions = { +export const appOptionsNoAuth: FirebaseAppOptions = { databaseURL, }; -export let appOptionsNoDatabaseUrl: FirebaseAppOptions = { +export const appOptionsNoDatabaseUrl: FirebaseAppOptions = { credential, }; -export let appOptionsAuthDB: FirebaseAppOptions = { +export const appOptionsAuthDB: FirebaseAppOptions = { credential, databaseURL, }; @@ -137,7 +137,7 @@ export function appRejectedWhileFetchingAccessToken(): FirebaseApp { }, appName, new FirebaseNamespace().INTERNAL); } -export let refreshToken = { +export const refreshToken = { clientId: 'mock-client-id', clientSecret: 'mock-client-secret', refreshToken: 'mock-refresh-token', @@ -145,11 +145,11 @@ export let refreshToken = { }; /* tslint:disable:no-var-requires */ -export let certificateObject = require('./mock.key.json'); +export const certificateObject = require('./mock.key.json'); /* tslint:enable:no-var-requires */ // Randomly generated key pairs that don't correspond to anything related to Firebase or GCP -export let keyPairs = [ +export const keyPairs = [ /* tslint:disable:max-line-length */ // The private key for this key pair is identical to the one used in ./mock.key.json { diff --git a/test/unit/auth/action-code-settings-builder.spec.ts b/test/unit/auth/action-code-settings-builder.spec.ts index 5f799d5a86..78eace7a04 100644 --- a/test/unit/auth/action-code-settings-builder.spec.ts +++ b/test/unit/auth/action-code-settings-builder.spec.ts @@ -164,8 +164,8 @@ describe('ActionCodeSettingsBuilder', () => { url: 'https://www.example.com/path/file?a=1&b=2', handleCodeInApp: true, android: {}, - } as any); - }).to.throw(AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME.message); + } as any); + }).to.throw(AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME.message); }); const invalidPackageNames = [null, NaN, 0, 1, true, false, '', ['com.example.android'], _.noop]; diff --git a/test/unit/auth/auth-api-request.spec.ts b/test/unit/auth/auth-api-request.spec.ts index be4aa83a6c..cf29267c1c 100755 --- a/test/unit/auth/auth-api-request.spec.ts +++ b/test/unit/auth/auth-api-request.spec.ts @@ -2456,8 +2456,8 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { it('should be rejected when the response does not contain a link', () => { const expectedError = new FirebaseAuthError( - AuthClientErrorCode.INTERNAL_ERROR, - 'INTERNAL ASSERT FAILED: Unable to create the email action link'); + AuthClientErrorCode.INTERNAL_ERROR, + 'INTERNAL ASSERT FAILED: Unable to create the email action link'); const requestData = deepExtend({ requestType: 'VERIFY_EMAIL', email, @@ -2522,12 +2522,12 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((result) => { expect(result).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, {})); + callParams(path, expectedHttpMethod, {})); }); }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -2559,7 +2559,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, {})); + callParams(path, expectedHttpMethod, {})); }); }); }); @@ -2590,7 +2590,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((result) => { expect(result).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, data)); + callParams(path, expectedHttpMethod, data)); }); }); @@ -2607,7 +2607,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((result) => { expect(result).to.deep.equal({oauthIdpConfigs: []}); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, data)); + callParams(path, expectedHttpMethod, data)); }); }); @@ -2624,7 +2624,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((result) => { expect(result).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, data)); + callParams(path, expectedHttpMethod, data)); }); }); @@ -2679,7 +2679,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, data)); + callParams(path, expectedHttpMethod, data)); }); }); }); @@ -2699,12 +2699,12 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((result) => { expect(result).to.be.undefined; expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, {})); + callParams(path, expectedHttpMethod, {})); }); }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -2736,7 +2736,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, {})); + callParams(path, expectedHttpMethod, {})); }); }); }); @@ -2771,7 +2771,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); @@ -2807,7 +2807,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); @@ -2828,7 +2828,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); }); @@ -2871,7 +2871,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); @@ -2895,7 +2895,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedPartialResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, partialRequest)); + callParams(expectedPath, expectedHttpMethod, partialRequest)); }); }); @@ -2918,12 +2918,12 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedPartialResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, partialRequest)); + callParams(expectedPath, expectedHttpMethod, partialRequest)); }); }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'saml.provider', ['oidc.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -2971,7 +2971,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); @@ -2993,7 +2993,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); }); @@ -3020,7 +3020,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -3191,7 +3191,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -3272,7 +3272,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); @@ -3308,7 +3308,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); @@ -3329,7 +3329,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(path, expectedHttpMethod, expectedRequest)); + callParams(path, expectedHttpMethod, expectedRequest)); }); }); }); @@ -3402,7 +3402,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); @@ -3435,7 +3435,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedPartialResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, partialRequest)); + callParams(expectedPath, expectedHttpMethod, partialRequest)); }); }); @@ -3462,12 +3462,12 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((response) => { expect(response).to.deep.equal(expectedPartialResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, partialRequest)); + callParams(expectedPath, expectedHttpMethod, partialRequest)); }); }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'oidc.provider', ['saml.provider'], [], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it('should be rejected given an invalid provider ID:' + JSON.stringify(invalidProviderId), () => { const expectedError = new FirebaseAuthError(AuthClientErrorCode.INVALID_PROVIDER_ID); @@ -3515,7 +3515,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); @@ -3537,7 +3537,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, expectedHttpMethod, expectedRequest)); + callParams(expectedPath, expectedHttpMethod, expectedRequest)); }); }); }); @@ -3910,7 +3910,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((actualResult) => { expect(actualResult).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, expectedRequest)); + callParams(expectedPath, patchMethod, expectedRequest)); }); }); @@ -3930,7 +3930,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((actualResult) => { expect(actualResult).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, partialRequest)); + callParams(expectedPath, patchMethod, partialRequest)); }); }); @@ -3950,7 +3950,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { .then((actualResult) => { expect(actualResult).to.deep.equal(expectedResult.data); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, partialRequest)); + callParams(expectedPath, patchMethod, partialRequest)); }); }); @@ -4002,7 +4002,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, expectedRequest)); + callParams(expectedPath, patchMethod, expectedRequest)); }); }); @@ -4024,7 +4024,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, expectedRequest)); + callParams(expectedPath, patchMethod, expectedRequest)); }); }); @@ -4050,7 +4050,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { }, (error) => { expect(error).to.deep.equal(expectedError); expect(stub).to.have.been.calledOnce.and.calledWith( - callParams(expectedPath, patchMethod, expectedRequest)); + callParams(expectedPath, patchMethod, expectedRequest)); }); }); }); diff --git a/test/unit/auth/auth-config.spec.ts b/test/unit/auth/auth-config.spec.ts index 9fca41ec64..d5777d787d 100755 --- a/test/unit/auth/auth-config.spec.ts +++ b/test/unit/auth/auth-config.spec.ts @@ -271,9 +271,9 @@ describe('SAMLConfig', () => { }); const invalidResourceNames: string[] = [ - '', 'incorrectsaml.', 'saml.provider', 'saml', 'oidc.provider', - 'projects/project1/prefixinboundSamlConfigs/saml.provider', - 'projects/project1/oauthIdpConfigs/saml.provider']; + '', 'incorrectsaml.', 'saml.provider', 'saml', 'oidc.provider', + 'projects/project1/prefixinboundSamlConfigs/saml.provider', + 'projects/project1/oauthIdpConfigs/saml.provider']; invalidResourceNames.forEach((invalidResourceName) => { it(`should return null for invalid resource name "${invalidResourceName}"`, () => { expect(SAMLConfig.getProviderIdFromResourceName(invalidResourceName)).to.be.null; @@ -287,8 +287,8 @@ describe('SAMLConfig', () => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'incorrectsaml.', 'saml', 'oidc.provider', 'other', [], [1, 'a'], - {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'incorrectsaml.', 'saml', 'oidc.provider', 'other', [], [1, 'a'], + {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it(`should return false on invalid SAML provider ID "${JSON.stringify(invalidProviderId)}"`, () => { expect(SAMLConfig.isProviderId(invalidProviderId)).to.be.false; @@ -413,7 +413,7 @@ describe('SAMLConfig', () => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'oidc.provider', 'other', [], [1, 'a'], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'oidc.provider', 'other', [], [1, 'a'], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((providerId) => { it('should throw on invalid providerId:' + JSON.stringify(providerId), () => { const invalidClientRequest = deepCopy(clientRequest) as any; @@ -582,9 +582,9 @@ describe('OIDCConfig', () => { }); const invalidResourceNames: string[] = [ - '', 'incorrectsaml.', 'oidc.provider', 'oidc', 'saml.provider', - 'projects/project1/prefixoauthIdpConfigs/oidc.provider', - 'projects/project1/inboundSamlConfigs/oidc.provider']; + '', 'incorrectsaml.', 'oidc.provider', 'oidc', 'saml.provider', + 'projects/project1/prefixoauthIdpConfigs/oidc.provider', + 'projects/project1/inboundSamlConfigs/oidc.provider']; invalidResourceNames.forEach((invalidResourceName) => { it(`should return null for invalid resource name "${invalidResourceName}"`, () => { expect(OIDCConfig.getProviderIdFromResourceName(invalidResourceName)).to.be.null; @@ -598,8 +598,8 @@ describe('OIDCConfig', () => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'incorrectoidc.', 'oidc', 'saml.provider', 'other', [], [1, 'a'], - {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'incorrectoidc.', 'oidc', 'saml.provider', 'other', [], [1, 'a'], + {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it(`should return false on invalid OIDC provider ID "${JSON.stringify(invalidProviderId)}"`, () => { expect(OIDCConfig.isProviderId(invalidProviderId)).to.be.false; @@ -692,7 +692,7 @@ describe('OIDCConfig', () => { }); const invalidProviderIds = [ - null, NaN, 0, 1, true, false, '', 'other', 'saml.provider', [], [1, 'a'], {}, { a: 1 }, _.noop]; + null, NaN, 0, 1, true, false, '', 'other', 'saml.provider', [], [1, 'a'], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((providerId) => { it('should throw on invalid providerId:' + JSON.stringify(providerId), () => { const invalidClientRequest = deepCopy(clientRequest) as any; diff --git a/test/unit/auth/auth.spec.ts b/test/unit/auth/auth.spec.ts index 0451be7288..2de8247a8b 100755 --- a/test/unit/auth/auth.spec.ts +++ b/test/unit/auth/auth.spec.ts @@ -1771,7 +1771,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub revokeRefreshTokens to return expected uid. const revokeRefreshTokensStub = sinon.stub(testConfig.RequestHandler.prototype, 'revokeRefreshTokens') - .resolves(uid); + .resolves(uid); stubs.push(revokeRefreshTokensStub); return auth.revokeRefreshTokens(uid) .then((result) => { @@ -1786,7 +1786,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub revokeRefreshTokens to throw a backend error. const revokeRefreshTokensStub = sinon.stub(testConfig.RequestHandler.prototype, 'revokeRefreshTokens') - .rejects(expectedError); + .rejects(expectedError); stubs.push(revokeRefreshTokensStub); return auth.revokeRefreshTokens(uid) .then((result) => { @@ -1852,7 +1852,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub uploadAccount to return expected result. const uploadAccountStub = sinon.stub(testConfig.RequestHandler.prototype, 'uploadAccount') - .resolves(expectedUserImportResult); + .resolves(expectedUserImportResult); stubs.push(uploadAccountStub); return auth.importUsers(users, options) .then((result) => { @@ -1867,7 +1867,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub uploadAccount to reject with expected error. const uploadAccountStub = sinon.stub(testConfig.RequestHandler.prototype, 'uploadAccount') - .rejects(expectedServerError); + .rejects(expectedServerError); stubs.push(uploadAccountStub); return auth.importUsers(users, options) .then((result) => { @@ -1884,7 +1884,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub uploadAccount to throw with expected error. const uploadAccountStub = sinon.stub(testConfig.RequestHandler.prototype, 'uploadAccount') - .throws(expectedOptionsError); + .throws(expectedOptionsError); stubs.push(uploadAccountStub); expect(() => { return auth.importUsers(users, {hash: {algorithm: 'invalid' as any}}); @@ -1905,7 +1905,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub uploadAccount to return expected result. const uploadAccountStub = sinon.stub(testConfig.RequestHandler.prototype, 'uploadAccount') - .returns(Promise.resolve(expectedUserImportResult)); + .returns(Promise.resolve(expectedUserImportResult)); const usersCopy = deepCopy(users); usersCopy.forEach((user) => { (user as any).tenantId = TENANT_ID; @@ -2026,7 +2026,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub createSessionCookie to return expected sessionCookie. const createSessionCookieStub = sinon.stub(testConfig.RequestHandler.prototype, 'createSessionCookie') - .resolves(sessionCookie); + .resolves(sessionCookie); stubs.push(createSessionCookieStub); return auth.createSessionCookie(idToken, options) .then((result) => { @@ -2052,7 +2052,7 @@ AUTH_CONFIGS.forEach((testConfig) => { // Stub createSessionCookie to throw a backend error. const createSessionCookieStub = sinon.stub(testConfig.RequestHandler.prototype, 'createSessionCookie') - .rejects(expectedError); + .rejects(expectedError); stubs.push(createSessionCookieStub); return auth.createSessionCookie(idToken, options) .then((result) => { @@ -2157,7 +2157,7 @@ AUTH_CONFIGS.forEach((testConfig) => { .then((actualLink: string) => { // Confirm underlying API called with expected parameters. expect(getEmailActionLinkStub).to.have.been.calledOnce.and.calledWith( - emailActionFlow.requestType, email, actionCodeSettings); + emailActionFlow.requestType, email, actionCodeSettings); // Confirm expected user record response returned. expect(actualLink).to.equal(expectedLink); }); @@ -2178,7 +2178,7 @@ AUTH_CONFIGS.forEach((testConfig) => { .then((actualLink: string) => { // Confirm underlying API called with expected parameters. expect(getEmailActionLinkStub).to.have.been.calledOnce.and.calledWith( - emailActionFlow.requestType, email, undefined); + emailActionFlow.requestType, email, undefined); // Confirm expected user record response returned. expect(actualLink).to.equal(expectedLink); }); @@ -2196,7 +2196,7 @@ AUTH_CONFIGS.forEach((testConfig) => { }, (error: any) => { // Confirm underlying API called with expected parameters. expect(getEmailActionLinkStub).to.have.been.calledOnce.and.calledWith( - emailActionFlow.requestType, email, actionCodeSettings); + emailActionFlow.requestType, email, actionCodeSettings); // Confirm expected error returned. expect(error).to.equal(expectedError); }); @@ -2218,7 +2218,7 @@ AUTH_CONFIGS.forEach((testConfig) => { }); const invalidProviderIds = [ - undefined, null, NaN, 0, 1, true, false, '', [], [1, 'a'], {}, { a: 1 }, _.noop]; + undefined, null, NaN, 0, 1, true, false, '', [], [1, 'a'], {}, { a: 1 }, _.noop]; invalidProviderIds.forEach((invalidProviderId) => { it(`should be rejected given an invalid provider ID "${JSON.stringify(invalidProviderId)}"`, () => { return (auth as Auth).getProviderConfig(invalidProviderId as any) diff --git a/test/unit/auth/credential.spec.ts b/test/unit/auth/credential.spec.ts index 0b9ac61925..368d983f0c 100644 --- a/test/unit/auth/credential.spec.ts +++ b/test/unit/auth/credential.spec.ts @@ -416,7 +416,7 @@ describe('Credential', () => { it('should throw error if type not specified on cert file', () => { fsStub = sinon.stub(fs, 'readFileSync').returns(JSON.stringify({})); expect(() => getApplicationDefault()) - .to.throw(Error, 'Invalid contents in the credentials file'); + .to.throw(Error, 'Invalid contents in the credentials file'); }); it('should throw error if type is unknown on cert file', () => { diff --git a/test/unit/auth/tenant-manager.spec.ts b/test/unit/auth/tenant-manager.spec.ts index bf1c937e63..c39a611f35 100644 --- a/test/unit/auth/tenant-manager.spec.ts +++ b/test/unit/auth/tenant-manager.spec.ts @@ -53,11 +53,11 @@ describe('TenantManager', () => { mockApp = mocks.app(); tenantManager = new TenantManager(mockApp); nullAccessTokenTenantManager = new TenantManager( - mocks.appReturningNullAccessToken()); + mocks.appReturningNullAccessToken()); malformedAccessTokenTenantManager = new TenantManager( - mocks.appReturningMalformedAccessToken()); + mocks.appReturningMalformedAccessToken()); rejectedPromiseAccessTokenTenantManager = new TenantManager( - mocks.appRejectedWhileFetchingAccessToken()); + mocks.appRejectedWhileFetchingAccessToken()); }); diff --git a/test/unit/auth/token-generator.spec.ts b/test/unit/auth/token-generator.spec.ts index b95c1ad64b..6e28929014 100644 --- a/test/unit/auth/token-generator.spec.ts +++ b/test/unit/auth/token-generator.spec.ts @@ -372,7 +372,7 @@ describe('FirebaseTokenGenerator', () => { }); it('should be fulfilled given a valid uid and empty object developer claims', () => { - return tokenGenerator.createCustomToken(mocks.uid, {}); + return tokenGenerator.createCustomToken(mocks.uid, {}); }); it('should be fulfilled given a valid uid and valid developer claims', () => { diff --git a/test/unit/auth/token-verifier.spec.ts b/test/unit/auth/token-verifier.spec.ts index 41dddfe514..8de2ca54a3 100644 --- a/test/unit/auth/token-verifier.spec.ts +++ b/test/unit/auth/token-verifier.spec.ts @@ -153,7 +153,7 @@ describe('FirebaseTokenVerifier', () => { expiredErrorCode: AuthClientErrorCode.INVALID_ARGUMENT, }, app, - ); + ); }).not.to.throw(); }); diff --git a/test/unit/auth/user-import-builder.spec.ts b/test/unit/auth/user-import-builder.spec.ts index 58b100d059..68685a48ea 100644 --- a/test/unit/auth/user-import-builder.spec.ts +++ b/test/unit/auth/user-import-builder.spec.ts @@ -210,23 +210,23 @@ describe('UserImportBuilder', () => { let minRounds: number; let maxRounds: number; switch (algorithm) { - case 'MD5': - minRounds = 0; - maxRounds = 8192; - break; - case 'SHA1': - case 'SHA256': - case 'SHA512': - minRounds = 1; - maxRounds = 8192; - break; - case 'PBKDF_SHA1': - case 'PBKDF2_SHA256': - minRounds = 0; - maxRounds = 120000; - break; - default: - throw new Error('Unexpected algorithm: ' + algorithm); + case 'MD5': + minRounds = 0; + maxRounds = 8192; + break; + case 'SHA1': + case 'SHA256': + case 'SHA512': + minRounds = 1; + maxRounds = 8192; + break; + case 'PBKDF_SHA1': + case 'PBKDF2_SHA256': + minRounds = 0; + maxRounds = 120000; + break; + default: + throw new Error('Unexpected algorithm: ' + algorithm); } const invalidRounds = [minRounds - 1, maxRounds + 1, 'invalid', undefined, null]; @@ -611,8 +611,8 @@ describe('UserImportBuilder', () => { // Index should match server error index. index: 1, error: new FirebaseAuthError( - AuthClientErrorCode.INVALID_USER_IMPORT, - 'Some error occurred!', + AuthClientErrorCode.INVALID_USER_IMPORT, + 'Some error occurred!', ), }, ], @@ -682,8 +682,8 @@ describe('UserImportBuilder', () => { { index: 2, error: new FirebaseAuthError( - AuthClientErrorCode.INVALID_USER_IMPORT, - 'Some error occurred in USER3!', + AuthClientErrorCode.INVALID_USER_IMPORT, + 'Some error occurred in USER3!', ), }, // Client side detected error. @@ -692,8 +692,8 @@ describe('UserImportBuilder', () => { { index: 5, error: new FirebaseAuthError( - AuthClientErrorCode.INVALID_USER_IMPORT, - 'Another error occurred in USER6!', + AuthClientErrorCode.INVALID_USER_IMPORT, + 'Another error occurred in USER6!', ), }, // Client side errors. @@ -702,7 +702,7 @@ describe('UserImportBuilder', () => { ], }; const userImportBuilder = new UserImportBuilder( - testUsers, validOptions as any, userRequestValidatorWithMultipleErrors); + testUsers, validOptions as any, userRequestValidatorWithMultipleErrors); expect(userImportBuilder.buildResponse(failingServerResponse)) .to.deep.equal(mixedErrorUserImportResponse); }); diff --git a/test/unit/auth/user-record.spec.ts b/test/unit/auth/user-record.spec.ts index 7b81d83a2a..77f079111a 100644 --- a/test/unit/auth/user-record.spec.ts +++ b/test/unit/auth/user-record.spec.ts @@ -447,7 +447,7 @@ describe('UserRecord', () => { it('should return expected photoURL', () => { expect(userRecord.photoURL).to.equal( - 'https://lh3.googleusercontent.com/1234567890/photo.jpg'); + 'https://lh3.googleusercontent.com/1234567890/photo.jpg'); }); it('should throw when modifying readonly photoURL property', () => { @@ -626,13 +626,13 @@ describe('UserRecord', () => { it('should throw when modifying readonly providerData property', () => { expect(() => { (userRecord as any).providerData = [ - new UserInfo({ - providerId: 'google.com', - displayName: 'Jane Doe', - photoUrl: 'https://lh3.googleusercontent.com/00000000/photo.jpg', - email: 'janedoe@gmail.com', - rawId: '00000000', - }), + new UserInfo({ + providerId: 'google.com', + displayName: 'Jane Doe', + photoUrl: 'https://lh3.googleusercontent.com/00000000/photo.jpg', + email: 'janedoe@gmail.com', + rawId: '00000000', + }), ]; }).to.throw(Error); }); diff --git a/test/unit/firebase-app.spec.ts b/test/unit/firebase-app.spec.ts index 5d6fc3063c..001d959bcf 100644 --- a/test/unit/firebase-app.spec.ts +++ b/test/unit/firebase-app.spec.ts @@ -877,7 +877,7 @@ describe('FirebaseApp', () => { it('resets the proactive refresh timeout upon a force refresh', () => { // Force a token refresh. return mockApp.INTERNAL.getToken(true).then((token1) => { - // Forward the clock to five minutes and one second before expiry. + // Forward the clock to five minutes and one second before expiry. let expiryInMilliseconds = token1.expirationTime - Date.now(); clock.tick(expiryInMilliseconds - (5 * ONE_MINUTE_IN_MILLISECONDS) - 1000); diff --git a/test/unit/firebase-namespace.spec.ts b/test/unit/firebase-namespace.spec.ts index f52b50bfc9..7908f6d306 100644 --- a/test/unit/firebase-namespace.spec.ts +++ b/test/unit/firebase-namespace.spec.ts @@ -622,7 +622,7 @@ describe('FirebaseNamespace', () => { it('should return a reference to ProjectManagement type', () => { expect(firebaseNamespace.projectManagement.ProjectManagement) - .to.be.deep.equal(ProjectManagement); + .to.be.deep.equal(ProjectManagement); }); }); @@ -656,7 +656,7 @@ describe('FirebaseNamespace', () => { it('should return a reference to SecurityRules type', () => { expect(firebaseNamespace.securityRules.SecurityRules) - .to.be.deep.equal(SecurityRules); + .to.be.deep.equal(SecurityRules); }); }); }); diff --git a/test/unit/firebase.spec.ts b/test/unit/firebase.spec.ts index 913f3c5067..bdbd4d787a 100644 --- a/test/unit/firebase.spec.ts +++ b/test/unit/firebase.spec.ts @@ -129,8 +129,7 @@ describe('Firebase', () => { }); it('should initialize SDK given an application default credential', () => { - let credPath: string | undefined; - credPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + const credPath: string | undefined = process.env.GOOGLE_APPLICATION_CREDENTIALS; process.env.GOOGLE_APPLICATION_CREDENTIALS = path.resolve(__dirname, '../resources/mock.key.json'); firebaseAdmin.initializeApp({ credential: firebaseAdmin.credential.applicationDefault(), diff --git a/test/unit/instance-id/instance-id-request.spec.ts b/test/unit/instance-id/instance-id-request.spec.ts index 2b83642f11..4f4186adf1 100644 --- a/test/unit/instance-id/instance-id-request.spec.ts +++ b/test/unit/instance-id/instance-id-request.spec.ts @@ -97,52 +97,52 @@ describe('FirebaseInstanceIdRequestHandler', () => { }); it('should throw for HTTP 404 errors', () => { - const stub = sinon.stub(HttpClient.prototype, 'send') - .rejects(utils.errorFrom({}, 404)); - stubs.push(stub); - - const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); - return requestHandler.deleteInstanceId('test-iid') - .then(() => { - throw new Error('Unexpected success'); - }) - .catch((error) => { - expect(error.code).to.equal('instance-id/api-error'); - expect(error.message).to.equal('Instance ID "test-iid": Failed to find the instance ID.'); - }); + const stub = sinon.stub(HttpClient.prototype, 'send') + .rejects(utils.errorFrom({}, 404)); + stubs.push(stub); + + const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); + return requestHandler.deleteInstanceId('test-iid') + .then(() => { + throw new Error('Unexpected success'); + }) + .catch((error) => { + expect(error.code).to.equal('instance-id/api-error'); + expect(error.message).to.equal('Instance ID "test-iid": Failed to find the instance ID.'); + }); }); it('should throw for HTTP 409 errors', () => { - const stub = sinon.stub(HttpClient.prototype, 'send') - .rejects(utils.errorFrom({}, 409)); - stubs.push(stub); - - const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); - return requestHandler.deleteInstanceId('test-iid') - .then(() => { - throw new Error('Unexpected success'); - }) - .catch((error) => { - expect(error.code).to.equal('instance-id/api-error'); - expect(error.message).to.equal('Instance ID "test-iid": Already deleted.'); - }); + const stub = sinon.stub(HttpClient.prototype, 'send') + .rejects(utils.errorFrom({}, 409)); + stubs.push(stub); + + const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); + return requestHandler.deleteInstanceId('test-iid') + .then(() => { + throw new Error('Unexpected success'); + }) + .catch((error) => { + expect(error.code).to.equal('instance-id/api-error'); + expect(error.message).to.equal('Instance ID "test-iid": Already deleted.'); + }); }); it('should throw for unexpected HTTP errors', () => { - const expectedResult = {error: 'test error'}; - const stub = sinon.stub(HttpClient.prototype, 'send') - .rejects(utils.errorFrom(expectedResult, 511)); - stubs.push(stub); - - const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); - return requestHandler.deleteInstanceId('test-iid') - .then(() => { - throw new Error('Unexpected success'); - }) - .catch((error) => { - expect(error.code).to.equal('instance-id/api-error'); - expect(error.message).to.equal('test error'); - }); + const expectedResult = {error: 'test error'}; + const stub = sinon.stub(HttpClient.prototype, 'send') + .rejects(utils.errorFrom(expectedResult, 511)); + stubs.push(stub); + + const requestHandler = new FirebaseInstanceIdRequestHandler(mockApp); + return requestHandler.deleteInstanceId('test-iid') + .then(() => { + throw new Error('Unexpected success'); + }) + .catch((error) => { + expect(error.code).to.equal('instance-id/api-error'); + expect(error.message).to.equal('test error'); + }); }); }); }); diff --git a/test/unit/messaging/messaging.spec.ts b/test/unit/messaging/messaging.spec.ts index 52219c4312..558a5b706d 100644 --- a/test/unit/messaging/messaging.spec.ts +++ b/test/unit/messaging/messaging.spec.ts @@ -482,7 +482,7 @@ describe('Messaging', () => { return messaging.send( {token: 'mock-token'}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/invalid-argument'); + .and.have.property('code', 'messaging/invalid-argument'); }); it('should fail when the backend server returns a detailed error with FCM error code', () => { @@ -502,7 +502,7 @@ describe('Messaging', () => { return messaging.send( {token: 'mock-token'}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); ['THIRD_PARTY_AUTH_ERROR', 'APNS_AUTH_ERROR'].forEach((errorCode) => { @@ -523,7 +523,7 @@ describe('Messaging', () => { return messaging.send( {token: 'mock-token'}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/third-party-auth-error'); + .and.have.property('code', 'messaging/third-party-auth-error'); }); }); @@ -538,7 +538,7 @@ describe('Messaging', () => { return messaging.send( {token: 'mock-token'}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); it('should fail when the backend server returns an unknown error', () => { @@ -755,7 +755,7 @@ describe('Messaging', () => { return messaging.sendAll( [validMessage], ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/invalid-argument'); + .and.have.property('code', 'messaging/invalid-argument'); }); it('should fail when the backend server returns a detailed error with FCM error code', () => { @@ -775,7 +775,7 @@ describe('Messaging', () => { return messaging.sendAll( [validMessage], ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); it('should map server error code to client-side error', () => { @@ -789,7 +789,7 @@ describe('Messaging', () => { return messaging.sendAll( [validMessage], ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); it('should fail when the backend server returns an unknown error', () => { @@ -1049,7 +1049,7 @@ describe('Messaging', () => { return messaging.sendMulticast( {tokens: ['a']}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/invalid-argument'); + .and.have.property('code', 'messaging/invalid-argument'); }); it('should fail when the backend server returns a detailed error with FCM error code', () => { @@ -1069,7 +1069,7 @@ describe('Messaging', () => { return messaging.sendMulticast( {tokens: ['a']}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); it('should map server error code to client-side error', () => { @@ -1083,7 +1083,7 @@ describe('Messaging', () => { return messaging.sendMulticast( {tokens: ['a']}, ).should.eventually.be.rejectedWith('test error message') - .and.have.property('code', 'messaging/registration-token-not-registered'); + .and.have.property('code', 'messaging/registration-token-not-registered'); }); it('should fail when the backend server returns an unknown error', () => { @@ -1528,7 +1528,7 @@ describe('Messaging', () => { disableRetries(messaging); return messaging.sendToDeviceGroup( - mocks.messaging.notificationKey, + mocks.messaging.notificationKey, mocks.messaging.payload, ).should.eventually.be.rejected.and.have.property('code', expectedError); }); @@ -1779,7 +1779,7 @@ describe('Messaging', () => { disableRetries(messaging); return messaging.sendToTopic( - mocks.messaging.topic, + mocks.messaging.topic, mocks.messaging.payload, ).should.eventually.be.rejected.and.have.property('code', expectedError); }); @@ -1998,7 +1998,7 @@ describe('Messaging', () => { disableRetries(messaging); return messaging.sendToCondition( - mocks.messaging.condition, + mocks.messaging.condition, mocks.messaging.payload, ).should.eventually.be.rejected.and.have.property('code', expectedError); }); diff --git a/test/unit/project-management/android-app.spec.ts b/test/unit/project-management/android-app.spec.ts index cd043c3484..2fed6622ed 100644 --- a/test/unit/project-management/android-app.spec.ts +++ b/test/unit/project-management/android-app.spec.ts @@ -100,22 +100,22 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp.getMetadata().should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(null)); stubs.push(stub); return androidApp.getMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'getMetadata()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'getMetadata()\'s responseData must be a non-null object. Response data: null'); }); const requiredFieldsList = ['name', 'appId', 'projectId', 'packageName']; @@ -125,22 +125,22 @@ describe('AndroidApp', () => { delete partialApiResponse[requiredField]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return androidApp.getMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - `getMetadata()\'s responseData.${requiredField} must be a non-empty string. ` + .should.eventually.be.rejected + .and.have.property( + 'message', + `getMetadata()\'s responseData.${requiredField} must be a non-empty string. ` + `Response data: ${JSON.stringify(partialApiResponse, null, 2)}`); }); }); it('should resolve with metadata on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(VALID_ANDROID_APP_METADATA_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(VALID_ANDROID_APP_METADATA_API_RESPONSE)); stubs.push(stub); return androidApp.getMetadata().should.eventually.deep.equal(VALID_ANDROID_APP_METADATA); }); @@ -151,17 +151,17 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp.setDisplayName(newDisplayName) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should resolve on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.resolve()); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.resolve()); stubs.push(stub); return androidApp.setDisplayName(newDisplayName).should.eventually.be.fulfilled; }); @@ -190,23 +190,23 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.resolve(null)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'getShaCertificates()\'s responseData must be a non-null object. Response data: ' + .should.eventually.be.rejected + .and.have.property( + 'message', + 'getShaCertificates()\'s responseData must be a non-null object. Response data: ' + 'null'); }); @@ -214,25 +214,25 @@ describe('AndroidApp', () => { const partialApiResponse = {}; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.deep.equal([]); + .should.eventually.deep.equal([]); }); it('should throw when API response has non-array "certificates" field', () => { const partialApiResponse = { certificates: 'none' }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"certificates" field must be present in the getShaCertificates() response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"certificates" field must be present in the getShaCertificates() response data. ' + 'Response data: ' + JSON.stringify(partialApiResponse, null, 2)); }); @@ -243,14 +243,14 @@ describe('AndroidApp', () => { delete partialApiResponse.certificates[1][requiredField]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.be.rejected - .and.have.property( - 'message', - `getShaCertificates()\'s responseData.certificates[].${requiredField} must be a ` + .should.eventually.be.rejected + .and.have.property( + 'message', + `getShaCertificates()\'s responseData.certificates[].${requiredField} must be a ` + 'non-empty string. Response data: ' + JSON.stringify(partialApiResponse, null, 2)); }); @@ -258,11 +258,11 @@ describe('AndroidApp', () => { it('should resolve with metadata on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') - .returns(Promise.resolve(VALID_ANDROID_CERTS_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'getAndroidShaCertificates') + .returns(Promise.resolve(VALID_ANDROID_CERTS_API_RESPONSE)); stubs.push(stub); return androidApp.getShaCertificates() - .should.eventually.deep.equal(VALID_ANDROID_CERTS); + .should.eventually.deep.equal(VALID_ANDROID_CERTS); }); }); @@ -271,17 +271,17 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'addAndroidShaCertificate') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'addAndroidShaCertificate') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp.addShaCertificate(certificateToAdd) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should resolve on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'addAndroidShaCertificate') - .returns(Promise.resolve()); + .stub(ProjectManagementRequestHandler.prototype, 'addAndroidShaCertificate') + .returns(Promise.resolve()); stubs.push(stub); return androidApp.addShaCertificate(certificateToAdd).should.eventually.be.fulfilled; }); @@ -294,28 +294,28 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'deleteResource') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'deleteResource') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp - .deleteShaCertificate(certificateToDeleteWithResourceName) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .deleteShaCertificate(certificateToDeleteWithResourceName) + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should fail on certificate without resourceName', () => { expect(() => androidApp.deleteShaCertificate(certificateToDelete)) - .to.throw(FirebaseProjectManagementError) - .with.property('code', 'project-management/invalid-argument'); + .to.throw(FirebaseProjectManagementError) + .with.property('code', 'project-management/invalid-argument'); }); it('should resolve on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'deleteResource') - .returns(Promise.resolve()); + .stub(ProjectManagementRequestHandler.prototype, 'deleteResource') + .returns(Promise.resolve()); stubs.push(stub); return androidApp - .deleteShaCertificate(certificateToDeleteWithResourceName) - .should.eventually.be.fulfilled; + .deleteShaCertificate(certificateToDeleteWithResourceName) + .should.eventually.be.fulfilled; }); }); @@ -327,22 +327,22 @@ describe('AndroidApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return androidApp.getConfig().should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(null)); stubs.push(stub); return androidApp.getConfig() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'getConfig()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'getConfig()\'s responseData must be a non-null object. Response data: null'); }); it('should throw with non-base64 response.configFileContents', () => { @@ -350,21 +350,21 @@ describe('AndroidApp', () => { apiResponse.configFileContents = '1' + apiResponse.configFileContents; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(apiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(apiResponse)); stubs.push(stub); return androidApp.getConfig() - .should.eventually.be.rejected - .and.have.property( - 'message', - `getConfig()\'s responseData.configFileContents must be a base64 string. ` + .should.eventually.be.rejected + .and.have.property( + 'message', + `getConfig()\'s responseData.configFileContents must be a base64 string. ` + `Response data: ${JSON.stringify(apiResponse, null, 2)}`); }); it('should resolve with metadata on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(VALID_ANDROID_CONFIG_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(VALID_ANDROID_CONFIG_API_RESPONSE)); stubs.push(stub); return androidApp.getConfig().should.eventually.deep.equal(VALID_ANDROID_CONFIG); }); diff --git a/test/unit/project-management/ios-app.spec.ts b/test/unit/project-management/ios-app.spec.ts index ab0be5b033..3f84e3713b 100644 --- a/test/unit/project-management/ios-app.spec.ts +++ b/test/unit/project-management/ios-app.spec.ts @@ -99,22 +99,22 @@ describe('IosApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.reject(expectedError)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.reject(expectedError)); stubs.push(stub); return iosApp.getMetadata().should.eventually.be.rejected.and.equal(expectedError); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(null)); stubs.push(stub); return iosApp.getMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'getMetadata()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'getMetadata()\'s responseData must be a non-null object. Response data: null'); }); const requiredFieldsList = ['name', 'appId', 'projectId', 'bundleId']; @@ -124,22 +124,22 @@ describe('IosApp', () => { delete partialApiResponse[requiredField]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return iosApp.getMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - `getMetadata()\'s responseData.${requiredField} must be a non-empty string. ` + .should.eventually.be.rejected + .and.have.property( + 'message', + `getMetadata()\'s responseData.${requiredField} must be a non-empty string. ` + `Response data: ${JSON.stringify(partialApiResponse, null, 2)}`); }); }); it('should resolve with metadata on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getResource') - .returns(Promise.resolve(VALID_IOS_APP_METADATA_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'getResource') + .returns(Promise.resolve(VALID_IOS_APP_METADATA_API_RESPONSE)); stubs.push(stub); return iosApp.getMetadata().should.eventually.deep.equal(VALID_IOS_APP_METADATA); }); @@ -150,17 +150,17 @@ describe('IosApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return iosApp.setDisplayName(newDisplayName) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should resolve on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.resolve()); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.resolve()); stubs.push(stub); return iosApp.setDisplayName(newDisplayName).should.eventually.be.fulfilled; }); @@ -174,22 +174,22 @@ describe('IosApp', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return iosApp.getConfig().should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(null)); stubs.push(stub); return iosApp.getConfig() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'getConfig()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'getConfig()\'s responseData must be a non-null object. Response data: null'); }); it('should throw with non-base64 response.configFileContents', () => { @@ -197,21 +197,21 @@ describe('IosApp', () => { apiResponse.configFileContents = '1' + apiResponse.configFileContents; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(apiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(apiResponse)); stubs.push(stub); return iosApp.getConfig() - .should.eventually.be.rejected - .and.have.property( - 'message', - `getConfig()\'s responseData.configFileContents must be a base64 string. ` + .should.eventually.be.rejected + .and.have.property( + 'message', + `getConfig()\'s responseData.configFileContents must be a base64 string. ` + `Response data: ${JSON.stringify(apiResponse, null, 2)}`); }); it('should resolve with metadata on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'getConfig') - .returns(Promise.resolve(VALID_IOS_CONFIG_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'getConfig') + .returns(Promise.resolve(VALID_IOS_CONFIG_API_RESPONSE)); stubs.push(stub); return iosApp.getConfig().should.eventually.deep.equal(VALID_IOS_CONFIG); }); diff --git a/test/unit/project-management/project-management-api-request.spec.ts b/test/unit/project-management/project-management-api-request.spec.ts index 87a3e334af..2ae4f1c228 100644 --- a/test/unit/project-management/project-management-api-request.spec.ts +++ b/test/unit/project-management/project-management-api-request.spec.ts @@ -98,24 +98,24 @@ describe('ProjectManagementRequestHandler', () => { return; } it(`should throw for HTTP ${errorCode} errors`, () => { - const stub = sinon.stub(HttpClient.prototype, 'send') - .rejects(utils.errorFrom({}, parseInt(errorCode, 10))); - stubs.push(stub); + const stub = sinon.stub(HttpClient.prototype, 'send') + .rejects(utils.errorFrom({}, parseInt(errorCode, 10))); + stubs.push(stub); - return callback() - .should.eventually.be.rejected - .and.have.property('code', errorCodeMap[errorCode]); + return callback() + .should.eventually.be.rejected + .and.have.property('code', errorCodeMap[errorCode]); }); }); it('should throw for HTTP unknown errors', () => { - const stub = sinon.stub(HttpClient.prototype, 'send') - .rejects(utils.errorFrom({}, 1337)); - stubs.push(stub); + const stub = sinon.stub(HttpClient.prototype, 'send') + .rejects(utils.errorFrom({}, 1337)); + stubs.push(stub); - return callback() - .should.eventually.be.rejected - .and.have.property('code', 'project-management/unknown-error'); + return callback() + .should.eventually.be.rejected + .and.have.property('code', 'project-management/unknown-error'); }); } @@ -139,22 +139,22 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${PROJECT_RESOURCE_NAME}/androidApps?page_size=100`; return requestHandler.listAndroidApps(PROJECT_RESOURCE_NAME) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -170,21 +170,21 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${PROJECT_RESOURCE_NAME}/iosApps?page_size=100`; return requestHandler.listIosApps(PROJECT_RESOURCE_NAME) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -207,22 +207,22 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${PROJECT_RESOURCE_NAME}:searchApps?page_size=100`; return requestHandler.listAppMetadata(PROJECT_RESOURCE_NAME) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -234,10 +234,10 @@ describe('ProjectManagementRequestHandler', () => { stubs.push(stub); return requestHandler.createAndroidApp(PROJECT_RESOURCE_NAME, PACKAGE_NAME, DISPLAY_NAME) - .should.eventually.be.rejected - .and.have.property( - 'message', - 'createAndroidApp\'s responseData.name must be a non-empty string. Response data: ' + .should.eventually.be.rejected + .and.have.property( + 'message', + 'createAndroidApp\'s responseData.name must be a non-empty string. Response data: ' + '{}'); }); @@ -253,13 +253,13 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().resolves(utils.responseFrom(pollErrorResult)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().resolves(utils.responseFrom(pollErrorResult)); stubs.push(stub); return requestHandler.createAndroidApp(PROJECT_RESOURCE_NAME, PACKAGE_NAME, DISPLAY_NAME) - .should.eventually.be.rejected - .and.have.property('code', 'project-management/already-exists'); + .should.eventually.be.rejected + .and.have.property('code', 'project-management/already-exists'); }); it('should propagate polling API response thrown errors', () => { @@ -267,13 +267,13 @@ describe('ProjectManagementRequestHandler', () => { const pollError = 'second-poll-error'; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().returns(Promise.reject(pollError)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().returns(Promise.reject(pollError)); stubs.push(stub); return requestHandler.createAndroidApp(PROJECT_RESOURCE_NAME, PACKAGE_NAME, DISPLAY_NAME) - .should.eventually.be.rejected - .and.equal(pollError); + .should.eventually.be.rejected + .and.equal(pollError); }); it('should succeed after multiple polls', () => { @@ -287,9 +287,9 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().resolves(utils.responseFrom(firstPollResult)) - .onThirdCall().resolves(utils.responseFrom(secondPollResult)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().resolves(utils.responseFrom(firstPollResult)) + .onThirdCall().resolves(utils.responseFrom(secondPollResult)); stubs.push(stub); const initialUrl = `https://${HOST}:${PORT}/v1beta1/${PROJECT_RESOURCE_NAME}/androidApps`; @@ -301,25 +301,25 @@ describe('ProjectManagementRequestHandler', () => { const pollingUrl = `https://${HOST}:${PORT}/v1/${OPERATION_RESOURCE_NAME}`; return requestHandler.createAndroidApp(PROJECT_RESOURCE_NAME, PACKAGE_NAME, DISPLAY_NAME) - .then((result) => { - expect(result).to.equal(expectedJsonResponse); - expect(stub) - .to.have.been.calledThrice - .and.calledWith({ - method: 'POST', - url: initialUrl, - data: initialData, - headers: expectedHeaders, - timeout: 10000, - }) - .and.calledWith({ - method: 'GET', - url: pollingUrl, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); - }); + .then((result) => { + expect(result).to.equal(expectedJsonResponse); + expect(stub) + .to.have.been.calledThrice + .and.calledWith({ + method: 'POST', + url: initialUrl, + data: initialData, + headers: expectedHeaders, + timeout: 10000, + }) + .and.calledWith({ + method: 'GET', + url: pollingUrl, + data: null, + headers: expectedHeaders, + timeout: 10000, + }); + }); }); }); @@ -331,10 +331,10 @@ describe('ProjectManagementRequestHandler', () => { stubs.push(stub); return requestHandler.createIosApp(PROJECT_RESOURCE_NAME, BUNDLE_ID, DISPLAY_NAME) - .should.eventually.be.rejected - .and.have.property( - 'message', - 'createIosApp\'s responseData.name must be a non-empty string. Response data: {}'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'createIosApp\'s responseData.name must be a non-empty string. Response data: {}'); }); it('should propagate polling API response returned errors', () => { @@ -349,13 +349,13 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().resolves(utils.responseFrom(pollErrorResult)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().resolves(utils.responseFrom(pollErrorResult)); stubs.push(stub); return requestHandler.createIosApp(PROJECT_RESOURCE_NAME, BUNDLE_ID, DISPLAY_NAME) - .should.eventually.be.rejected - .and.have.property('code', 'project-management/already-exists'); + .should.eventually.be.rejected + .and.have.property('code', 'project-management/already-exists'); }); it('should propagate polling API response thrown errors', () => { @@ -363,13 +363,13 @@ describe('ProjectManagementRequestHandler', () => { const pollError = 'second-poll-error'; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().returns(Promise.reject(pollError)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().returns(Promise.reject(pollError)); stubs.push(stub); return requestHandler.createIosApp(PROJECT_RESOURCE_NAME, BUNDLE_ID, DISPLAY_NAME) - .should.eventually.be.rejected - .and.equal(pollError); + .should.eventually.be.rejected + .and.equal(pollError); }); it('should succeed after multiple polls', () => { @@ -383,9 +383,9 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .onFirstCall().resolves(utils.responseFrom(initialResult)) - .onSecondCall().resolves(utils.responseFrom(firstPollResult)) - .onThirdCall().resolves(utils.responseFrom(secondPollResult)); + .onFirstCall().resolves(utils.responseFrom(initialResult)) + .onSecondCall().resolves(utils.responseFrom(firstPollResult)) + .onThirdCall().resolves(utils.responseFrom(secondPollResult)); stubs.push(stub); const initialUrl = `https://${HOST}:${PORT}/v1beta1/${PROJECT_RESOURCE_NAME}/iosApps`; @@ -397,25 +397,25 @@ describe('ProjectManagementRequestHandler', () => { const pollingUrl = `https://${HOST}:${PORT}/v1/${OPERATION_RESOURCE_NAME}`; return requestHandler.createIosApp(PROJECT_RESOURCE_NAME, BUNDLE_ID, DISPLAY_NAME) - .then((result) => { - expect(result).to.equal(expectedJsonResponse); - expect(stub) - .to.have.been.calledThrice - .and.calledWith({ - method: 'POST', - url: initialUrl, - data: initialData, - headers: expectedHeaders, - timeout: 10000, - }) - .and.calledWith({ - method: 'GET', - url: pollingUrl, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); - }); + .then((result) => { + expect(result).to.equal(expectedJsonResponse); + expect(stub) + .to.have.been.calledThrice + .and.calledWith({ + method: 'POST', + url: initialUrl, + data: initialData, + headers: expectedHeaders, + timeout: 10000, + }) + .and.calledWith({ + method: 'GET', + url: pollingUrl, + data: null, + headers: expectedHeaders, + timeout: 10000, + }); + }); }); }); @@ -423,7 +423,7 @@ describe('ProjectManagementRequestHandler', () => { const newDisplayName = 'test-new-display-name'; testHttpErrors( - () => requestHandler.setDisplayName(ANDROID_APP_RESOURCE_NAME, newDisplayName)); + () => requestHandler.setDisplayName(ANDROID_APP_RESOURCE_NAME, newDisplayName)); it('should succeed', () => { const stub = sinon.stub(HttpClient.prototype, 'send').resolves(utils.responseFrom({})); @@ -435,15 +435,15 @@ describe('ProjectManagementRequestHandler', () => { displayName: newDisplayName, }; return requestHandler.setDisplayName(ANDROID_APP_RESOURCE_NAME, newDisplayName) - .then(() => { - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'PATCH', - url, - data: requestData, - headers: expectedHeaders, - timeout: 10000, - }); + .then(() => { + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'PATCH', + url, + data: requestData, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -454,21 +454,21 @@ describe('ProjectManagementRequestHandler', () => { const expectedResult: any = { certificates: [] }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${ANDROID_APP_RESOURCE_NAME}/sha`; return requestHandler.getAndroidShaCertificates(ANDROID_APP_RESOURCE_NAME) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -476,7 +476,7 @@ describe('ProjectManagementRequestHandler', () => { const certificateToAdd = new ShaCertificate(VALID_SHA_1_HASH); testHttpErrors( - () => requestHandler.addAndroidShaCertificate(ANDROID_APP_RESOURCE_NAME, certificateToAdd)); + () => requestHandler.addAndroidShaCertificate(ANDROID_APP_RESOURCE_NAME, certificateToAdd)); it('should succeed', () => { const stub = sinon.stub(HttpClient.prototype, 'send').resolves(utils.responseFrom({})); @@ -488,15 +488,15 @@ describe('ProjectManagementRequestHandler', () => { certType: 'SHA_1', }; return requestHandler.addAndroidShaCertificate(ANDROID_APP_RESOURCE_NAME, certificateToAdd) - .then(() => { - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'POST', - url, - data: requestData, - headers: expectedHeaders, - timeout: 10000, - }); + .then(() => { + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'POST', + url, + data: requestData, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -509,21 +509,21 @@ describe('ProjectManagementRequestHandler', () => { }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${ANDROID_APP_RESOURCE_NAME}/config`; return requestHandler.getConfig(ANDROID_APP_RESOURCE_NAME) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -536,21 +536,21 @@ describe('ProjectManagementRequestHandler', () => { const expectedResult = { success: true }; const stub = sinon.stub(HttpClient.prototype, 'send') - .resolves(utils.responseFrom(expectedResult)); + .resolves(utils.responseFrom(expectedResult)); stubs.push(stub); const url = `https://${HOST}:${PORT}/v1beta1/${resourceName}`; return requestHandler.getResource(resourceName) - .then((result) => { - expect(result).to.deep.equal(expectedResult); - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'GET', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then((result) => { + expect(result).to.deep.equal(expectedResult); + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'GET', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); @@ -565,15 +565,15 @@ describe('ProjectManagementRequestHandler', () => { const url = `https://${HOST}:${PORT}/v1beta1/${resourceName}`; return requestHandler.deleteResource(resourceName) - .then(() => { - expect(stub).to.have.been.calledOnce.and.calledWith({ - method: 'DELETE', - url, - data: null, - headers: expectedHeaders, - timeout: 10000, - }); + .then(() => { + expect(stub).to.have.been.calledOnce.and.calledWith({ + method: 'DELETE', + url, + data: null, + headers: expectedHeaders, + timeout: 10000, }); + }); }); }); }); diff --git a/test/unit/project-management/project-management.spec.ts b/test/unit/project-management/project-management.spec.ts index cbf391f141..aecfb324bb 100644 --- a/test/unit/project-management/project-management.spec.ts +++ b/test/unit/project-management/project-management.spec.ts @@ -76,7 +76,7 @@ describe('ProjectManagement', () => { const projectManagementAny: any = ProjectManagement; return new projectManagementAny(invalidApp); }).to.throw( - 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'instance.'); }); }); @@ -86,7 +86,7 @@ describe('ProjectManagement', () => { const projectManagementAny: any = ProjectManagement; return new projectManagementAny(); }).to.throw( - 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'First argument passed to admin.projectManagement() must be a valid Firebase app ' + 'instance.'); }); @@ -116,48 +116,48 @@ describe('ProjectManagement', () => { describe('listAndroidApps', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.resolve(null)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'listAndroidApps()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'listAndroidApps()\'s responseData must be a non-null object. Response data: null'); }); it('should return empty array when API response missing "apps" field', () => { const partialApiResponse = {}; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.deep.equal([]); + .should.eventually.deep.equal([]); }); it('should throw when API response has non-array "apps" field', () => { const partialApiResponse = { apps: 'none' }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps" field must be present in the listAndroidApps() response data. Response data: ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps" field must be present in the listAndroidApps() response data. Response data: ' + JSON.stringify(partialApiResponse, null, 2)); }); @@ -167,14 +167,14 @@ describe('ProjectManagement', () => { }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps[].appId" field must be present in the listAndroidApps() response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps[].appId" field must be present in the listAndroidApps() response data. ' + `Response data: ${JSON.stringify(partialApiResponse, null, 2)}`); }); @@ -185,11 +185,11 @@ describe('ProjectManagement', () => { }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') - .returns(Promise.resolve(validListAndroidAppsApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAndroidApps') + .returns(Promise.resolve(validListAndroidAppsApiResponse)); stubs.push(stub); return projectManagement.listAndroidApps() - .should.eventually.deep.equal(validAndroidApps); + .should.eventually.deep.equal(validAndroidApps); }); }); @@ -200,48 +200,48 @@ describe('ProjectManagement', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.resolve(null)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'listIosApps()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'listIosApps()\'s responseData must be a non-null object. Response data: null'); }); it('should return empty array when API response missing "apps" field', () => { const partialApiResponse = {}; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.deep.equal([]); + .should.eventually.deep.equal([]); }); it('should throw when API response has non-array "apps" field', () => { const partialApiResponse = { apps: 'none' }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps" field must be present in the listIosApps() response data. Response data: ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps" field must be present in the listIosApps() response data. Response data: ' + JSON.stringify(partialApiResponse, null, 2)); }); @@ -251,14 +251,14 @@ describe('ProjectManagement', () => { }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps[].appId" field must be present in the listIosApps() response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps[].appId" field must be present in the listIosApps() response data. ' + `Response data: ${JSON.stringify(partialApiResponse, null, 2)}`); }); @@ -266,11 +266,11 @@ describe('ProjectManagement', () => { const validIosApps: IosApp[] = [projectManagement.iosApp(APP_ID)]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') - .returns(Promise.resolve(VALID_LIST_IOS_APPS_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'listIosApps') + .returns(Promise.resolve(VALID_LIST_IOS_APPS_API_RESPONSE)); stubs.push(stub); return projectManagement.listIosApps() - .should.eventually.deep.equal(validIosApps); + .should.eventually.deep.equal(validIosApps); }); }); @@ -297,35 +297,35 @@ describe('ProjectManagement', () => { describe('createAndroidApp', () => { it('should propagate intial API response errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.createAndroidApp(PACKAGE_NAME) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw when initial API response is null', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') + .returns(Promise.resolve(null)); stubs.push(stub); return projectManagement.createAndroidApp(PACKAGE_NAME) - .should.eventually.be.rejected - .and.have.property( - 'message', - 'createAndroidApp()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'createAndroidApp()\'s responseData must be a non-null object. Response data: null'); }); it('should throw when initial API response.appId is undefined', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') - .returns(Promise.resolve({})); + .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') + .returns(Promise.resolve({})); stubs.push(stub); return projectManagement.createAndroidApp(PACKAGE_NAME) - .should.eventually.be.rejected - .and.have.property( - 'message', - '"responseData.appId" field must be present in createAndroidApp()\'s response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"responseData.appId" field must be present in createAndroidApp()\'s response data. ' + 'Response data: {}'); }); @@ -334,46 +334,46 @@ describe('ProjectManagement', () => { const validCreateAppResponse = { appId: APP_ID }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') - .returns(Promise.resolve(validCreateAppResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'createAndroidApp') + .returns(Promise.resolve(validCreateAppResponse)); stubs.push(stub); return projectManagement.createAndroidApp(PACKAGE_NAME) - .should.eventually.deep.equal(createdAndroidApp); + .should.eventually.deep.equal(createdAndroidApp); }); }); describe('createIosApp', () => { it('should propagate intial API response errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.createIosApp(BUNDLE_ID) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw when initial API response is null', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') + .returns(Promise.resolve(null)); stubs.push(stub); return projectManagement.createIosApp(BUNDLE_ID) - .should.eventually.be.rejected - .and.have.property( - 'message', - 'createIosApp()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'createIosApp()\'s responseData must be a non-null object. Response data: null'); }); it('should throw when initial API response.appId is undefined', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') - .returns(Promise.resolve({})); + .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') + .returns(Promise.resolve({})); stubs.push(stub); return projectManagement.createIosApp(BUNDLE_ID) - .should.eventually.be.rejected - .and.have.property( - 'message', - '"responseData.appId" field must be present in createIosApp()\'s response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"responseData.appId" field must be present in createIosApp()\'s response data. ' + 'Response data: {}'); }); @@ -382,11 +382,11 @@ describe('ProjectManagement', () => { const validCreateAppResponse = { appId: APP_ID }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') - .returns(Promise.resolve(validCreateAppResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'createIosApp') + .returns(Promise.resolve(validCreateAppResponse)); stubs.push(stub); return projectManagement.createIosApp(BUNDLE_ID) - .should.eventually.deep.equal(createdIosApp); + .should.eventually.deep.equal(createdIosApp); }); }); @@ -415,48 +415,48 @@ describe('ProjectManagement', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should throw with null API response', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(null)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(null)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - 'listAppMetadata()\'s responseData must be a non-null object. Response data: null'); + .should.eventually.be.rejected + .and.have.property( + 'message', + 'listAppMetadata()\'s responseData must be a non-null object. Response data: null'); }); it('should return empty array when API response missing "apps" field', () => { const partialApiResponse = {}; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.deep.equal([]); + .should.eventually.deep.equal([]); }); it('should throw when API response has non-array "apps" field', () => { const partialApiResponse = { apps: 'none' }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps" field must be present in the listAppMetadata() response data. Response data: ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps" field must be present in the listAppMetadata() response data. Response data: ' + JSON.stringify(partialApiResponse, null, 2)); }); @@ -466,14 +466,14 @@ describe('ProjectManagement', () => { }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(partialApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(partialApiResponse)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps[].appId" field must be present in the listAppMetadata() response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps[].appId" field must be present in the listAppMetadata() response data. ' + `Response data: ${JSON.stringify(partialApiResponse, null, 2)}`); }); @@ -485,14 +485,14 @@ describe('ProjectManagement', () => { }; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(missingPlatformApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(missingPlatformApiResponse)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.be.rejected - .and.have.property( - 'message', - '"apps[].platform" field must be present in the listAppMetadata() response data. ' + .should.eventually.be.rejected + .and.have.property( + 'message', + '"apps[].platform" field must be present in the listAppMetadata() response data. ' + `Response data: ${JSON.stringify(missingPlatformApiResponse, null, 2)}`); }); @@ -520,11 +520,11 @@ describe('ProjectManagement', () => { }, ]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(VALID_LIST_APP_METADATA_API_RESPONSE)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(VALID_LIST_APP_METADATA_API_RESPONSE)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.deep.equal(expectedAppMetadata); + .should.eventually.deep.equal(expectedAppMetadata); }); it('should resolve with "apps[].platform" to be "PLATFORM_UNKNOWN" for web app', () => { @@ -543,28 +543,28 @@ describe('ProjectManagement', () => { }]; const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') - .returns(Promise.resolve(webPlatformApiResponse)); + .stub(ProjectManagementRequestHandler.prototype, 'listAppMetadata') + .returns(Promise.resolve(webPlatformApiResponse)); stubs.push(stub); return projectManagement.listAppMetadata() - .should.eventually.deep.equal(expectedAppMetadata); + .should.eventually.deep.equal(expectedAppMetadata); }); }); describe('setDisplayName', () => { it('should propagate API errors', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.reject(EXPECTED_ERROR)); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.reject(EXPECTED_ERROR)); stubs.push(stub); return projectManagement.setDisplayName(DISPLAY_NAME_ANDROID) - .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); + .should.eventually.be.rejected.and.equal(EXPECTED_ERROR); }); it('should resolve on success', () => { const stub = sinon - .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') - .returns(Promise.resolve()); + .stub(ProjectManagementRequestHandler.prototype, 'setDisplayName') + .returns(Promise.resolve()); stubs.push(stub); return projectManagement.setDisplayName(DISPLAY_NAME_ANDROID).should.eventually.be.fulfilled; }); diff --git a/test/unit/security-rules/security-rules.spec.ts b/test/unit/security-rules/security-rules.spec.ts index 63c5cf12f5..e10865d823 100644 --- a/test/unit/security-rules/security-rules.spec.ts +++ b/test/unit/security-rules/security-rules.spec.ts @@ -64,7 +64,7 @@ describe('SecurityRules', () => { 'Bucket name not specified or invalid. Specify a default bucket name via the ' + 'storageBucket option when initializing the app, or specify the bucket name ' + 'explicitly when calling the rules API.', - ); + ); const INVALID_BUCKET_NAMES: any[] = [null, '', true, false, 1, 0, {}, []]; const INVALID_SOURCES: any[] = [null, undefined, '', 1, true, {}, []]; @@ -114,7 +114,7 @@ describe('SecurityRules', () => { const securityRulesAny: any = SecurityRules; return new securityRulesAny(invalidApp); }).to.throw( - 'First argument passed to admin.securityRules() must be a valid Firebase app ' + 'First argument passed to admin.securityRules() must be a valid Firebase app ' + 'instance.'); }); }); @@ -124,7 +124,7 @@ describe('SecurityRules', () => { const securityRulesAny: any = SecurityRules; return new securityRulesAny(); }).to.throw( - 'First argument passed to admin.securityRules() must be a valid Firebase app ' + 'First argument passed to admin.securityRules() must be a valid Firebase app ' + 'instance.'); }); @@ -202,8 +202,8 @@ describe('SecurityRules', () => { const response = deepCopy(FIRESTORE_RULESET_RESPONSE); response.source = null; const stub = sinon - .stub(SecurityRulesApiClient.prototype, 'getRuleset') - .resolves(response); + .stub(SecurityRulesApiClient.prototype, 'getRuleset') + .resolves(response); stubs.push(stub); return securityRules.getRuleset('foo') .should.eventually.be.rejected.and.have.property( diff --git a/test/unit/storage/storage.spec.ts b/test/unit/storage/storage.spec.ts index 4b95529ef3..55fc8ff6df 100644 --- a/test/unit/storage/storage.spec.ts +++ b/test/unit/storage/storage.spec.ts @@ -92,12 +92,12 @@ describe('Storage', () => { 'explicitly when calling the getBucket() method.'; const invalidNames = [null, NaN, 0, 1, true, false, '', [], [1, 'a'], {}, { a: 1}, _.noop]; invalidNames.forEach((invalidName) => { - it(`should throw given invalid bucket name: ${ JSON.stringify(invalidName) }`, () => { - expect(() => { - const bucketAny: any = storage.bucket; - bucketAny(invalidName); - }).to.throw(expectedError); - }); + it(`should throw given invalid bucket name: ${ JSON.stringify(invalidName) }`, () => { + expect(() => { + const bucketAny: any = storage.bucket; + bucketAny(invalidName); + }).to.throw(expectedError); + }); }); }); diff --git a/test/unit/utils/api-request.spec.ts b/test/unit/utils/api-request.spec.ts index 440a9de044..c20073bab4 100644 --- a/test/unit/utils/api-request.spec.ts +++ b/test/unit/utils/api-request.spec.ts @@ -378,9 +378,9 @@ describe('HttpClient', () => { 'My-Custom-Header': 'CustomValue', }, }).post(mockPath, reqData) - .reply(200, respData, { - 'content-type': 'application/json', - }); + .reply(200, respData, { + 'content-type': 'application/json', + }); mockedRequests.push(scope); const client = new HttpClient(); return client.send({ @@ -409,9 +409,9 @@ describe('HttpClient', () => { }, }, }).post(mockPath, reqData) - .reply(200, respData, { - 'content-type': 'application/json', - }); + .reply(200, respData, { + 'content-type': 'application/json', + }); mockedRequests.push(scope); const client = new HttpClient(); return client.send({ @@ -440,9 +440,9 @@ describe('HttpClient', () => { 'My-Custom-Header': 'CustomValue', }, }).post(mockPath, reqData) - .reply(200, {success: true}, { - 'content-type': 'application/json', - }); + .reply(200, {success: true}, { + 'content-type': 'application/json', + }); mockedRequests.push(scope); const client = new HttpClient(); const request: HttpRequestConfig = { @@ -470,10 +470,10 @@ describe('HttpClient', () => { 'My-Custom-Header': 'CustomValue', }, }).get(mockPath) - .query(reqData) - .reply(200, respData, { - 'content-type': 'application/json', - }); + .query(reqData) + .reply(200, respData, { + 'content-type': 'application/json', + }); mockedRequests.push(scope); const client = new HttpClient(); return client.send({ @@ -558,10 +558,10 @@ describe('HttpClient', () => { 'My-Custom-Header': 'CustomValue', }, }).head(mockPath) - .query(reqData) - .reply(200, respData, { - 'content-type': 'application/json', - }); + .query(reqData) + .reply(200, respData, { + 'content-type': 'application/json', + }); mockedRequests.push(scope); const client = new HttpClient(); return client.send({ diff --git a/test/unit/utils/error.spec.ts b/test/unit/utils/error.spec.ts index 0791b42769..41e977f725 100755 --- a/test/unit/utils/error.spec.ts +++ b/test/unit/utils/error.spec.ts @@ -80,7 +80,7 @@ describe('FirebaseAuthError', () => { const error = FirebaseAuthError.fromServerError('USER_NOT_FOUND'); expect(error.code).to.be.equal('auth/user-not-found'); expect(error.message).to.be.equal( - 'There is no user record corresponding to the provided identifier.'); + 'There is no user record corresponding to the provided identifier.'); }); it('should initialize an error from an unexpected server code', () => { @@ -100,22 +100,22 @@ describe('FirebaseAuthError', () => { describe('with message specified', () => { it('should initialize an error from an expected server code', () => { const error = FirebaseAuthError.fromServerError( - 'USER_NOT_FOUND', 'Invalid uid'); + 'USER_NOT_FOUND', 'Invalid uid'); expect(error.code).to.be.equal('auth/user-not-found'); expect(error.message).to.be.equal('Invalid uid'); }); it('should initialize an error from an unexpected server code', () => { const error = FirebaseAuthError.fromServerError( - 'UNEXPECTED_ERROR', 'An unexpected error occurred.'); + 'UNEXPECTED_ERROR', 'An unexpected error occurred.'); expect(error.code).to.be.equal('auth/internal-error'); expect(error.message).to.be.equal('An unexpected error occurred.'); }); it('should initialize an error from an expected server with server detailed message', () => { const error = FirebaseAuthError.fromServerError( - 'CONFIGURATION_NOT_FOUND : more details', - 'Ignored message'); + 'CONFIGURATION_NOT_FOUND : more details', + 'Ignored message'); expect(error.code).to.be.equal('auth/configuration-not-found'); expect(error.message).to.be.equal('more details'); }); @@ -131,14 +131,14 @@ describe('FirebaseAuthError', () => { it('should not include raw server response from an expected server code', () => { const error = FirebaseAuthError.fromServerError( - 'USER_NOT_FOUND', 'Invalid uid', mockRawServerResponse); + 'USER_NOT_FOUND', 'Invalid uid', mockRawServerResponse); expect(error.code).to.be.equal('auth/user-not-found'); expect(error.message).to.be.equal('Invalid uid'); }); it('should include raw server response from an unexpected server code', () => { const error = FirebaseAuthError.fromServerError( - 'UNEXPECTED_ERROR', 'An unexpected error occurred.', mockRawServerResponse); + 'UNEXPECTED_ERROR', 'An unexpected error occurred.', mockRawServerResponse); expect(error.code).to.be.equal('auth/internal-error'); expect(error.message).to.be.equal( 'An unexpected error occurred. Raw server response: "' + diff --git a/tslint-test.json b/tslint-test.json deleted file mode 100644 index 27fa06e5bd..0000000000 --- a/tslint-test.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "tslint:latest", - "rules": { - "interface-name": false, - "member-ordering": [true, - "public-before-private", - "static-before-instance", - "variables-before-functions" - ], - "prefer-object-spread": false, - "no-implicit-dependencies": [true, "dev", "optional"], - "max-classes-per-file": false, - "max-line-length": [true, 120], - "no-consecutive-blank-lines": false, - "object-literal-sort-keys": false, - "ordered-imports": false, - "quotemark": [true, "single", "avoid-escape"], - "no-unused-expression": false, - "variable-name": [true, "ban-keywords", "check-format", "allow-trailing-underscore"] - } -} diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 5626542a6e..0000000000 --- a/tslint.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "tslint:latest", - "rules": { - "interface-name": false, - "member-ordering": [true, - "public-before-private", - "static-before-instance", - "variables-before-functions" - ], - "prefer-object-spread": false, - "no-implicit-dependencies": [true, "dev", "optional"], - "max-classes-per-file": false, - "max-line-length": [true, 120], - "no-consecutive-blank-lines": false, - "object-literal-sort-keys": false, - "ordered-imports": false, - "quotemark": [true, "single", "avoid-escape"], - "variable-name": [true, "ban-keywords", "check-format", "allow-trailing-underscore"] - } -}