Skip to content

Dart SDK

The FraiseQL Dart SDK provides an async HTTP client for querying FraiseQL GraphQL APIs and schema annotations for defining types. It works in Dart CLI applications and Flutter mobile/web apps.

pubspec.yaml
dependencies:
fraiseql: ^2.1.0
Terminal window
dart pub get

Requirements: Dart >= 3.0.0

import 'package:fraiseql/fraiseql.dart';
// Simple client
final client = FraiseQLClient.simple('http://localhost:8080/graphql');
// Full configuration
final client = FraiseQLClient(FraiseQLClientConfig(
url: 'http://localhost:8080/graphql',
authorization: 'Bearer eyJhbGciOiJIUzI1NiIs...',
timeout: Duration(seconds: 30),
));

For JWT refresh or OAuth token rotation, pass an async factory instead of a static token:

final client = FraiseQLClient(FraiseQLClientConfig(
url: 'http://localhost:8080/graphql',
authorizationFactory: () async {
final token = await refreshAccessToken();
return 'Bearer $token';
},
));

The factory is called on every request, so you can return a fresh token each time.

final result = await client.query('{ users { id name email } }');
print(result['data']['users']);
// With variables
final result = await client.query(
r'query($id: ID!) { user(id: $id) { name } }',
variables: {'id': 'user-123'},
operationName: 'GetUser',
);
final result = await client.mutate(
r'mutation($input: CreateUserInput!) { createUser(input: $input) { id } }',
variables: {
'input': {'name': 'Alice', 'email': 'alice@example.com'},
},
);

Always close the client when done to release HTTP connections:

await client.close();

If you inject your own http.Client via FraiseQLClientConfig.httpClient, the SDK will not close it — you manage its lifecycle.


All exceptions inherit from FraiseQLException:

ExceptionWhen thrownKey properties
GraphQLExceptionResponse contains errors arrayerrors (full list), message (first error)
NetworkExceptionConnection refused, DNS failuremessage
TimeoutExceptionRequest exceeded timeoutduration
AuthenticationExceptionHTTP 401 or 403statusCode
RateLimitExceptionHTTP 429retryAfter
try {
final result = await client.query('{ users { id } }');
} on AuthenticationException catch (e) {
print('Auth failed (${e.statusCode})');
} on RateLimitException {
print('Rate limited — retry later');
} on GraphQLException catch (e) {
print('GraphQL error: ${e.message}');
for (final err in e.errors) {
print(err['message']);
}
} on NetworkException catch (e) {
print('Network error: ${e.message}');
}

Wrap FraiseQL queries as Google Gemini tool definitions for use with the Generative AI API:

final descriptor = FraiseQLGeminiToolDescriptor(
client: client,
name: 'get_users',
description: 'Fetch users by role',
query: r'query($role: String!) { users(role: $role) { id name } }',
parametersSchema: {
'type': 'object',
'properties': {
'role': {'type': 'string'},
},
'required': ['role'],
},
);
// Execute the query with arguments from the model
final result = await descriptor.execute({'role': 'admin'});

Works with both google_generative_ai and firebase_vertexai packages.


Define GraphQL types using annotations:

@FraiseQLType(name: 'User', description: 'A registered user')
class User {
@FraiseQLField(name: 'id', required: true, description: 'Unique identifier')
final String id;
@FraiseQLField(name: 'email', required: false)
final String? email;
@FraiseQLField(name: 'legacyField', deprecated: true)
final String? legacyField;
User({required this.id, this.email, this.legacyField});
}

These are metadata annotations for reflection. They do not generate schema output or validate against compiled schemas.


gRPC endpoints are auto-generated when [grpc] is enabled — no per-operation annotation needed. See gRPC Transport.