Generate GraphQL Classes (Generator 2)
Ferry Generator 2 is the next-gen code generator focused on small output, fast builds, and plain Dart classes (no built_value). It's designed to be easy to read, fast to compile, and friendly to tree-shaking and runtime performance.
Migrating from the original generator? See Migrate to Generator 2.
Motivation
Generator 2 exists because the original generator optimized for built_value-based models and serializers. That approach is stable, but it produces a lot of boilerplate. Generator 2 targets:
- Smaller generated code (no builders, no serializers)
- Plain Dart models with
constconstructors and simpletoJson/fromJson - Sealed unions/interfaces with an
__unknownfallback variant - Predictable fragment reuse across operations
- Configurable
copyWith,==,hashCode,toString
Generator 2 is experimental. If you depend on
built_valuefeatures, use the existing generator (ferry_generator) instead.
Quick Start
1) Add dependencies
In your app package, add these:
ferry_execprovidesOperationRequest, which the generatedReqclasses extend.
2) Download your schema (SDL)
3) Create .graphql files
Place your operations and fragments under lib/ (any subdirectory is fine). You can import other .graphql files with comment imports:
4) Add build.yaml
5) Run build_runner
To see full logging output, run build_runner with
--verbose.
What gets generated
For each .graphql input, generator 2 can emit:
*.ast.gql.dart-constAST definitions (DocumentNodedefinitions).*.data.gql.dart- Data classes for operations and fragments.*.var.gql.dart- Variables classes (omitted if there are no vars).*.req.gql.dart- Request classes extendingOperationRequest.*.schema.gql.dart- Dart representations of schema enums, inputs, and possible-types.*.utils.gql.dart- Equality/hash helpers (only when enabled).
Notes
- If an operation has no variables, no
*.var.gql.dartis emitted and the request type isOperationRequest<Data, Null>. reqoutput depends onastoutput (the request'sDocumentNodereferences AST constants).
Polymorphism (interfaces & unions)
Generator 2 emits sealed base classes for interface/union selections and concrete subclasses for each concrete type, plus an __unknown variant. Example structure:
GSearchData_search(sealed base)GSearchData_search__asHumanGSearchData_search__asDroidGSearchData_search__unknown
Optional when/maybeWhen extensions are available for ergonomic pattern matching (enable under data_classes.when_extensions).
Fragment reuse (and dedupe)
- If a selection set is only a fragment spread (plus
__typename), generator 2 reuses the fragment class instead of creating a nested duplicate. - This ensures the same fragment used in multiple operations maps to a single class.
- You can disable this with
data_classes.reuse_fragments: false.
Transitive fragment interface inheritance only applies to unconditional fragment spreads.
Config Reference
Top-level options:
schema
file(required):package|path/to/schema.graphqladd_typenames(defaulttrue): required for polymorphic selections and when-extensionsgenerate_possible_types_map(defaulttrue): controls possibleTypes generation in schema outputoutput_dir(default__generated__)source_extension(default.graphql)
Multiple schemas are not supported. schema.files will throw.
outputs
ast,data,vars,req,schema(all defaulttrue)reqrequiresast,data, andvarsto be enabled.
data_classes
reuse_fragments(defaulttrue)when_extensions:when(defaultfalse)maybe_when(defaultfalse)
utils:copy_with(defaultfalse)equals(defaultfalse)hash_code(defaultfalse)to_string(defaultfalse)
collections
Choose how list/map fields are represented:
plain(default): standardList/Maptypes.unmodifiable: wraps generated list/map fields withList.unmodifiable/Map.unmodifiablein constructors andfromJson.
vars
tristate_optionals(defaultfalse)- When enabled, nullable inputs/vars are wrapped in
Value<T>fromgql_tristate_value.
- When enabled, nullable inputs/vars are wrapped in
docs
enabled(defaultfalse): emit doc comments from GraphQL schema descriptions.
enums
fallback:global(defaultfalse) - generate a fallback value for all enumsname(defaultgUnknownEnumValue)per_enum- map of enum name to fallback value
scalars
Define scalar mappings and custom serializers:
formatting
enabled(defaulttrue)language_version(optional, e.g.3.6)emit_format_off(defaultfalse): add// dart format offto generated files (still formats once ifenabled: true).
logging
level(defaultwarn):off | error | warn | info | debug | verboseverboseis an alias fordebug.
format(defaulttext):text | jsoncategories(default empty = all): list of categories to include for info/debug logs
Available:config,validation,schema,ir,data,vars,req,emit,build
Example:
Migration notes (v1 -> v2)
- No
built_value, no builders, noserializer_builder. - All models are plain Dart classes with
constconstructors and directtoJson/fromJson. - Equality/hash/toString/copyWith are opt-in.
schema.filesis not supported.