Chapter 07 · Firebase Data Connect
Subchapter 7.1
reference/cloud_functions.mdMarkdown6 KBView on GitHub
Use this reference to handle database events in SQL Connect by triggering Cloud Functions in response to mutation executions.
To handle a mutation execution, define the onMutationExecuted event handler.
Unlike document-based database triggers (like Firestore or Realtime Database), SQL Connect event triggers do not provide a “before” snapshot of the data. Because SQL Connect proxies requests directly to PostgreSQL, “before” states cannot be resolved transactionally.
onMutationExecuted executes a SQL Connect mutation, it can
trigger another onMutationExecuted trigger in a cascading loop. Make sure
that onMutationExecuted has a filter on operation to reduce the chance of
infinite loops.The Cloud Function region option must match your SQL Connect service
location. You must explicitly configure the region parameter (e.g.,
'us-central1') in the trigger options to match the location specified in
dataconnect.yaml.
import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";
export const logMutation = onMutationExecuted(
{
region: "europe-west1" // Must match the SQL Connect service location
},
(event) => {
logger.info("A mutation was executed!", {
eventId: event.id,
type: event.type
});
}
);To prevent unnecessary function invocations and infinite execution loops,
always specify narrow filters using service and operation attributes.
service & operation (Recommended): Always specify these to restrict
the trigger to a specific mutation in your project.connector (Optional): Can be omitted if you want to trigger on the same
operation name across multiple connectors. Specify it only if you need to
restrict the trigger to a specific connector.import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";
// Triggers for "CreateUser" mutation in "myAppService" service.
// 'connector' is omitted (optional), meaning it matches "CreateUser" in any connector.
export const onUserCreate = onMutationExecuted(
{
service: "myAppService",
operation: "CreateUser",
// region: "us-central1" // Optional: defaults to us-central1, change if database is elsewhere
},
(event) => {
logger.info("A new user was created!");
}
);
// Advanced: Trigger using wildcards or capture variables
export const onMutationCaptures = onMutationExecuted(
{
service: "myAppService",
operation: "{operation}", // Captures matching operation name dynamically
},
(event) => {
const triggeredOp = event.params.operation;
logger.info(`Captured operation execution: ${triggeredOp}`);
}
);Extract security credentials about the caller who executed the mutation using
event.authType and event.authId.
| Triggered Principal | event.authType | event.authId |
|---|---|---|
| Authenticated end user | "app_user" | Firebase Auth token UID |
| Unauthenticated end user | "unauthenticated" | Empty |
| Admin SDK (Impersonating User) | "app_user" | Firebase Auth token UID of the impersonated user |
| Admin SDK (Impersonating Unauth) | "unauthenticated" | Empty |
| Admin SDK (Full privileges) | "admin" | Empty |
export const processSensitiveMutation = onMutationExecuted(
{ operation: "UpdateFinancials" },
(event) => {
if (event.authType === "admin") {
console.log("Elevated admin mutation execution.");
} else {
console.log(`Mutation initiated by user: ${event.authId}`);
}
}
);The trigger payload provides inputs passed to the mutation (payload.variables)
and return values generated from the execution (payload.data).
{
"authType": "app_user",
"authId": "user-123",
"data": {
"payload": {
"variables": {
"movieId": "m-1",
"rating": 5
},
"data": {
"review_insert": {
"id": "r-99"
}
},
"errors": []
}
}
}event.data.payload.variables: Inputs passed to the mutation.event.data.payload.data: Fields returned by the mutation execution.event.data.payload.errors: Array of execution errors. Empty if
successful.import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";
export const onNewReview = onMutationExecuted(
{
service: "myAppService",
connector: "reviews",
operation: "CreateReview",
},
(event) => {
// Extract input variables passed to the mutation
const inputVariables = event.data.payload.variables;
// Extract returned fields from the database write
const returnedFields = event.data.payload.data;
logger.info(`Processed review ${returnedFields.review_insert.id} for movie ${inputVariables.movieId}`);
}
);