Skip to content

Navigation Menu

Sign in
Sign up

Extend type programatically #2617

Unanswered
dennis-koster asked this question in Q&A
Discussion options

Hi,

I am creating a custom directive that can be applied on a type definition. The aim is for it to generate an additional type, based on the type the directive is applied to and then extend the original type with an attribute that refers to the generated type.

I have managed to generate the new type programatically using the type registry in the manipulateTypeDefinition method to register a new ObjectType. However, I am am struggling to find a way to register a type extension.

Here is what I am trying to achieve in a nutshell. Given this schema:

type NewsItem @translatable {
 id: ID!
 title: TranslatableString!
 intro: TranslatableString
 content: TranslatableString
}

I want the following to be generated:

# This I have managed
type NewsItemTranslation {
 locale: String!
 title: String!
 intro: String
 content: String
}
# This I need help with
extend type NewsItem {
 translations: [NewsItemTranslations!]!
}

Any nudge in the right direction would be hugely appreciated!

You must be logged in to vote

Replies: 2 comments 1 reply

Comment options

UPDATE: I have now, somewhat, managed to add the translations field to the type defintion of NewsItem with the code below. However, I can not image this being the correct way with all of these nested node instantiations.

public function manipulateTypeDefinition(
 DocumentAST &$documentAST,
 TypeDefinitionNode &$typeDefinition
): void {
 $typeName = $typeDefinition->getName()->value;
 /** @var ObjectTypeDefinitionNode $rootType */
 $rootType = $documentAST->types[$typeName];
 $rootType->fields = ASTHelper::prepend(
 $rootType->fields,
 new FieldDefinitionNode([
 'name' => new NameNode([
 'value' => 'translations',
 ]),
 'type' => new NonNullTypeNode([
 'type' => new ListTypeNode([
 'type' => new NonNullTypeNode([
 'type' => new NamedTypeNode([
 'name' => new NameNode([
 'value' => $typeName . 'Translation',
 ]),
 ]),
 ]),
 ]),
 ]),
 'directives' => new NodeList([]),
 'arguments' => new NodeList([]),
 ]),
 );
}
You must be logged in to vote
0 replies
Comment options

You can take some inspiration from the PaginationManipulator class since it does a similar transformation as you are trying to achieve:

$connectionType = Parser::objectTypeDefinition(/** @lang GraphQL */ <<<GRAPHQL
"A paginated list of {$fieldTypeName} edges."
type {$connectionTypeName} {
"Pagination information about the list of edges."
{$paginationType->infoFieldName()}: PageInfo! @field(resolver: "{$connectionFieldClass}@pageInfoResolver") {$this->maybeInheritCacheControlDirective()}
"A list of {$fieldTypeName} edges."
edges: [{$connectionEdgeName}!]! @field(resolver: "{$connectionFieldClass}@edgeResolver") {$this->maybeInheritCacheControlDirective()}
}
GRAPHQL

Especially using Parser::objectTypeDefinition (and friends) might be interesting to create those objects from GraphQL code.

You must be logged in to vote
1 reply
Comment options

Great find! I'll see if I can get to work, thanks for the tip!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /