Open eddeee888 opened 6 months ago
Hi @nikhilgupta345,
Let's track your issue here.
I believe your use case is correct in terms of how GraphQL works. It's the type generation that's the issue.
There are 2 main problems here:
UserMapper
is not applied correctlyTo wire up UserMapper
manually, we can do this:
schema: "**/*.graphql"
generates:
src/schema:
preset: "@eddeee888/gcg-typescript-resolver-files"
watchPattern: "**/*.mappers.ts"
presetConfig:
mode: "merged"
resolverGeneration: all
typesPluginsConfig:
resolversNonOptionalTypename: false
mappers:
User: "./schema.mappers#UserMapper" # manually wire up UserMapper to User
However, this has its own problem... explained in the next section
With the setup in (1.), here's what's happening:
a. We can return UserMapper
to User
node:
// src/schema/Query/user.ts
export const user: NonNullable<QueryResolvers['user']> = async (
_parent,
_arg,
_ctx
) => {
// we can now return `UserMapper` here 🎉
return {
id: "123",
isAdmin: true,
};
};
b. And we can access UserMapper
in UserResolver
:
export const User: UserResolvers = {
// typeof Parent is UserMapper 🎉
__resolveType: (parent) => {
if (parent.isAdmin) {
return "AdminUser";
}
return "CustomerUser";
},
};
c. HOWEVER, the parent
of AdminUser
and CustomerUser
are not UserMapper
export const AdminUser: AdminUserResolvers = {
// ❌ parent should be `UserMapper` but it's `AdminUser`
adminName: (parent) => {
},
};
To make the parent of (c.) UserMapper, we'd have to again manually wire up the type e.g.
// src/schema/schema.mappers.ts
export type UserMapper = { id: string; isAdmin: boolean };
export type AdminUserMapper = UserMapper
export type CustomerUserMapper = UserMapper
So, it's basically back to the other way in https://github.com/eddeee888/graphql-code-generator-plugins/issues/266 😅
Note that the good thing about the way where we declare AdminUserMapper
and CustomerUserMapper
is that any other resolver return AdminCustomer
or CustomerUser
node also need to return mapper, which makes the parent
type consistent e.g.
Query {
adminUser: AdminUser
}
Then, the Query.adminUser
is like this:
export const adminUser = () => {
return something // `something` is `AdminUserMapper`
}
Thanks for digging in! I'm not able to actually get the mapper working properly. This is my codegen.ts:
const config: CodegenConfig = {
overwrite: true,
schema: "**/*.graphql",
generates: {
"src/graphql": {
preset: "@eddeee888/gcg-typescript-resolver-files" as any,
presetConfig: {
mode: "merged",
resolverGeneration: "all",
typesPluginsConfig: {
contextType: "./context#Context",
resolversNonOptionalTypename: false,
mappers: {
Integration: "./integration/schema.mappers.ts#IntegrationMapper",
},
},
scalarsOverrides: {
ID: {
type: "number",
},
},
},
},
},
hooks: {
afterOneFileWrite: ["prettier --config ../.prettierrc --write"],
},
};
In this case the base type is Integration
(not User) but there's no __resolveType
on the IntegrationResolver. Any idea what's wrong? It's also created a ton of additional type resolvers in the root rather than within their constituent folders. (e.g. I would expect Integration.ts
to be within the integration
folder)
Hi @nikhilgupta345 ,
mode: "merged"
will put all the files at root. Doc.
For why IntegrationResolvers
resolvers doesn't have __resolveType
, I'm confused 🤔 I'm trying a setup and it seems to work ok.
Maybe you could send the minimal schema snippet here and I could git it a go?
Hi @nikhilgupta345 ,
Apologies for the long delay! I have released an alpha version to correctly detect and wire up interface mappers:
yarn add -D @eddeee888/gcg-typescript-resolver-files@pr314-run570-1
Here's the PR with the alpha version to your repro repo: https://github.com/nikhilgupta345/repro-graphql-codegen-bug/pull/1
And here's the screenshot where parent
is UserMapper:
From https://github.com/eddeee888/graphql-code-generator-plugins/issues/266#issuecomment-2111635370