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 Flutter 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 yourconnector.yaml
, add your outputDir
, package
and (for the web SDK)
packageJsonDir
.
connectorId: movies
generate:
dartSdk:
outputDir: ../../lib/generated # Feel free to change this to a different path
package: movies
outputDir
specifies where the generated SDK should output to. This path is
relative to the directory that contains the connector.yaml
file itself.
Optionally, you can provide an absolute path to your outputDir
.
package
specifies the package name.
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.
.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 setup instructions.
Then, install the Data Connect plugin:
flutter pub add firebase_data_connect
Initialize the Data Connect Flutter 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).
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 'package:firebase_data_connect/firebase_data_connect.dart';
// generated queries and mutations from SDK
import 'generated/movies.dart';
Prototype and test your Flutter apps
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 'package:firebase_data_connect/firebase_data_connect.dart';
import 'generated/movies.dart';
MoviesConnector.instance.dataConnect
.useDataConnectEmulator('127.0.0.1', 9399);
// Make calls from your app
QueryRef<ListMoviesData, void> ref = MoviesConnector.instance.listMovies.ref();
To switch to production resources, comment out lines for connecting to the emulator.
Use queries on the client side
The generated code will already come with predefined Query Refs. All you need
to do is import and call execute
on them.
import 'generated/movies.dart';
await MoviesConnector.instance.listMovies().execute();
Call SDK query methods
Here's an example using these action shortcut functions:
import 'generated/movies.dart';
function onBtnClick() {
// This will call the generated Dart from the CLI and then make an HTTP request to the server.
MoviesConnector.instance.listMovies().execute().then(data => showInUI(data)); // == MoviesConnector.instance.listMovies().ref().execute();
}
Optional Fields
Some queries may have optional fields. In these cases, the Flutter SDK exposes a builder method, and will have to be set separately.
For example, the field rating
is optional when calling createMovie
, so you
need to provide it in the builder function.
await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi"}).rating(5).execute();
Subscribe to changes
You can subscribe to changes (which will update any time you execute a query).
QueryRef<ListMoviesData, void> listRef = MoviesConnector.instance.listMovies().ref();
// subscribe will immediately invoke the query if no execute was called on it previously.
listRef.subscribe().listen((data) {
updateUIWithMovies(data.movies);
});
await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();
await listRef.execute(); // will update the subscription above`
Use mutations on the client side
Mutations are accessible in the same way as queries.
await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();
Data types in the Dart SDK
The Data Connect server represents common GraphQL data types. These are represented in the SDK as follows.
Data Connect Type | Dart |
---|---|
Timestamp | firebase_data_connect.Timestamp |
Int (32-bit) | int |
Date | DateTime |
UUID | string |
Int64 | int |
Float | double |
Boolean | bool |
Any | firebase_data_connect.AnyValue |