graphql-codegen-flutter-freezed-classes
v0.0.33
Published
GraphQL Code Generator plugin to generate freezed classes from your GraphQL schema
Downloads
7
Maintainers
Readme
GraphQL Flutter Freezed Classes
This project aims to speed up your development of Flutter apps by generating Freezed from your GraphQL schema.
Features
- [x] Generate Freezed classes for ObjectTypes
- [x] Generate Freezed classes for InputTypes
- [x] Support for EnumsTypes
- [x] Support for custom ScalarTypes
- [x] Support freeze documentation of class & properties from GraphQL SDL description comments
- [x] Ignore/don't generate freezed classes for certain ObjectTypes
- [] Support arguments
- [] Support directives
- [] Support deprecation annotation
- [] Support for InterfaceTypes
- [x] Support for UnionTypes union/sealed classes
- [x] Merge InputTypes with ObjectType as union/sealed class union/sealed classes
Example
Using the CLI
ffc generate -s schema.graphql --scalars '{"jsonb": "Map<String, dynamic>","timestamptz": "DateTime", "UUID": "String"}' -m 'Create$Input' -m 'Update$Input' -m 'Upsert$Input' -m 'Delete$Input'
Given the following GraphQL schema below
# schema.graphql
type Movie {
id: ID!
title: String!
}
input CreateMovieInput {
title: String!
}
input UpsertMovieInput {
id: ID!
title: String!
}
input UpdateMovieInput {
id: ID!
title: String
}
input DeleteMovieInput {
id: ID!
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Starship {
id: ID!
name: String!
length: Float
}
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
type Character {
name: String!
appearsIn: [Episode]!
}
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
starships: [Starship]
totalCredits: Int
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
primaryFunction: String
}
union SearchResult = Human | Droid | Starship
# tests
scalar UUID
scalar timestamptz
scalar jsonb
# cyclic references/nested types
input AInput {
b: BInput!
}
input BInput {
c: CInput!
}
input CInput {
a: AInput!
}
type ComplexType {
a: [String]
b: [ID!]
c: [Boolean!]!
d: [[Int]]
e: [[Float]!]
f: [[String]!]!
g: jsonb
h: timestamptz!
i: UUID!
}
Generated file
// app_models.dart
// with lowercaseEnums: true
enum Episode {
@JsonKey(name: "EMPIRE") empire,
@JsonKey(name: "JEDI") jedi,
@JsonKey(name: "NEWHOPE") newhope,
}
// with lowercaseEnums: false
enum Gender {
FEMALE,
MALE,
}
@freezed
class AInput with _$AInput{
const factory AInput({
required BInput b
}) = _AInput;
factory AInput.fromJson(Map<String, dynamic> json) => _$AInputFromJson(json);
};
@freezed
class BInput with _$BInput{
const factory BInput({
required CInput c
}) = _BInput;
factory BInput.fromJson(Map<String, dynamic> json) => _$BInputFromJson(json);
};
@freezed
class CInput with _$CInput{
const factory CInput({
required AInput a
}) = _CInput;
factory CInput.fromJson(Map<String, dynamic> json) => _$CInputFromJson(json);
};
@freezed
class ComplexType with _$ComplexType{
const factory ComplexType({
List<String?>? a,
List<String>? b,
required List<bool> c,
List<List<int?>?>? d,
List<List<double?>>? e,
required List<List<String?>> f,
Map<String, dynamic>? g,
required DateTime h,
required String i
}) = _ComplexType;
factory ComplexType.fromJson(Map<String, dynamic> json) => _$ComplexTypeFromJson(json);
};
// TODO: Merge InputTypes with ObjectType as union/sealed classconst
@freezed
class Movie with _$Movie {
const factory Movie({
required String id,
required String title,
}) = _Movie;
const factory Movie.createInput({
required String title,
}) = _CreateMovieInput;
const factory Movie.upsertInput({
required String id,
required String title,
}) = _UpsertMovieInput;
const factory Movie.updateInput({
required String id,
String title,
}) = _UpdateMovieInput;
const factory Movie.deleteInput({
required String id,
}) = _DeleteMovieInput;
factory Movie.fromJson(Map<String, dynamic> json) => _$MovieFromJson(json);
}
// Without mergeInputs
@freezed
class Movie with _$Movie{
const factory Movie({
required String id,
required String title,
}) = _Movie;
factory Movie.fromJson(Map<String, dynamic> json) => _$MovieFromJson(json);
}
@freezed
class CreateMovieInput with _$CreateMovieInput{
const factory CreateMovieInput({
required String title,
}) = _CreateMovieInput;
factory CreateMovieInput.fromJson(Map<String, dynamic> json) => _$CreateMovieInputFromJson(json);
}
@freezed
class UpdateMovieInput with _$UpdateMovieInput{
const factory UpdateMovieInput({
required String id,
String? title,
}) = _UpdateMovieInput;
factory UpdateMovieInput.fromJson(Map<String, dynamic> json) => _$UpdateMovieInputFromJson(json);
}
@freezed
class UpsertMovieInput with _$UpsertMovieInput{
const factory UpsertMovieInput({
required String id,
required String title,
}) = _UpsertMovieInput;
factory UpsertMovieInput.fromJson(Map<String, dynamic> json) => _$UpsertMovieInputFromJson(json);
}
@freezed
class DeleteMovieInput with _$DeleteMovieInput{
const factory DeleteMovieInput({
required String id,
}) = _DeleteMovieInput;
factory DeleteMovieInput.fromJson(Map<String, dynamic> json) => _$DeleteMovieInputFromJson(json);
}
Getting started
Flutter Setup
Install freezed in your flutter project
Install json_serializable in your flutter project
Download your GraphQL schema in graphql format and place it at the root of your Flutter project
npm install -g graphqurl
gq <graphql-endpoint> --introspect > schema.graphql
# if your graphql endpoint requires authentication:
gq <graphql-endpoint> -H "Authorization: Bearer <token>" --introspect > schema.graphql
Generator setup
Install the generator globally from npm
Generate your Freezed classes with the CLI
CLI Usage
Description
Generate Freezed classes from your GraphQL Schema
Usage
ffc generate [-jeuEpOS -s <string> -o <string> -f <string> -i <string> -m <string> -c <string> -w <string|string[]|boolean|undefined> -T <number>]
Options
| Options | Type Definition | Default values | Description |
| ---------------------------------------------------- | ------------------------- | -------------- | :------------------------------------------------------------------------------------------------------ |
| -s, --schema | string | optional | the path to the GraphQL Schema. Default: ./schema.graphql |
| -o, --output | string | optional | the full path of the output file. Default: ./lib/generated/app_models.dart
|
| -f, --fileName, --file-name | string | app_models | the name of the output file without the .dart extension. Appends/replaces the fileName in output option |
| -i, --ignore, --ignoreTypes, --ignore-types | string[] | [] | names of GraphQL types to ignore when generating Freezed classes |
| -j, --json, --fromJsonToJson, --from-json-to-json | boolean | true | generate fromJson and toJson methods on the classes with json_serialization |
| -e, --enum, --lowercaseEnums, --lowercase-enums | boolean | true | make enum fields lowercase |
| -u, --union, --unionConstructor, --union-constructor | boolean | true | generate empty constructors for Union Types |
| -m, --merge, --mergeInputs, --merge-inputs | string[] | [] | merge InputTypes of a pattern with an ObjectType as a union/sealed class |
| -c, --scalars, --customScalars, --custom-scalars | string | optional | a JSON.stringify object map of custom Scalars to Dart built-in types |
| -w, --watch | string|string[]|boolean | optional | regenerate when GraphQL schemas changes. Accepts a boolean or an array of glob patterns |
| -E, --errorsOnly, --errors-only | boolean | optional | print only errors |
| -p, --usePolling, --use-polling | boolean | optional | poll for changes when watch is unavailable on system |
| -T, --interval | number | optional | poll every x millisecond |
| -O, --overwrite | boolean | true | overwrite files if they already exist |
| -S, --silent | boolean | optional | suppress printing errors when they occur |
Contribution
What you can do to help
Star this repo on GitHub
Send in PRs
Share the word