Configuration Reference
Every option in config.json, explained.
Complete examples
Here are fully annotated configs for all three targets. Each is a valid, working configuration for the example schema used throughout this documentation.
{
"schemaPaths": ["schema/*.graphql"],
"mode": "client",
"typeMappings": {
"ID": "String",
"String": "String",
"Float": "double",
"Int": "int",
"Boolean": "bool",
"Null": "null"
},
"outputDir": "lib/generated",
"clientConfig": {
"dart": {
"packageName": "my_app",
"generateAllFieldsFragments": true,
"autoGenerateQueries": true,
"nullableFieldsRequired": false,
"immutableInputFields": true,
"immutableTypeFields": true
}
}
}
{
"schemaPaths": ["schema/*.graphql"],
"mode": "client",
"typeMappings": {
"ID": "String",
"String": "String",
"Float": "Double",
"Int": "Integer",
"Boolean": "Boolean",
"Null": "null"
},
"outputDir": "src/main/java/com/example/generated",
"clientConfig": {
"java": {
"packageName": "com.example.generated",
"generateAllFieldsFragments": true,
"autoGenerateQueries": true,
"nullableFieldsRequired": false,
"immutableInputFields": true,
"immutableTypeFields": true
}
}
}
{
"schemaPaths": ["schema/*.graphql"],
"mode": "server",
"typeMappings": {
"ID": "String",
"String": "String",
"Float": "Double",
"Int": "Integer",
"Boolean": "Boolean",
"Null": "null"
},
"outputDir": "src/main/java/com/example/generated",
"serverConfig": {
"spring": {
"basePackage": "com.example.generated",
"generateControllers": true,
"generateInputs": true,
"generateTypes": true,
"generateRepositories": false,
"immutableInputFields": true,
"immutableTypeFields": false
}
}
}
Top-level options
| Key | Type | Required | Description |
|---|---|---|---|
schemaPaths |
string[] |
Yes | Array of glob patterns for schema files. Supports *.graphql, *.gql, and any glob syntax. Patterns are resolved relative to the config file's directory. |
mode |
"client" | "server" |
Yes | "client" generates type-safe client code. "server" generates Spring Boot scaffolding (controllers, service interfaces, types). |
typeMappings |
object |
Yes | Maps GraphQL scalar names to target language type names. Built-in scalars (ID, String, Int, Float, Boolean) must be mapped. Add custom scalars here. |
outputDir |
string |
Yes | Directory where generated files are written. Created if it doesn't exist. All generated files in this directory are overwritten on each run. |
clientConfig |
object |
When mode: "client" |
Contains a "dart" or "java" key with language-specific options. |
serverConfig |
object |
When mode: "server" |
Contains a "spring" key with server-specific options. |
Dart client options (clientConfig.dart)
| Key | Type | Default | Description |
|---|---|---|---|
packageName |
string |
— | Your Dart package name (from pubspec.yaml). Used in generated import paths. Required. |
generateAllFieldsFragments |
boolean |
false |
Generates a named fragment per type (_all_fields_TypeName) selecting all fields. Required for autoGenerateQueries. Will fail if the schema contains a type cycle — see warning below. |
autoGenerateQueries |
boolean |
false |
Automatically builds query strings for every operation using _all_fields fragments. When true, you never write query strings by hand. Requires generateAllFieldsFragments: true and a cycle-free schema. |
nullableFieldsRequired |
boolean |
false |
When true, nullable fields are also required in constructors (but still T? typed). When false, nullable fields are optional constructor parameters. |
immutableInputFields |
boolean |
true |
Makes input class fields final. Strongly recommended. |
immutableTypeFields |
boolean |
true |
Makes response type class fields final. Strongly recommended for client code. |
Schema cycles and generateAllFieldsFragments
If your schema contains a type cycle — for example Person has a field vehicles: [Vehicle!]! and Vehicle has a field owner: Person! — the generator will fail at parse time with:
This happens because _all_fields_Person must include all fields of Person, which includes vehicles, whose _all_fields_Vehicle fragment in turn includes owner, which references _all_fields_Person again — an infinite loop.
This is a known limitation with no planned fix. The recommended solution is to break the cycle in the schema itself by introducing a projection type that omits the back-reference:
type Person {
id: ID!
name: String!
vehicles: [Vehicle!]! # Vehicle references Person → cycle
}
type Vehicle {
id: ID!
brand: String!
owner: Person! # back-reference creates the cycle
}
# Projection type — same fields as Person, but no vehicles field
type PersonInfo {
id: ID!
name: String!
}
type Person {
id: ID!
name: String!
vehicles: [Vehicle!]!
}
type Vehicle {
id: ID!
brand: String!
owner: PersonInfo! # references PersonInfo, not Person → no cycle
}
_all_fields_Vehicle now depends on _all_fields_PersonInfo, which has no further type references. The cycle is broken and generation succeeds.
If breaking the cycle is not possible, set both generateAllFieldsFragments and autoGenerateQueries to false and write your query strings manually.
Java client options (clientConfig.java)
| Key | Type | Default | Description |
|---|---|---|---|
packageName |
string |
— | Base Java package for generated classes (e.g. "com.example.generated"). Required. Subpackages (.types, .inputs, .enums, .client) are created automatically. |
generateAllFieldsFragments |
boolean |
false |
Same as Dart — generates _all_fields fragments per type. Will fail if the schema contains a type cycle — see warning below. |
autoGenerateQueries |
boolean |
false |
Generates query string constants for every schema operation. |
nullableFieldsRequired |
boolean |
false |
Controls whether nullable fields require explicit null in builders. |
immutableInputFields |
boolean |
true |
Makes input fields final with Objects.requireNonNull for required fields. |
immutableTypeFields |
boolean |
true |
Makes response type fields final (no setters). Set false for Spring server types. |
Spring Boot options (serverConfig.spring)
| Key | Type | Default | Description |
|---|---|---|---|
basePackage |
string |
— | Base Java package for all generated server files. Required. |
generateControllers |
boolean |
true |
Generates @Controller classes with Spring GraphQL annotations (@QueryMapping, @MutationMapping, @SubscriptionMapping, @Argument). |
generateInputs |
boolean |
true |
Generates Java classes for all input type definitions in the schema. |
generateTypes |
boolean |
true |
Generates Java classes for all type definitions (excluding Query, Mutation, Subscription). |
generateRepositories |
boolean |
false |
Generates JpaRepository interfaces for types annotated with @glRepository. |
immutableInputFields |
boolean |
true |
Makes server-side input fields final. |
immutableTypeFields |
boolean |
false |
Controls whether type class fields have setters. Must be false for Spring's GraphQL runtime to set fields via reflection. Set true only if you handle deserialization yourself. |
typeMappings — custom scalars
GraphQL supports custom scalars for types like Date, DateTime, BigDecimal, URL, etc. Add them to typeMappings to control the generated language type:
{
"typeMappings": {
"ID": "String",
"String": "String",
"Float": "Double",
"Int": "Integer",
"Boolean": "Boolean",
"Null": "null",
"DateTime": "OffsetDateTime",
"BigDecimal": "BigDecimal",
"URL": "String",
"Long": "Long",
"UUID": "UUID"
}
}
For scalars that require an import statement, use the @glExternal directive on the scalar definition in your schema instead. See the @glExternal directive for details.
Running the CLI
# Generate once
glink -c config.json
# Watch mode — regenerate on schema file changes
glink -c config.json -w
# Print version
glink --version
# Print help
glink --help
The -c / --config flag is the only required argument. Paths in the config file (schemaPaths, outputDir) are resolved relative to the config file's location, not the current working directory. This means you can run glink from any directory as long as you provide the correct path to the config file.
Multiple configs in one project
A monorepo with a Dart frontend and a Java Spring backend can have two separate config files — dart-config.json and spring-config.json. Run both: glink -c dart-config.json && glink -c spring-config.json. Both read the same schema; each writes to its own output directory.