Data Connect: Event Triggers and Generated Admin SDKs

As more and more of you adopt Data Connect, we’ve been listening to your feature requests on Firebase UserVoice. We’re excited to announce these new features that you can now use:

  • Event triggers: run server-side code when a mutation is executed
  • Generated admin SDKs: type-safe SDKs get generated from gql definitions for your use in privileged environments

Read more below for more information about each one!

Event triggers

Data Connect is helpful for modeling data, then querying and updating that data from your client-side code. Now, you can run server-side code in response to the execution of a mutation in your Data Connect service. You can do this with Cloud Functions for Firebase or other services like Cloud Run and App Hosting - or really, any system you’d like to use.

Use cases

Here are some common use cases:

  • Data synchronization: replicate or synchronize data with other systems (like Firestore or external APIs) immediately after a mutation occurs
  • Asynchronous workflows: after a database change, kick off long-running processes, such as image processing or data aggregation
  • User engagement: send a welcome email upon account creation or Firebase Cloud Messaging notifications to users after a specific event in your application

You’ll see each of these in the examples below.

Trigger a function for every executed mutation

Every time a mutation is executed, the onMutationExecuted event handler will be triggered. To get the data payload, use event.data, which is a MutationEventData object.

Let’s say you want to replicate all data over to Firestore. Here’s an example of what the Cloud Function looks like if you wanted to perform an action in this case:

export const logMutation = async onMutationExecuted(
  {
    /* Trigger on all mutations, spanning all services and connectors */
  },
  (event) => {
    // Action taken for all mutations
    // Insert the data into Firestore under the path /messages/:documentId/original

    const writeResult = await getFirestore()
      .collection("messages")
      .add({original: event.data});
  }
);

Trigger a function for certain mutation(s)

In many cases, you might want to perform an action when a certain mutation or group of mutations are executed. You can filter by service, connector, and/or operation to do so - all three are not required.

In this example, when a friend sends a message, the user will receive a Firebase Cloud Messaging notification:

// Registration token for Firebase Cloud Messaging.
const registrationToken = 'YOUR_REGISTRATION_TOKEN';

// Trigger this function only for the SendMessage mutation
// in the messages connector of the myAppService service
export const onUserCreate = onMutationExecuted(
  {
    service: "myAppService",
    connector: "messages",
    operation: "SendMessage",
  },
  (event) => {
    // Add logic here for the message is sent
    const message = {
      data: {
        msg: 'event.data.sendMessage.message'
      },
      token: registrationToken
    }

  // Send a message to the device corresponding to the provided
  getMessaging().send(message);
);

Filter triggers on multiple values

You can use capture groups to filter triggers on multiple values, and any groups captured are available in event.params to use. See Understand path patterns for more information.

Let’s say all of your services and connectors relevant to a game start with “Game”, and all of them have a “score” field. Every time a mutation in any of these services or connectors is executed, you can trigger a function that helps you update the average score. In this example, you’ll need to get existing data from Data Connect using the Admin SDK, as the Data Connect event does not provide a “before” snapshot of the data.

// Trigger on all operations that match `Game*`, on any service and connector
export const onMutationWildcards = async onMutationExecuted(
  {
    operation: "Game*",
  },
  (event) => {
    const games = await getGames(...);
    const avg = games.average;
    const totalGamesCount = games.total;
    const newAvg =
      (games.average * games.total + event.data.score ) / games.total;

    await upsertGame(admin, {
      average: newAvg,
      total: totalGamesCount + 1,
      // other fields
    });
  }
);

It’s important to note that you only have access to the arguments sent to the mutation and the data that was returned by it upon execution. This is different to other database triggers (such as Firestore or Realtime Database), as the Data Connect event does not provide a “before” snapshot of the data. Data Connect proxies requests to the underlying database, so the “before” snapshot of the data cannot be obtained transactionally.

Generated admin SDKs

Before now, you could use the Firebase Admin SDK with Data Connect to execute actions, like performing queries and mutations on a Data Connect service, in a privileged environment. This can help you with bulk data management and other operations with elevated privileges and impersonated credentials. The Admin SDK previously provided you with two sets of APIs: one for running arbitrary GraphQL operations and another for bulk data operations.

Now, there is another set of APIs for Data Connect: generated admin SDKs, which are type-safe SDKs generated from your gql definitions. In much the same way as you generate SDKs for your client apps, you generate a custom admin SDK in parallel as you design the schemas, queries, and mutations. Those are deployed to your Data Connect service, and then, you use these methods from this SDK in your backend logic or administration scripts.

It’s important to note that Data Connect queries and mutations are not submitted by clients at the time of the request. Instead, when deployed, Data Connect operations are stored on the server, like Cloud Functions. This means that whenever you deploy changes to your queries and mutations, you also need to regenerate admin SDKs and redeploy any services that rely on them.

Try it out!

Check out the documentation to learn more about and see examples for event triggers and generated admin SDKs.

We’re always incredibly excited to see what you build with Data Connect and these new features! Your feedback is invaluable as we use it for our roadmap going forward, so please continue to share your thoughts and requests on Firebase’s UserVoice!