Skip to content
2 changes: 0 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ module.exports = {
"@typescript-eslint/no-unsafe-return": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/no-use-before-define": ["warn", { functions: false, typedefs: false }], // TODO(bkendall): change to error.
"@typescript-eslint/no-var-requires": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/prefer-includes": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/prefer-regexp-exec": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/prefer-string-starts-ends-with": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/restrict-plus-operands": "warn", // TODO(bkendall): remove, allow to error.
"@typescript-eslint/restrict-template-expressions": "warn", // TODO(bkendall): remove, allow to error.
"no-constant-condition": "warn", // TODO(bkendall): remove, allow to error.
Expand Down
2 changes: 1 addition & 1 deletion src/apphosting/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
// SSL.
const maybeNodeError = err as { cause: { code: string }; code: string };
if (
/HANDSHAKE_FAILURE/.test(maybeNodeError?.cause?.code) ||
maybeNodeError?.cause?.code?.includes("HANDSHAKE_FAILURE") ||
Comment thread
joehan marked this conversation as resolved.
"EPROTO" === maybeNodeError?.code
) {
return false;
Expand Down Expand Up @@ -213,7 +213,7 @@
projectId: string,
backendId: string,
nonInteractive: boolean,
rootDir: string = "/",

Check warning on line 216 in src/apphosting/backend.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Type string trivially inferred from a string literal, remove type annotation
): Promise<{ backend: Backend; location: string }> {
const location = await promptLocation(
projectId,
Expand Down Expand Up @@ -349,7 +349,7 @@
* Prompts the user for a backend id and verifies that it doesn't match a pre-existing backend.
*/
export async function promptNewBackendId(projectId: string, location: string): Promise<string> {
while (true) {

Check warning on line 352 in src/apphosting/backend.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected constant condition
const backendId = await input({
default: "my-web-app",
message: "Provide a name for your backend [3-30 characters]",
Expand Down Expand Up @@ -723,7 +723,7 @@
message: locationDisambugationPrompt,
choices: [...backendsByLocation.keys()],
});
return backendsByLocation.get(location)!;

Check warning on line 726 in src/apphosting/backend.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Forbidden non-null assertion
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/deploy/firestore/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
export interface IndexContext {
databaseId: string;
indexesFileName: string;
indexesRawSpec: any; // could be the old v1beta1 indexes spec or the new v1/v1 format

Check warning on line 25 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
}

/**
Expand All @@ -33,13 +33,13 @@
* @param rulesFile File name for the Firestore rules to be deployed.
*/
function prepareRules(
context: any,

Check warning on line 36 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
rulesDeploy: RulesDeploy,
databaseId: string,
rulesFile: string,
): void {
rulesDeploy.addFile(rulesFile, databaseId);
context.firestore.rules.push({

Check warning on line 42 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe call of an `any` typed value

Check warning on line 42 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .firestore on an `any` value
databaseId,
rulesFile,
} as RulesContext);
Expand All @@ -53,19 +53,19 @@
* @param indexesFileName File name for the index configs to be parsed from.
*/
function prepareIndexes(
context: any,

Check warning on line 56 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unexpected any. Specify a different type
options: Options,
databaseId: string,
indexesFileName: string,
): void {
const indexesPath = options.config.path(indexesFileName);
const indexesRawSpec = loadCJSON(indexesPath);

Check warning on line 62 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe assignment of an `any` value

utils.logBullet(
`${clc.bold(clc.cyan("firestore:"))} reading indexes from ${clc.bold(indexesFileName)}...`,
);

context.firestore.indexes.push({

Check warning on line 68 in src/deploy/firestore/prepare.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .firestore on an `any` value
databaseId,
indexesFileName,
indexesRawSpec,
Expand Down Expand Up @@ -156,15 +156,15 @@

// Used for edge case when deploying to a named database
// https://github.com/firebase/firebase-tools/pull/6129
const excludeRules = targets.indexOf("firestore:indexes") >= 0;
const excludeIndexes = targets.indexOf("firestore:rules") >= 0;
const excludeRules = targets.includes("firestore:indexes");
const excludeIndexes = targets.includes("firestore:rules");

// Used for edge case when deploying --only firestore:rules,firestore:indexes
// https://github.com/firebase/firebase-tools/issues/6857
const includeRules = targets.indexOf("firestore:rules") >= 0;
const includeIndexes = targets.indexOf("firestore:indexes") >= 0;
const includeRules = targets.includes("firestore:rules");
const includeIndexes = targets.includes("firestore:indexes");

const onlyFirestore = targets.indexOf("firestore") >= 0;
const onlyFirestore = targets.includes("firestore");

context.firestoreIndexes = !excludeIndexes || includeIndexes || onlyFirestore;
context.firestoreRules = !excludeRules || includeRules || onlyFirestore;
Expand Down
2 changes: 1 addition & 1 deletion src/emulator/apphosting/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ async function tripFirebasePostinstall(
if (
dependency.name === "@firebase/util" &&
semverGte(dependency.version, "1.11.0") &&
firebaseUtilPaths.indexOf(dependency.path) === -1
!firebaseUtilPaths.includes(dependency.path)
) {
firebaseUtilPaths.push(dependency.path);
}
Expand Down
2 changes: 1 addition & 1 deletion src/emulator/auth/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function isValidPhoneNumber(phoneNumber: string): boolean {
// is not worth the effort and bloat (500+ kB). libphonenumber-js is not used
// either since it has different behaviors and may block numbers that are
// valid in production.
return /^\+/.test(phoneNumber);
return phoneNumber.startsWith("+");
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/emulator/dataconnect/pgliteServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export class PostgresServer {
await db.waitReady;
return db;
} catch (err: unknown) {
if (pg17Dir && hasMessage(err) && /Database already exists/.test(err.message)) {
if (pg17Dir && hasMessage(err) && err.message.includes("Database already exists")) {
// Clear out the current pglite data
fs.rmSync(pg17Dir, { force: true, recursive: true });
const db = new PGlite({ ...baseArgs, dataDir: pg17Dir });
Expand Down
2 changes: 1 addition & 1 deletion src/emulator/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ function removeOldFiles(
for (const file of files) {
const fullFilePath = path.join(emulator.opts.cacheDir, file);

if (file.indexOf(emulator.opts.namePrefix) < 0) {
if (!file.includes(emulator.opts.namePrefix)) {
// This file is not related to this emulator, could be a JAR
// from a different emulator or just a random file.
continue;
Expand Down
12 changes: 8 additions & 4 deletions src/emulator/downloadableEmulators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const EMULATOR_UPDATE_DETAILS: {
* generate download details for a single emulator, based on the host environment.
* pulls data from `downloadableEmulatorInfo.json`.
* @param emulator The name of the downloadable emulator to get details for.
* @returns The download details for the specified emulator.
* @return The download details for the specified emulator.
*/
function generateDownloadDetails(emulator: DownloadableEmulators): EmulatorDownloadDetails {
const emulatorUiDetails = experiments.isEnabled("emulatoruisnapshot")
Expand Down Expand Up @@ -653,14 +653,18 @@ export async function start(
return _runBinary(emulator, command, extraEnv);
}

/**
*
*/
export function isIncomaptibleArchError(err: unknown): boolean {
return (
hasMessage(err) &&
/Unknown system error/.test(err.message ?? "") &&
process.platform === "darwin"
hasMessage(err) && err.message.includes("Unknown system error") && process.platform === "darwin"
);
}

/**
*
*/
export function emulatorVersionOverride(emulator: DownloadableEmulators) {
return process.env[`${emulator.toUpperCase()}_EMULATOR_VERSION`];
}
2 changes: 1 addition & 1 deletion src/firestore/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function assertHasOneOf(obj: any, props: string[]): void {
*/
export function assertEnum(obj: any, prop: string, valid: any[]): void {
const objString = clc.cyan(JSON.stringify(obj));
if (valid.indexOf(obj[prop]) < 0) {
if (!valid.includes(obj[prop])) {
throw new FirebaseError(`Field "${prop}" must be one of ${valid.join(", ")}: ${objString}`);
}
}
Expand Down
30 changes: 28 additions & 2 deletions src/profileReport.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from "chai";

import * as stream from "stream";
import { extractReadableIndex, formatNumber, ProfileReport } from "./profileReport";

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 {
Expand Down Expand Up @@ -100,4 +100,30 @@ describe("profilerReport", () => {
const result = extractReadableIndex(query);
expect(result).to.eq(".value");
});

describe("extractJSON", () => {
it("should return parsed JSON when line starts with data: and input is false", () => {
const line = 'data: {"path":["public"],"name":"rest-read"}';
const result = extractJSON(line, false);
expect(result).to.deep.eq({ path: ["public"], name: "rest-read" });
});

it("should return null when line does not start with data: and input is false", () => {
const line = "event: log";
const result = extractJSON(line, false);
expect(result).to.be.null;
});

it("should return parsed JSON directly when input is true", () => {
const line = '{"path":["public"],"name":"rest-read"}';
const result = extractJSON(line, true);
expect(result).to.deep.eq({ path: ["public"], name: "rest-read" });
});

it("should return null for malformed JSON", () => {
const line = "data: {invalid-json}";
const result = extractJSON(line, false);
expect(result).to.be.null;
});
});
});
21 changes: 17 additions & 4 deletions src/profileReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import * as readline from "readline";
import { FirebaseError } from "./error";
import { logger } from "./logger";

const DATA_LINE_REGEX = /^data: /;

const BANDWIDTH_NOTE =
"NOTE: The numbers reported here are only estimates of the data" +
" payloads from read operations. They are NOT a valid measure of your bandwidth bill.";
Expand All @@ -25,11 +23,14 @@ const COLLAPSE_WILDCARD = ["$wildcard"];

// 'static' helper methods

/**
*
*/
export function extractJSON(line: string, input: any): string | null {
if (!input && !DATA_LINE_REGEX.test(line)) {
if (!input && !line.startsWith("data: ")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the prefix check has been modernized to line.startsWith('data: ') (which is 6 characters long), the subsequent line.substring(5) on line 30 is now inconsistent as it leaves a leading space in the string before parsing. Consider updating it to line.substring(6) or line.slice(6) to cleanly remove the entire prefix.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit d6542d9: Updated line.substring(5) to line.substring(6) to correctly strip the 6-character "data: " prefix matching line.startsWith("data: "). Also added comprehensive unit tests for extractJSON covering SSE and non-SSE cases in src/profileReport.spec.ts.

return null;
} else if (!input) {
line = line.substring(5);
line = line.substring(6);
}
try {
return JSON.parse(line);
Expand All @@ -38,10 +39,16 @@ export function extractJSON(line: string, input: any): string | null {
}
}

/**
*
*/
export function pathString(path: string[]): string {
return `/${path ? path.join("/") : ""}`;
}

/**
*
*/
export function formatNumber(num: number) {
const parts = num.toFixed(2).split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
Expand All @@ -51,6 +58,9 @@ export function formatNumber(num: number) {
return parts.join(".");
}

/**
*
*/
export function formatBytes(bytes: number) {
const threshold = 1000;
if (Math.round(bytes) < threshold) {
Expand All @@ -66,6 +76,9 @@ export function formatBytes(bytes: number) {
return formatNumber(formattedBytes) + " " + units[u];
}

/**
*
*/
export function extractReadableIndex(query: Record<string, any>): string {
if (query.orderBy) {
return query.orderBy;
Expand Down
Loading