Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --disable-triggers flag to database write commands #5179

Merged
merged 6 commits into from Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1,3 +1,4 @@
- Releases RTDB Emulator v4.11.0: Wire protocol update for `startAfter`, `endBefore`.
- Changes `superstatic` dependency to `v8`, addressing Hosting emulator issues on Windows.
- Fixes internal library that was not being correctly published.
- Adds `--disable-triggers` flag to RTDB write commands.
5 changes: 5 additions & 0 deletions src/commands/database-push.ts
Expand Up @@ -21,6 +21,7 @@ export const command = new Command("database:push <path> [infile]")
"--instance <instance>",
"use the database <instance>.firebaseio.com (if omitted, use default database instance)"
)
.option("--disable-triggers", "suppress any Cloud functions triggered by this operation")
.before(requirePermissions, ["firebasedatabase.instances.update"])
.before(requireDatabaseInstance)
.before(populateInstanceDetails)
Expand All @@ -33,6 +34,9 @@ export const command = new Command("database:push <path> [infile]")
utils.stringToStream(options.data) || (infile ? fs.createReadStream(infile) : process.stdin);
const origin = realtimeOriginOrEmulatorOrCustomUrl(options.instanceDetails.databaseUrl);
const u = new URL(utils.getDatabaseUrl(origin, options.instance, path + ".json"));
if (options.disableTriggers) {
u.searchParams.set("disableTriggers", "true");
}

if (!infile && !options.data) {
utils.explainStdin();
Expand All @@ -46,6 +50,7 @@ export const command = new Command("database:push <path> [infile]")
method: "POST",
path: u.pathname,
body: inStream,
queryParams: u.searchParams,
});
} catch (err: any) {
logger.debug(err);
Expand Down
3 changes: 2 additions & 1 deletion src/commands/database-remove.ts
Expand Up @@ -17,6 +17,7 @@ export const command = new Command("database:remove <path>")
"--instance <instance>",
"use the database <instance>.firebaseio.com (if omitted, use default database instance)"
)
.option("--disable-triggers", "suppress any Cloud functions triggered by this operation")
.before(requirePermissions, ["firebasedatabase.instances.update"])
.before(requireDatabaseInstance)
.before(populateInstanceDetails)
Expand All @@ -40,7 +41,7 @@ export const command = new Command("database:remove <path>")
return utils.reject("Command aborted.", { exit: 1 });
}

const removeOps = new DatabaseRemove(options.instance, path, origin);
const removeOps = new DatabaseRemove(options.instance, path, origin, !!options.disableTriggers);
await removeOps.execute();
utils.logSuccess("Data removed successfully");
});
5 changes: 5 additions & 0 deletions src/commands/database-set.ts
Expand Up @@ -23,6 +23,7 @@ export const command = new Command("database:set <path> [infile]")
"--instance <instance>",
"use the database <instance>.firebaseio.com (if omitted, use default database instance)"
)
.option("--disable-triggers", "suppress any Cloud functions triggered by this operation")
.before(requirePermissions, ["firebasedatabase.instances.update"])
.before(requireDatabaseInstance)
.before(populateInstanceDetails)
Expand All @@ -34,6 +35,9 @@ export const command = new Command("database:set <path> [infile]")
const origin = realtimeOriginOrEmulatorOrCustomUrl(options.instanceDetails.databaseUrl);
const dbPath = utils.getDatabaseUrl(origin, options.instance, path);
const dbJsonURL = new URL(utils.getDatabaseUrl(origin, options.instance, path + ".json"));
if (options.disableTriggers) {
dbJsonURL.searchParams.set("disableTriggers", "true");
}

const confirm = await promptOnce(
{
Expand Down Expand Up @@ -61,6 +65,7 @@ export const command = new Command("database:set <path> [infile]")
method: "PUT",
path: dbJsonURL.pathname,
body: inStream,
queryParams: dbJsonURL.searchParams,
});
} catch (err: any) {
logger.debug(err);
Expand Down
5 changes: 5 additions & 0 deletions src/commands/database-update.ts
Expand Up @@ -23,6 +23,7 @@ export const command = new Command("database:update <path> [infile]")
"--instance <instance>",
"use the database <instance>.firebaseio.com (if omitted, use default database instance)"
)
.option("--disable-triggers", "suppress any Cloud functions triggered by this operation")
.before(requirePermissions, ["firebasedatabase.instances.update"])
.before(requireDatabaseInstance)
.before(populateInstanceDetails)
Expand Down Expand Up @@ -51,6 +52,9 @@ export const command = new Command("database:update <path> [infile]")
(infile && fs.createReadStream(infile)) ||
process.stdin;
const jsonUrl = new URL(utils.getDatabaseUrl(origin, options.instance, path + ".json"));
if (options.disableTriggers) {
jsonUrl.searchParams.set("disableTriggers", "true");
}

if (!infile && !options.data) {
utils.explainStdin();
Expand All @@ -62,6 +66,7 @@ export const command = new Command("database:update <path> [infile]")
method: "PATCH",
path: jsonUrl.pathname,
body: inStream,
queryParams: jsonUrl.searchParams,
});
} catch (err: any) {
throw new FirebaseError("Unexpected error while setting data");
Expand Down
5 changes: 3 additions & 2 deletions src/database/remove.ts
Expand Up @@ -29,10 +29,11 @@ export default class DatabaseRemove {
* @param instance RTBD instance ID.
* @param path path to delete.
* @param host db host.
* @param disableTriggers if true, suppresses any Cloud functions that would be triggered by this operation.
*/
constructor(instance: string, path: string, host: string) {
constructor(instance: string, path: string, host: string, disableTriggers: boolean = false) {
tohhsinpei marked this conversation as resolved.
Show resolved Hide resolved
this.path = path;
this.remote = new RTDBRemoveRemote(instance, host);
this.remote = new RTDBRemoveRemote(instance, host, disableTriggers);
this.deleteJobStack = new Stack({
name: "delete stack",
concurrency: 1,
Expand Down
10 changes: 8 additions & 2 deletions src/database/removeRemote.ts
Expand Up @@ -22,10 +22,12 @@ export class RTDBRemoveRemote implements RemoveRemote {
private instance: string;
private host: string;
private apiClient: Client;
private disableTriggers: boolean;

constructor(instance: string, host: string) {
constructor(instance: string, host: string, disableTriggers: boolean = false) {
tohhsinpei marked this conversation as resolved.
Show resolved Hide resolved
this.instance = instance;
this.host = host;
this.disableTriggers = disableTriggers;

const url = new URL(utils.getDatabaseUrl(this.host, this.instance, "/"));
this.apiClient = new Client({ urlPrefix: url.origin, auth: true });
Expand All @@ -46,7 +48,11 @@ export class RTDBRemoveRemote implements RemoveRemote {
private async patch(path: string, body: any, note: string): Promise<boolean> {
const t0 = Date.now();
const url = new URL(utils.getDatabaseUrl(this.host, this.instance, path + ".json"));
const queryParams = { print: "silent", writeSizeLimit: "tiny" };
const queryParams = {
print: "silent",
writeSizeLimit: "tiny",
disableTriggers: this.disableTriggers.toString(),
};
const res = await this.apiClient.request({
method: "PATCH",
path: url.pathname,
Expand Down
8 changes: 4 additions & 4 deletions src/test/database/removeRemote.spec.ts
Expand Up @@ -17,15 +17,15 @@ describe("RemoveRemote", () => {
it("should return true when patch is small", () => {
nock(serverUrl)
.patch("/a/b.json")
.query({ print: "silent", writeSizeLimit: "tiny" })
.query({ print: "silent", writeSizeLimit: "tiny", disableTriggers: "false" })
.reply(200, {});
return expect(remote.deletePath("/a/b")).to.eventually.eql(true);
});

it("should return false whem patch is large", () => {
nock(serverUrl)
.patch("/a/b.json")
.query({ print: "silent", writeSizeLimit: "tiny" })
.query({ print: "silent", writeSizeLimit: "tiny", disableTriggers: "false" })
.reply(400, {
error:
"Data requested exceeds the maximum size that can be accessed with a single request.",
Expand All @@ -36,15 +36,15 @@ describe("RemoveRemote", () => {
it("should return true when multi-path patch is small", () => {
nock(serverUrl)
.patch("/a/b.json")
.query({ print: "silent", writeSizeLimit: "tiny" })
.query({ print: "silent", writeSizeLimit: "tiny", disableTriggers: "false" })
.reply(200, {});
return expect(remote.deleteSubPath("/a/b", ["1", "2", "3"])).to.eventually.eql(true);
});

it("should return false when multi-path patch is large", () => {
nock(serverUrl)
.patch("/a/b.json")
.query({ print: "silent", writeSizeLimit: "tiny" })
.query({ print: "silent", writeSizeLimit: "tiny", disableTriggers: "false" })
tohhsinpei marked this conversation as resolved.
Show resolved Hide resolved
.reply(400, {
error:
"Data requested exceeds the maximum size that can be accessed with a single request.",
Expand Down