From b4dad1e11ca0e3ef2fd015fc4113f45fc8d7eb4c Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Fri, 6 Nov 2026 23:49:54 +0000 Subject: [PATCH] refactor: fix @typescript-eslint/restrict-plus-operands in 10 root src files (b/582886038) --- src/accountExporter.spec.ts | 6 +++--- src/accountExporter.ts | 2 +- src/accountImporter.ts | 13 +++++++------ src/config.ts | 4 ++-- src/localFunction.ts | 6 +++--- src/profileReport.spec.ts | 2 +- src/profileReport.ts | 16 ++++++++++++---- src/profiler.ts | 2 +- src/projectUtils.ts | 5 +++-- src/utils.ts | 2 +- 10 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/accountExporter.spec.ts b/src/accountExporter.spec.ts index a6457bdecf7..e10373025df 100644 --- a/src/accountExporter.spec.ts +++ b/src/accountExporter.spec.ts @@ -130,7 +130,7 @@ describe("accountExporter", () => { ",false,,," + userList[j].displayName + Array(22).join(",") + // A lot of empty fields... - userList[j].disabled; + String(userList[j].disabled); if (j === 6) { expectedEntry += ",,,,,,123234234,test@test.org,,https://example.com/photo.jpg" + Array(18).join(","); @@ -184,7 +184,7 @@ describe("accountExporter", () => { singleUser.displayName + '"' + Array(22).join(",") + // A lot of empty fields. - singleUser.disabled; + String(singleUser.disabled); expect(spyWrite.getCall(0).args[0]).to.eq(expectedEntry + Array(27).join(",") + os.EOL); expect(nock.isDone()).to.be.true; }); @@ -229,7 +229,7 @@ describe("accountExporter", () => { ",false,,," + '"Foo ""Bar"" Baz"' + Array(22).join(",") + // A lot of empty fields. - singleUser.disabled; + String(singleUser.disabled); expect(spyWrite.getCall(0).args[0]).to.eq(expectedEntry + Array(27).join(",") + os.EOL); expect(nock.isDone()).to.be.true; }); diff --git a/src/accountExporter.ts b/src/accountExporter.ts index 22c07a7e307..c2a5117e993 100644 --- a/src/accountExporter.ts +++ b/src/accountExporter.ts @@ -204,7 +204,7 @@ export async function serialExportUsers(projectId: string, options: any): Promis const userList = ret.body.users; if (userList && userList.length > 0) { options.writeUsersToFile(userList, options.format, options.writeStream); - utils.logSuccess("Exported " + userList.length + " account(s) successfully."); + utils.logSuccess(`Exported ${String(userList.length)} account(s) successfully.`); // The identitytoolkit API do not return a nextPageToken value // consistently when the last page is reached if (!ret.body.nextPageToken) { diff --git a/src/accountImporter.ts b/src/accountImporter.ts index cea4c12358d..6f2045bd60e 100644 --- a/src/accountImporter.ts +++ b/src/accountImporter.ts @@ -184,6 +184,7 @@ function validateRequiredParameters(options: any): any { return { valid: true }; } const hashAlgo = options.hashAlgo.toUpperCase(); + const hashAlgoName = String(options.hashAlgo); let roundsNum; switch (hashAlgo) { case "HMAC_SHA512": @@ -192,7 +193,7 @@ function validateRequiredParameters(options: any): any { case "HMAC_MD5": if (!options.hashKey || options.hashKey === "") { throw new FirebaseError( - "Must provide hash key(base64 encoded) for hash algorithm " + options.hashAlgo, + "Must provide hash key(base64 encoded) for hash algorithm " + hashAlgoName, ); } return { hashAlgo: hashAlgo, hashKey: options.hashKey, valid: true }; @@ -215,26 +216,26 @@ function validateRequiredParameters(options: any): any { roundsNum = parseInt(options.rounds, 10); if (isNaN(roundsNum) || roundsNum < 0 || roundsNum > 120000) { throw new FirebaseError( - "Must provide valid rounds(0..120000) for hash algorithm " + options.hashAlgo, + "Must provide valid rounds(0..120000) for hash algorithm " + hashAlgoName, ); } return { hashAlgo: hashAlgo, rounds: options.rounds, valid: true }; case "SCRYPT": { if (!options.hashKey || options.hashKey === "") { throw new FirebaseError( - "Must provide hash key(base64 encoded) for hash algorithm " + options.hashAlgo, + "Must provide hash key(base64 encoded) for hash algorithm " + hashAlgoName, ); } roundsNum = parseInt(options.rounds, 10); if (isNaN(roundsNum) || roundsNum <= 0 || roundsNum > 8) { throw new FirebaseError( - "Must provide valid rounds(1..8) for hash algorithm " + options.hashAlgo, + "Must provide valid rounds(1..8) for hash algorithm " + hashAlgoName, ); } const memCost = parseInt(options.memCost, 10); if (isNaN(memCost) || memCost <= 0 || memCost > 14) { throw new FirebaseError( - "Must provide valid memory cost(1..14) for hash algorithm " + options.hashAlgo, + "Must provide valid memory cost(1..14) for hash algorithm " + hashAlgoName, ); } let saltSeparator = ""; @@ -321,7 +322,7 @@ export function validateUserJson(userJson: any): { error?: string } { } async function sendRequest(projectId: string, userList: any[], hashOptions: any): Promise { - logger.info("Starting importing " + userList.length + " account(s)."); + logger.info(`Starting importing ${userList.length} account(s).`); const postData = genUploadAccountPostBody(projectId, userList, hashOptions); return apiClient .post("/identitytoolkit/v3/relyingparty/uploadAccount", postData, { diff --git a/src/config.ts b/src/config.ts index cd20b9e1fa0..8b983efeb50 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,7 +8,7 @@ import * as fs from "fs-extra"; import * as path from "path"; import { detectProjectRoot } from "./detectProjectRoot"; -import { FirebaseError } from "./error"; +import { FirebaseError, getErrMsg } from "./error"; import * as fsutils from "./fsutils"; import { confirm } from "./prompt"; import { resolveProjectPath } from "./projectPath"; @@ -371,7 +371,7 @@ export class Config { return new Config(data, options); } catch (e: any) { - throw new FirebaseError(`There was an error loading ${filename}:\n\n` + e.message, { + throw new FirebaseError(`There was an error loading ${filename}:\n\n${getErrMsg(e)}`, { exit: 1, }); } diff --git a/src/localFunction.ts b/src/localFunction.ts index a722cb010e8..31d47b7eca3 100644 --- a/src/localFunction.ts +++ b/src/localFunction.ts @@ -32,7 +32,7 @@ export default class LocalFunction { return resource.replace(this.paramWildcardRegex, (wildcard: string) => { const wildcardNoBraces = wildcard.slice(1, -1); // .slice removes '{' and '}' from wildcard const sub = params?.[wildcardNoBraces]; - return sub || wildcardNoBraces + utils.randomInt(1, 9); + return sub || `${wildcardNoBraces}${utils.randomInt(1, 9)}`; }); } @@ -219,9 +219,9 @@ export default class LocalFunction { private requestCallBack(err: unknown, response?: ClientResponse, body?: string | object) { if (err) { - return console.warn("\nERROR SENDING REQUEST: " + err); + return console.warn(`\nERROR SENDING REQUEST: ${String(err)}`); } - const status = response ? response.status + ", " : ""; + const status = response ? `${response.status}, ` : ""; // If the body is a string we want to check if we can parse it as JSON // and pretty-print it. We can't blindly stringify because stringifying diff --git a/src/profileReport.spec.ts b/src/profileReport.spec.ts index 26cbf160d48..4165fb2f38d 100644 --- a/src/profileReport.spec.ts +++ b/src/profileReport.spec.ts @@ -4,7 +4,7 @@ import * as stream from "stream"; import { extractJSON, extractReadableIndex, formatNumber, ProfileReport } from "./profileReport"; import { SAMPLE_INPUT_PATH, SAMPLE_OUTPUT_PATH } from "./test/fixtures/profiler-data"; -function combinerFunc(obj1: any, obj2: any): any { +function combinerFunc(obj1: { count: number }, obj2: { count: number }): { count: number } { return { count: obj1.count + obj2.count }; } diff --git a/src/profileReport.ts b/src/profileReport.ts index 4a434c7f9b7..631abbbf9f8 100644 --- a/src/profileReport.ts +++ b/src/profileReport.ts @@ -64,7 +64,7 @@ export function formatNumber(num: number) { export function formatBytes(bytes: number) { const threshold = 1000; if (Math.round(bytes) < threshold) { - return bytes + " B"; + return `${bytes} B`; } const units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; let u = -1; @@ -359,7 +359,7 @@ export class ProfileReport { }, }); const unindexed = this.collapsePaths(this.state.unindexed, (u1: any, u2: any) => { - _.mergeWith(u1, u2, (p1, p2) => { + _.mergeWith(u1, u2, (p1: { times: number; query: unknown }, p2: { times: number }) => { return { times: p1.times + p2.times, query: p1.query, @@ -386,7 +386,8 @@ export class ProfileReport { border: this.options.isFile ? [] : ["grey"], }, }); - const data = this.collapsePaths(pureData, (b1: any, b2: any) => { + type Bandwidth = { bytes: number; times: number }; + const data = this.collapsePaths(pureData, (b1: Bandwidth, b2: Bandwidth) => { return { bytes: b1.bytes + b2.bytes, times: b1.times + b2.times, @@ -468,7 +469,14 @@ export class ProfileReport { border: this.options.isFile ? [] : ["grey"], }, }); - const data = this.collapsePaths(pureData, (s1: any, s2: any) => { + type SpeedStats = { + times: number; + millis: number; + pendingCount: number; + pendingTime: number; + rejected: number; + }; + const data = this.collapsePaths(pureData, (s1: SpeedStats, s2: SpeedStats) => { return { times: s1.times + s2.times, millis: s1.millis + s2.millis, diff --git a/src/profiler.ts b/src/profiler.ts index edbe76a96c5..e0e5b98be79 100644 --- a/src/profiler.ts +++ b/src/profiler.ts @@ -86,7 +86,7 @@ export async function profiler(options: any): Promise { // If the response stream is closed, this handler is called (not // necessarially an error condition). res.body.on("end", () => { - spinner.text = counter + " operations recorded.\n"; + spinner.text = `${counter} operations recorded.\n`; }); // If the duration passes or another exception happens, this handler is // called. diff --git a/src/projectUtils.ts b/src/projectUtils.ts index 7a16b7f2fc7..d4618a2d4ed 100644 --- a/src/projectUtils.ts +++ b/src/projectUtils.ts @@ -44,6 +44,7 @@ export function needProjectId({ const aliasCount = Object.keys(aliases).length; if (aliasCount === 0) { + // marked returns a string unless called with { async: true }. throw new FirebaseError( "No currently active project.\n" + "To run this command, you need to specify a project. You have two options:\n" + @@ -56,9 +57,9 @@ export function needProjectId({ "To list all the Firebase projects to which you have access, run " + clc.bold("firebase projects:list") + ".\n" + - marked( + (marked( "To learn about active projects for the CLI, visit https://firebase.google.com/docs/cli#project_aliases", - ), + ) as string), ); } diff --git a/src/utils.ts b/src/utils.ts index a657208657a..0bfbd39c526 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1133,7 +1133,7 @@ export function formatFilesize(bytes: number, decimals = 2): string { const dm = decimals < 0 ? 0 : decimals; const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`; } export type Limit = (fn: () => Promise) => Promise;