flutter_graphql_codegen 1.0.1
flutter_graphql_codegen: ^1.0.1 copied to clipboard
A powerful code generator for Flutter GraphQL applications that generates type-safe Dart classes and client extensions from GraphQL schemas and operations.
Flutter GraphQL Codegen #
A code generator for Flutter GraphQL applications that generates type-safe Dart classes and client extensions from GraphQL schemas and operations.
β¨ Features #
- π― Type-safe code generation from GraphQL schemas and operations
- π§ Automatic Dart class generation with proper JSON serialization
- π GraphQL client extensions for queries, mutations, and subscriptions
- π‘οΈ Null safety support with graceful error handling
- π¦ Custom scalar support (DateTime, Decimal, Long, Byte, etc.)
- π Safe type converters with fallback values
- π Support for complex GraphQL features:
- Interfaces and unions
- Enums with custom values
- Input types and arguments
- Fragments and inline fragments
- Custom directives
- Nested and recursive types
- π Multiple schema sources: local files, HTTP/HTTPS URLs, file URLs
- π§ͺ Comprehensive test coverage with robust error handling
π Getting Started #
Installation #
Add this package to your pubspec.yaml
:
dependencies:
flutter_graphql_codegen: ^1.0.0
graphql: ^5.1.3
json_annotation: ^4.8.1
dev_dependencies:
build_runner: ^2.4.6
json_serializable: ^6.7.1
Configuration #
- Create a
build.yaml
file in your project root:
targets:
$default:
builders:
flutter_graphql_codegen:
enabled: true
options:
config_path: "graphql_codegen.yaml"
- Create a
graphql_codegen.yaml
configuration file:
# Schema source - supports multiple formats
schema_url: "lib/graphql/schema.graphql" # Local file path
# schema_url: "https://api.example.com/graphql" # HTTP/HTTPS URL
# schema_url: "file:///absolute/path/to/schema.graphql" # File URL
output_dir: "lib/graphql/generated"
document_paths:
- "lib/graphql/documents/**/*.graphql"
Schema Source Options
The schema_url
field supports multiple source types:
π Local Files:
schema_url: "schema.graphql" # Relative path
schema_url: "lib/graphql/schema.graphql" # Relative path with directories
schema_url: "/absolute/path/to/schema.graphql" # Absolute path
π File URLs:
schema_url: "file:///absolute/path/to/schema.graphql"
π HTTP/HTTPS URLs:
schema_url: "https://api.example.com/graphql" # GraphQL endpoint
schema_url: "http://localhost:4000/graphql/sdl" # Direct SDL endpoint
Alternative Configuration Format
You can also use alternative field names for compatibility:
schema: "lib/graphql/schema.graphql" # Instead of schema_url
documents: # Instead of document_paths
- "lib/graphql/documents/**/*.graphql"
π Usage #
Basic Example #
- Define your GraphQL operations in
.graphql
files:
# lib/graphql/queries/get_user.graphql
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
isActive
createdAt
}
}
- Run the code generator:
# First run: Generates GraphQL operation files and types.dart
dart run build_runner build --delete-conflicting-outputs
# Second run: Generates JSON serialization code (types.g.dart)
dart run build_runner build --delete-conflicting-outputs
Important: You need to run the build command twice:
- First run generates GraphQL types and operations
- Second run generates JSON serialization code for the types
This is because the JSON serialization generator (json_serializable
) needs the types.dart file to exist before it can generate the corresponding .g.dart files.
- Use the generated code in your Flutter app:
import 'package:graphql/client.dart';
import 'lib/graphql/generated/types.dart';
import 'lib/graphql/generated/get_user.dart';
// Initialize GraphQL client
final client = GraphQLClient(
link: HttpLink('https://your-graphql-endpoint.com/graphql'),
cache: GraphQLCache(),
);
// Use the generated extension method
final result = await client.getUserQuery(
variables: GetUserArguments(id: 'user-123'),
);
if (result.hasException) {
print('Error: ${result.exception}');
} else {
final user = result.parsedData?.user;
print('User: ${user?.name} (${user?.email})');
print('Created: ${user?.createdAt}');
}
Advanced Features #
Custom Scalars
The generator automatically handles custom scalars with safe converters:
// Generated safe converters with fallback values
@DateTimeConverter()
DateTime? createdAt;
@SafeIntConverter()
int count;
@SafeBoolConverter()
bool isActive;
@DecimalConverter()
Decimal? price;
Complex Types and Operations
# Schema types
type User {
id: ID!
profile: UserProfile
posts: [Post!]!
metadata: JSON
role: UserRole!
}
input CreateUserInput {
name: String!
email: String!
role: UserRole = USER
}
enum UserRole {
ADMIN
MODERATOR
USER
}
# Mutation example
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
email
role
}
}
# Subscription example
subscription UserUpdated($id: ID!) {
userUpdated(id: $id) {
id
name
isActive
}
}
Generated Extensions Usage
// Mutation with input validation
final createResult = await client.createUserMutation(
variables: CreateUserArguments(
input: CreateUserInput(
name: 'John Doe',
email: 'john@example.com',
role: UserRole.moderator,
),
),
);
// Subscription with real-time updates
final subscription = client.userUpdatedSubscription(
variables: UserUpdatedArguments(id: 'user-123'),
);
await for (final result in subscription.stream) {
if (result.data != null) {
final user = result.parsedData?.userUpdated;
print('User updated: ${user?.name}');
}
}
Error Handling #
The generator includes robust error handling:
// Safe converters handle malformed data gracefully
@SafeBoolConverter()
bool isActive; // Defaults to false if null or invalid
@SafeIntConverter()
int count; // Defaults to 0 if null or invalid
// Custom error handling
final result = await client.getUserQuery(
variables: GetUserArguments(id: 'invalid-id'),
);
if (result.hasException) {
// Handle GraphQL errors
final graphQLErrors = result.exception?.graphqlErrors;
final networkError = result.exception?.linkException;
print('GraphQL Errors: $graphQLErrors');
print('Network Error: $networkError');
} else {
// Safe to access data
final user = result.parsedData?.user;
}
βοΈ Configuration Options #
Option | Description | Default | Required |
---|---|---|---|
schema_url |
GraphQL schema source (URL or file path) | - | β |
output_dir |
Output directory for generated files | lib/generated |
β |
document_paths |
Glob patterns for GraphQL operation files | **/*.graphql |
β |
π API Reference #
Generated Types #
All GraphQL types are generated as Dart classes with:
- β
JSON serialization support (
fromJson
/toJson
) - β Null safety with safe defaults
- β Proper field typing based on GraphQL schema
- β Custom scalar handling with type converters
Generated Extensions #
For each operation, the generator creates client extensions:
- Queries:
client.{operationName}Query(variables?)
- Mutations:
client.{operationName}Mutation(variables?)
- Subscriptions:
client.{operationName}Subscription(variables?)
Type Safety #
// Generated with full type safety
class GetUserArguments {
final String id;
GetUserArguments({required this.id});
}
class User {
final String id;
final String? name;
final String? email;
@SafeBoolConverter()
final bool isActive;
User({
required this.id,
this.name,
this.email,
required this.isActive,
});
}
π§ Troubleshooting #
Common Issues #
"Target of URI hasn't been generated" Error
If you see errors like:
Target of URI hasn't been generated: 'package:your_app/graphql/generated/types.g.dart'
The method '_$UserFromJson' isn't defined for the type 'User'
Solution: Run the build command twice as described above. The first run generates the GraphQL types, and the second run generates the JSON serialization code.
Missing JSON Serialization Methods
If generated classes are missing fromJson
/toJson
methods:
- Ensure you have the required dependencies:
dependencies:
json_annotation: ^4.8.1
dev_dependencies:
build_runner: ^2.4.6
json_serializable: ^6.7.1
- Run build_runner twice:
dart run build_runner build --delete-conflicting-outputs
dart run build_runner build --delete-conflicting-outputs
Build Runner Conflicts
If you encounter build conflicts, use the clean option:
dart run build_runner clean
dart run build_runner build --delete-conflicting-outputs
Schema Download Issues
For HTTP/HTTPS schema URLs, ensure:
- The endpoint is accessible
- Authentication headers are set if required
- The URL returns valid GraphQL schema (SDL format)
Complex Type Generation Issues
If complex types aren't generating correctly:
- Check that your GraphQL schema is valid
- Ensure operation files have the correct extension (
.graphql
) - Verify the
document_paths
configuration matches your file structure
π§ͺ Testing #
The package includes comprehensive test coverage:
# Run all tests
dart test
# Run with coverage
dart test --coverage=coverage
dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib
π€ Contributing #
Contributions are welcome! Please see our Contributing Guidelines for details.
Development Setup #
- Fork the repository
- Clone your fork:
git clone https://github.com/ifmelate/flutter_graphql_codegen.git
- Install dependencies:
dart pub get
- Run tests:
dart test
- Make your changes
- Submit a pull request
π Changelog #
See CHANGELOG.md for a list of changes and releases.
π License #
This project is licensed under the MIT License - see the LICENSE file for details.