Use generated web SDKs

Firebase Data Connect client SDKs let you call your server-side queries and mutations directly from a Firebase app. You generate a custom client SDK in parallel as you design the schemas, queries and mutations you deploy to your Data Connect service. Then, you integrate methods from this SDK into your client logic.

As we've mentioned elsewhere, it's important to note that Data Connect queries and mutations are not submitted by client code and executed on the server. Instead, when deployed, Data Connect operations are stored on the server like Cloud Functions. This means you need to deploy corresponding client-side changes to avoid breaking existing users (for example, on older app versions).

That's why Data Connect provides you with a developer environment and tooling that lets you prototype your server-deployed schemas, queries and mutations. It also generates client-side SDKs automatically, while you prototype.

When you've iterated updates to your service and client apps, both server- and client-side updates are ready to deploy.

Generate your web SDK

As with most Firebase projects, work on your Firebase Data Connect client code takes place in a local project directory. Both the Data Connect VS Code extension and the Firebase CLI are important local tools for generating and managing client code.

SDK generation options are keyed to several entries in the dataconnect.yaml file generated when you initialized your project.

Initialize SDK generation

In your connector.yaml, add your outputDir, package and (for the web SDK) packageJsonDir.
generate:
  javascriptSdk:
    outputDir: "../movies-generated"
    package: "@movie-app/movies"
    packageJsonDir: "../../"

outputDir specifies where the generated SDK should output to.

package specifies the package name.

packageJsonDir specifies where to install the package.

In this case, install firebase@latest to ensure this peer dependency is fulfilled.

Configure paths relative to node_modules

For the web SDK, because Data Connect uses npm link to install your SDK, your generated SDK needs to be output to a directory at the same level as your node_modules path or in a child directory that can access node_modules.

In other words, your generated SDK needs to have access to the firebase node module to work correctly.

For example, if you have your node_modules in my-app/, then your output directory should be my-app/js-email-generated so that js-email-generated can import from its parent node_modules folder.

my-app/
  dataconnect/
    connector/
        connector.yaml
  node_modules/
    firebase/
  js-email-generated/
// connector.yaml
connectorId: "my-connector"
generate:
  javascriptSdk:
    outputDir: "../../js-email-generated"
    package: "@myapp/my-connector"

Or, if you have a monorepo where your modules are hosted at the root, you can place your output directory in any folder in your monorepo.

my-monorepo/
  dataconnect/
    connector/
        connector.yaml
  node_modules/
    firebase/
  my-app/
    js-email-generated/
  package.json
// connector.yaml
connectorId: "my-connector"
generate:
  javascriptSdk:
    outputDir: "../../my-app/js-email-generated" # You can also output to ../../js-email-generated

Update SDKs while prototyping

If you're prototyping interactively with the Data Connect VS Code extension and its Data Connect emulator, SDK source files are automatically generated and updated while you modify .gql files defining schemas, queries and mutations. This can be a useful feature in hot (re)loading workflows.

In other scenarios, if you're using the Data Connect emulator from the Firebase CLI, you can set a watch on .gql updates and also have SDK sources automatically updated.

Alternatively, you can use the CLI to regenerate SDKs whenever .gql files are changed:

firebase dataconnect:sdk:generate --watch

Generate SDKs for integration and for production releases

In some scenarios, such as preparing project sources to submit for CI tests, you can call the Firebase CLI for a batch update.

In these cases, use firebase dataconnect:sdk:generate.

Set up client code

Initialize your Data Connect app

First, initialize your app using the standard Firebase sequence.

initializeApp({...});

Initialize the Data Connect web SDK

Initialize your Data Connect instance using the information you used to set up Data Connect (all available in the Firebase console Data Connect tab).

The ConnectorConfig object

The SDK requires a connector configuration object.

This object is automatically generated from serviceId and location in dataconnect.yaml, and connectorId in connector.yaml.

Import libraries

There are two sets of imports needed to initialize your client code, general Data Connect imports and specific, generated SDK imports.

// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';

// generated queries and mutations from SDK
import { listMovies, ListMoviesResponse, createMovie, connectorConfig } from '@myorg/myconnector';

Prototype and test your web clients

Instrument clients to use a local emulator

You can use the Data Connect emulator, whether from the Data Connect VS Code extension or from the CLI.

Instrumenting the app to connect to the emulator is the same for both scenarios.

import { connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@myorg/myconnector'; // Replace with your package name
const dataConnect = getDataConnect(connectorConfig);

connectDataConnectEmulator(dataConnect, 'localhost', 9399);`

// Make calls from your app

To switch to production resources, comment out lines for connecting to the emulator.

Getting an instance

Calling getDataConnect is only required if you'd like to connect to the Data Connect emulator. Otherwise the generated SDK will automatically create an instance of the DataConnect object for you.

Using queries on the client side

The generated code will already come with pre-defined Query Refs. All you need to do is import and call execute on them.

import { executeQuery } from 'firebase/data-connect';
import { listMoviesRef } from '@movie-app/movies';

const ref = listMoviesRef();
const { data } = await executeQuery(ref);
console.log(data.movies);

Call SDK query methods

Here's an example using these action shortcut functions:

import { listMovies } from '@movie-app/movies';
function onBtnClick() {
// This will call the generated JS from the CLI and then make an HTTP request out // to the server.
listMovies().then(data => showInUI(data)); // == executeQuery(listMoviesRef);
}

Subscribing to changes

You can subscribe to changes (which will update any time you execute a query).

const listRef = listAllMoviesRef();

// subscribe will immediately invoke the query if no execute was called on it previously.
subscribe(listRef, ({ data }) => {
 updateUIWithMovies(data.movies);
});

await createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi", rating: 5 });\
await listMovies(); // will update the subscription above`

Using mutations on the client side

Mutations are accessible the same way as queries.

import { executeMutation } from 'firebase/data-connect';
import { createMovieRef } from '@movie-app/movies';

const { data } = await executeMutation(createMovieRef({ movie: 'Empire Strikes Back' }));

Data types in the web SDK

The Data Connect server represents common GraphQL data types. These are represented in the SDK as follows.

Data Connect Type TypeScript
Timestamp string
Date string
UUID string
Int64 string
Double Number
Float Number

Frameworks considerations

Angular

When generating code, the Angular CLIwill not pick up on new changes due to its dependency optimization code. In order to fix this, you will need to modify your angular.json.

  "projects": {
      "myproject": {
         "architect": {
                 "serve:": {
                            "prebundle": {
                                         "exclude": ["@movie-app/movies"]
                              }
                   }
            }
     }
  }