Is there any way to generate types for a schema using Apollo Federation directives? @key, @external, etc?
I tried to generate them but it doesn't seem to work:
For example:
extend type User @key(fields: "id") {
id: ID! @external
}
type UserRole {
type: UserType!
user: Driver
}
Error: Cannot extend type "User" because it is not defined. Did you mean "UserRole"?
Unknown directive "key".
Unknown directive "external".
Unknown type "User". Did you mean "UserRole"?
Environment:
@graphql-codegen/...: 1.3.1Hi @jsangilve !
How do you load your schema? Can you please share you codegen.yml?
I think Apollo Federation is using the directives only during it's build process, and strip it while serving the schema.
You can add a file with all the directives (federation-directives.graphql):
directive @external on FIELD_DEFINITION
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
directive @extends on OBJECT
Then, load it as part of your schema:
schema:
- http://remote-schema/graphql
- federation-directives.graphql
Thanks for your reply @dotansimha. Will try asap
@jsangilve any update? :)
Hi @dotansimha!
Sorry for the late reply.
I tried your suggestion and the errors for @key and @external directives are gone, but we still have trouble with the types, plus the _FieldSet param (as declared within the directives).
Error: Cannot extend type "User" because it is not defined. Did you mean "UserRole"?
Unknown type "User". Did you mean "UserRole"?
Unknown type "_FieldSet".
Unknown type "_FieldSet".
Unknown type "_FieldSet".
# codegen.yml
schema:
- resources/api.graphql
- resources/federation-directives.graphql
overwrite: true
generates:
src/api/types.ts:
config:
contextType: ./getContext#ApiContext
namingConvention:
enumValues: change-case#upperCase
plugins:
- add: "/* tslint:disable */"
- time
- typescript-resolvers
Just to be clear, this is not the Apollo Gateway but a federated service. The type User will never be defined here, but within a different service's schema.
My bad, you need the complete Federation directives spec:
scalar _Any
scalar _FieldSet
# a union of all types that use the @key directive
union _Entity
type _Service {
sdl: String
}
extend type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
}
directive @external on FIELD_DEFINITION
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
# this is an optional directive discussed below
directive @extends on OBJECT
(you can find it in https://www.apollographql.com/docs/apollo-server/federation/federation-spec/)
Thanks for the quick reply. Unknown errors for _Fieldset scalar are gone, but the problem type User persists.
Now that I think a little bit more about it, I guess the code generator would only work over the whole GraphQL schema (after federated services are loaded), i.e., it wouldn't be possible to generate types for a service's schema that extends types of another service' schema?
@jsangilve yeah that makes sense. Is it possible to access the other schemas you depend on? (via URL?)
Because if so, you can specify it as well as part of the schema field, and it will load and merge it.
Available since 1.5.0. You don't need to specify or add the directives now, just make sure to add federation: true and it will add it and generate a compatible signature.
@dotansimha thanks for the update!
We've been sorting out other problems with federation and didn't have time to look on this. I'll comment on this issue as soon as I give it a try with 1.5.0
@jsangilve We would love to collaborate with you on Federation in GraphQL Code Generator! Also happy to hear suggestions 馃殌 If you're interested we could talk on our Slack.
@kamilkisiela thx for working on the PR. It's quite busy right now, but I'll get back to you as soon I find time to test this. The service that's using the codegen it's not extending types right now :)
@jsangilve Could you please let me know how did you fixed this issue? The User is undefined