PR on GitHub: https://github.com/dotansimha/graphql-code-generator/pull/7383
Goals:
Challenges
The base SDK code is static and the same for every project that uses the artifacts of the Typed Document Node Builder SDK.
The available fields and argument configuration is provided to the base SDK via TypeScript Generics.
For each of the entry root types (Query, Mutation, Subscription), three Generics must be provided.
T_SelectionSet: Contains a tree of all fields that are selectable on a given root type (links to sub-ObjectTypes).
// Example selection set tree structure
type SDKSelectionSetUser = SDKSelectionSet<{
id?: boolean;
login?: boolean;
bestFriend?: SDKSelectionSetUser;
}>;
// root query selection set
type SDKSelectionSetQuery = SDKSelectionSet<{
__typename?: boolean;
user?: SDKSelectionSetUser & {
[SDKFieldArgumentSymbol]: {
id: string | never;
};
};
}>;
The SDKSelectionSet
helper applies some GraphQL specific constraints.
type A = { a: number }
both const a1: A = { a: 1 }
and const a2: A = { a: 1, b: 2 }
are legal assignments. In our SDK we want minimal runtime overhead. The helper type allows treating the latter assignment as a compiler error. For more detail refer to the AtLeastOnePropertyOf
and NoExtraProperties
types that enforce this behavior.T_Arguments: Contains a tree of all optional and mandatory arguments on each given root type (links to sub-ObjectTypes). Instead of having this within T_SelectionSet this type is also used for doing advanced type matching for ensuring that field arguments only reference variable definitions with a matching type.
// Example argument tree structure
type SDKArgumentsUser = {
friends:
// Sub-arguments of the type this field resolves to.
SDKArgumentsUser
// Arguments for this field.
& {
[SDKFieldArgumentSymbol]: {
whereNameNeedle: 'String';
first: 'Int',
after: 'String'
};
}
};
type SDKArgumentsQuery = {
user: SDKArgumentUser & {
[SDKFieldArgumentSymbol]: {
id: 'ID!';
};
};
};
The given example describes the argument required for the user field on the root Query type.
T_Result: Contains a tree of the execution result (currently this is simply what the basic typescript codegen plugin emits).
In addition, a T_InputTypeMap type must be provided which is a lookup map for the variable values.
type SDKInputTypeMap = {
String: string;
Int: number;
Boolean: number;
};
The instantiation of the SDK with those generics is the following: