Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Add a confirmation in `firebase init dataconnect` before asking for app idea description. (#9282)
1 change: 0 additions & 1 deletion firebase-vscode/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const defaultOptions: Readonly<VsCodeOptions> = {
projectNumber: "",
projectRoot: "",
account: "",
json: true,
nonInteractive: true,
interactive: false,
debug: false,
Expand Down
1 change: 0 additions & 1 deletion src/checkValidTargetFilters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const SAMPLE_OPTIONS: Options = {
only: "",
except: "",
nonInteractive: false,
json: false,
interactive: false,
debug: false,
force: false,
Expand Down
1 change: 1 addition & 0 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ export class Command {
}

if (getInheritedOption(options, "json")) {
options.interactive = false;
options.nonInteractive = true;
} else if (!options.isMCP) {
useConsoleLoggers();
Expand Down
6 changes: 1 addition & 5 deletions src/commands/firestore-backups-delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ export const command = new Command("firestore:backups:delete <backup>")
throw new FirebaseError(`Failed to delete the backup ${backupName}`, { original: err });
}

if (options.json) {
logger.info(JSON.stringify(backup, undefined, 2));
} else {
logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupName)}`));
}
logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupName)}`));

return backup;
});
10 changes: 2 additions & 8 deletions src/commands/firestore-backups-get.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import { Command } from "../command";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
import { FirestoreOptions } from "../firestore/options";
import { Backup, getBackup } from "../gcp/firestore";
import { PrettyPrint } from "../firestore/pretty-print";

export const command = new Command("firestore:backups:get <backup>")
.description("get a Cloud Firestore database backup")
.before(requirePermissions, ["datastore.backups.get"])
.before(warnEmulatorNotSupported, Emulators.FIRESTORE)
.action(async (backupName: string, options: FirestoreOptions) => {
.action(async (backupName: string) => {
const backup: Backup = await getBackup(backupName);
const printer = new PrettyPrint();

if (options.json) {
logger.info(JSON.stringify(backup, undefined, 2));
} else {
printer.prettyPrintBackup(backup);
}
printer.prettyPrintBackup(backup);

return backup;
});
19 changes: 8 additions & 11 deletions src/commands/firestore-backups-list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Command } from "../command";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand All @@ -23,17 +22,15 @@ export const command = new Command("firestore:backups:list")
const listBackupsResponse: ListBackupsResponse = await listBackups(options.project, location);
const backups: Backup[] = listBackupsResponse.backups || [];

if (options.json) {
logger.info(JSON.stringify(listBackupsResponse, undefined, 2));
} else {
printer.prettyPrintBackups(backups);
if (listBackupsResponse.unreachable && listBackupsResponse.unreachable.length > 0) {
logWarning(
"We were not able to reach the following locations: " +
listBackupsResponse.unreachable.join(", "),
);
}
printer.prettyPrintBackups(backups);
if (listBackupsResponse.unreachable && listBackupsResponse.unreachable.length > 0) {
logWarning(
"We were not able to reach the following locations: " +
listBackupsResponse.unreachable.join(", "),
);
}

// TODO: Consider returning listBackupResponse instead for --json. This will
// be a breaking change but exposes .unreachable, not just .backups.
return backups;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This change introduces a regression for users of the --json flag. Previously, the full listBackupsResponse object (including the unreachable field) was printed as JSON. With this change, only the backups array is returned, and thus printed, losing the unreachable information for JSON consumers.

While the TODO comment acknowledges this, it would be better to avoid this regression. I suggest returning listBackupsResponse to maintain the existing behavior for JSON output. This would be a breaking change for programmatic users of the command who might rely on the return value being Backup[], but given the new command framework's convention of using the return value for JSON output, it's the more correct and consistent approach.

Suggested change
return backups;
return listBackupsResponse;

});
10 changes: 3 additions & 7 deletions src/commands/firestore-backups-schedules-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,9 @@ export const command = new Command("firestore:backups:schedules:create")
weeklyRecurrence,
);

if (options.json) {
logger.info(JSON.stringify(backupSchedule, undefined, 2));
} else {
logger.info(
clc.bold(`Successfully created ${printer.prettyBackupScheduleString(backupSchedule)}`),
);
}
logger.info(
clc.bold(`Successfully created ${printer.prettyBackupScheduleString(backupSchedule)}`),
);

return backupSchedule;
});
6 changes: 1 addition & 5 deletions src/commands/firestore-backups-schedules-delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ export const command = new Command("firestore:backups:schedules:delete <backupSc
});
}

if (options.json) {
logger.info(JSON.stringify(backupSchedule, undefined, 2));
} else {
logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupScheduleName)}`));
}
logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupScheduleName)}`));

return backupSchedule;
});
7 changes: 1 addition & 6 deletions src/commands/firestore-backups-schedules-list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Command } from "../command";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand All @@ -24,11 +23,7 @@ export const command = new Command("firestore:backups:schedules:list")
databaseId,
);

if (options.json) {
logger.info(JSON.stringify(backupSchedules, undefined, 2));
} else {
printer.prettyPrintBackupSchedules(backupSchedules, databaseId);
}
printer.prettyPrintBackupSchedules(backupSchedules, databaseId);

return backupSchedules;
});
10 changes: 3 additions & 7 deletions src/commands/firestore-backups-schedules-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,9 @@ export const command = new Command("firestore:backups:schedules:update <backupSc
retention,
);

if (options.json) {
logger.info(JSON.stringify(backupSchedule, undefined, 2));
} else {
logger.info(
clc.bold(`Successfully updated ${printer.prettyBackupScheduleString(backupSchedule)}`),
);
}
logger.info(
clc.bold(`Successfully updated ${printer.prettyBackupScheduleString(backupSchedule)}`),
);

return backupSchedule;
});
25 changes: 10 additions & 15 deletions src/commands/firestore-bulkdelete.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Command } from "../command";
import * as fsi from "../firestore/api";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand Down Expand Up @@ -75,21 +74,17 @@ export const command = new Command("firestore:bulkdelete")

const op = await api.bulkDeleteDocuments(options.project, databaseId, collectionIds);

if (options.json) {
logger.info(JSON.stringify(op, undefined, 2));
if (op.name) {
logSuccess(`Successfully started bulk delete operation.`);
logBullet(`Operation name: ` + clc.cyan(op.name));
// TODO: Update this message to 'firebase firestore:operations:describe' command once it's implemented.
logBullet(
"You can monitor the operation's progress using the " +
clc.cyan(`gcloud firestore operations describe`) +
` command.`,
);
} else {
if (op.name) {
logSuccess(`Successfully started bulk delete operation.`);
logBullet(`Operation name: ` + clc.cyan(op.name));
// TODO: Update this message to 'firebase firestore:operations:describe' command once it's implemented.
logBullet(
"You can monitor the operation's progress using the " +
clc.cyan(`gcloud firestore operations describe`) +
` command.`,
);
} else {
logLabeledError(`Bulk Delete:`, `Failed to start a bulk delete operation.`);
}
logLabeledError(`Bulk Delete:`, `Failed to start a bulk delete operation.`);
}

return op;
Expand Down
22 changes: 9 additions & 13 deletions src/commands/firestore-databases-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,15 @@ export const command = new Command("firestore:databases:create <database>")

const databaseResp: types.DatabaseResp = await api.createDatabase(createDatabaseReq);

if (options.json) {
logger.info(JSON.stringify(databaseResp, undefined, 2));
} else {
logger.info(clc.bold(`Successfully created ${printer.prettyDatabaseString(databaseResp)}`));
logger.info(
"Please be sure to configure Firebase rules in your Firebase config file for\n" +
"the new database. By default, created databases will have closed rules that\n" +
"block any incoming third-party traffic.",
);
logger.info(
`Your database may be viewed at ${printer.firebaseConsoleDatabaseUrl(options.project, database)}`,
);
}
logger.info(clc.bold(`Successfully created ${printer.prettyDatabaseString(databaseResp)}`));
logger.info(
"Please be sure to configure Firebase rules in your Firebase config file for\n" +
"the new database. By default, created databases will have closed rules that\n" +
"block any incoming third-party traffic.",
);
logger.info(
`Your database may be viewed at ${printer.firebaseConsoleDatabaseUrl(options.project, database)}`,
);

return databaseResp;
});
6 changes: 1 addition & 5 deletions src/commands/firestore-databases-delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ export const command = new Command("firestore:databases:delete <database>")

const databaseResp: types.DatabaseResp = await api.deleteDatabase(options.project, database);

if (options.json) {
logger.info(JSON.stringify(databaseResp, undefined, 2));
} else {
logger.info(clc.bold(`Successfully deleted ${printer.prettyDatabaseString(databaseResp)}`));
}
logger.info(clc.bold(`Successfully deleted ${printer.prettyDatabaseString(databaseResp)}`));

return databaseResp;
});
7 changes: 1 addition & 6 deletions src/commands/firestore-databases-get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Command } from "../command";
import * as fsi from "../firestore/api";
import * as types from "../firestore/api-types";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand All @@ -19,11 +18,7 @@ export const command = new Command("firestore:databases:get [database]")
const databaseId = database || "(default)";
const databaseResp: types.DatabaseResp = await api.getDatabase(options.project, databaseId);

if (options.json) {
logger.info(JSON.stringify(databaseResp, undefined, 2));
} else {
printer.prettyPrintDatabase(databaseResp);
}
printer.prettyPrintDatabase(databaseResp);

return databaseResp;
});
7 changes: 1 addition & 6 deletions src/commands/firestore-databases-list.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Command } from "../command";
import * as fsi from "../firestore/api";
import * as types from "../firestore/api-types";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand All @@ -18,11 +17,7 @@ export const command = new Command("firestore:databases:list")

const databases: types.DatabaseResp[] = await api.listDatabases(options.project);

if (options.json) {
logger.info(JSON.stringify(databases, undefined, 2));
} else {
printer.prettyPrintDatabases(databases);
}
printer.prettyPrintDatabases(databases);

return databases;
});
26 changes: 11 additions & 15 deletions src/commands/firestore-databases-restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,21 +72,17 @@ export const command = new Command("firestore:databases:restore")
encryptionConfig,
);

if (options.json) {
logger.info(JSON.stringify(databaseResp, undefined, 2));
} else {
logger.info(
clc.bold(`Successfully initiated restore of ${printer.prettyDatabaseString(databaseResp)}`),
);
logger.info(
"Please be sure to configure Firebase rules in your Firebase config file for\n" +
"the new database. By default, created databases will have closed rules that\n" +
"block any incoming third-party traffic.",
);
logger.info(
`Once the restore is complete, your database may be viewed at ${printer.firebaseConsoleDatabaseUrl(options.project, databaseId)}`,
);
}
logger.info(
clc.bold(`Successfully initiated restore of ${printer.prettyDatabaseString(databaseResp)}`),
);
logger.info(
"Please be sure to configure Firebase rules in your Firebase config file for\n" +
"the new database. By default, created databases will have closed rules that\n" +
"block any incoming third-party traffic.",
);
logger.info(
`Once the restore is complete, your database may be viewed at ${printer.firebaseConsoleDatabaseUrl(options.project, databaseId)}`,
);

return databaseResp;

Expand Down
6 changes: 1 addition & 5 deletions src/commands/firestore-databases-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,7 @@ export const command = new Command("firestore:databases:update <database>")
pointInTimeRecoveryEnablement,
);

if (options.json) {
logger.info(JSON.stringify(databaseResp, undefined, 2));
} else {
logger.info(clc.bold(`Successfully updated ${printer.prettyDatabaseString(databaseResp)}`));
}
logger.info(clc.bold(`Successfully updated ${printer.prettyDatabaseString(databaseResp)}`));

return databaseResp;
});
7 changes: 1 addition & 6 deletions src/commands/firestore-locations.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Command } from "../command";
import * as fsi from "../firestore/api";
import * as types from "../firestore/api-types";
import { logger } from "../logger";
import { requirePermissions } from "../requirePermissions";
import { Emulators } from "../emulator/types";
import { warnEmulatorNotSupported } from "../emulator/commandUtils";
Expand All @@ -18,11 +17,7 @@ export const command = new Command("firestore:locations")

const locations: types.Location[] = await api.locations(options.project);

if (options.json) {
logger.info(JSON.stringify(locations, undefined, 2));
} else {
printer.prettyPrintLocations(locations);
}
printer.prettyPrintLocations(locations);

return locations;
});
9 changes: 2 additions & 7 deletions src/commands/firestore-operations-cancel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,20 @@ import { command } from "./firestore-operations-cancel";
import * as fsi from "../firestore/api";
import * as prompt from "../prompt";
import * as utils from "../utils";
import { logger } from "../logger";

describe("firestore:operations:cancel", () => {
const sandbox = sinon.createSandbox();
let firestoreApiStub: sinon.SinonStubbedInstance<fsi.FirestoreApi>;
let confirmStub: sinon.SinonStub;
let logSuccessStub: sinon.SinonStub;
let logWarningStub: sinon.SinonStub;
let loggerInfoStub: sinon.SinonStub;

beforeEach(() => {
firestoreApiStub = sandbox.createStubInstance(fsi.FirestoreApi);
sandbox.stub(fsi, "FirestoreApi").returns(firestoreApiStub);
confirmStub = sandbox.stub(prompt, "confirm");
logSuccessStub = sandbox.stub(utils, "logSuccess");
logWarningStub = sandbox.stub(utils, "logWarning");
loggerInfoStub = sandbox.stub(logger, "info");
});

afterEach(() => {
Expand Down Expand Up @@ -87,10 +84,8 @@ describe("firestore:operations:cancel", () => {
const status = { success: true };
firestoreApiStub.cancelOperation.resolves(status);

await command.runner()(operationName, options);
const jsonResult = await command.runner()(operationName, options);

expect(loggerInfoStub).to.be.calledOnceWith(JSON.stringify(status, undefined, 2));
expect(logSuccessStub).to.not.be.called;
expect(logWarningStub).to.not.be.called;
expect(jsonResult).to.eql(status);
});
});
Loading
Loading