[FEAT] Context Type Automatic Detection
Is your feature request related to a problem? Please describe. Pardon if this is already implemented, but the ability to override the context type in a similar fashion to other type mappings.
Describe the solution you'd like
Maybe ContextTypeMapper or even just ContextType
Describe alternatives you've considered
Currently using presetConfig.typesPluginConfig.contextType and it's working very well, but wanted to call this out.
Good idea @RichiCoder1 ! It's not currently implemented at the moment.
Do you have a suggestion for the file name? 🙂
Maybe just schema.context.ts? And warn if there are multiple matches with first winning?
Would export Context. So basically an automatic schemas/base/schema.context.ts#Context.
Nice! I think we are onto something here 🙌
Maybe the export could be ResolversContext to be more explicit?
There's also fieldContextTypes option in typescript-resolvers which could be used to set context on the field level...
So, I'm thinking each module could declare its own schema.context.ts file. For example:
If schema/user/schema.context.ts has Query_userResolversContext (context applicable to user query), then it'd be mapped to:
fieldContextTypes: ['Query.user#./schema/user/schema.context.ts#Query_userResolversContext']
Just to be certain this is what I'm also looking for. This would mean that the ResolversContext type definition in schema.context.ts will be imported by types.generated.ts and hence propagated. Correct?
Curious if this could also result in generating a context "resolver" file similar to what graphql-yoga would expect. But I suppose that's a feature on top of that as well.
Hi @karloluis ,
This would mean that the ResolversContext type definition in schema.context.ts will be imported by types.generated.ts and hence propagated. Correct?
Yes! That's correct.
You could already use the context type like this when creating GraphQL Yoga server:
const yoga = createYoga<{}, ResolverContext>({
context: { ... }, // <-- Context object/function is typed to `ResolverContext`
});
Each GraphQL server may have a different type for its context "resolver", so I'm not sure we should generate it. 🙂
Any updates here? Is there any way to specify the context type with this plugin? The docs state to use {config: contextType: 'MyCustomContext'}} but not clear how to integrate that with this plugin's defineConfig()... should the results of defineConfig() be updated with contextType, or is there another way?
EDIT: Nevermind, found it. typesPluginConfig.contextType
It's been a few months and I decided to update to version 0.8.0. Hurray! 🎉
Looking back at the configs I am still stuck on how to configure a default ContextType. My generated types look as follows:
export type QueryResolvers<
ContextType = any,
ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query'],
> = { ... }
With the use of generates."src/graphql".presetConfig.typesPluginConfig.contextType: "./context.ts#Context" I expected ContextType = any to change to reference the exported type from the file. Sadly that didn't happen and after tinkering around for a bit I have not been able to figure things out. Same could be said if I targeted Resolvers<ContextType = any>.
Is my understanding that the any type should reference the Context type incorrect? Could I be missing something with regards to the ts-resolver plugin?
Yes, that's correct @karloluis.
Here's an example repo: https://github.com/eddeee888/graphql-server-template/
- The context config is here: https://github.com/eddeee888/graphql-server-template/blob/bcf63ee72f59d656257f770978c6ca45cdf4287b/codegen.ts#L12...
- Which points to this type
Well that's awkward. After tinkering with the file a bit more and testing the typesSuffix option to validate that the options were in fact picked up it suddenly started working whereas a few runs ago it didn't seem to do any changes!
I suspect my runtime for codegen was somehow faulty. Maybe bad YAML indentation.
Hi there, I ran into this issue as well where my src/schema/types.generated.ts had ContextType of any.
Following your comment to edit the config in codegen.ts did the trick, so thank you 👍
My updated codegen.ts
import { defineConfig } from '@eddeee888/gcg-typescript-resolver-files';
import type { CodegenConfig } from '@graphql-codegen/cli';
export default {
schema: '**/schema.graphql',
generates: {
'src/schema': defineConfig({
emitLegacyCommonJSImports: false, // enables ESM imports with .js ext
typesPluginsConfig: {
contextType: '../index.js#ApolloServerContext',
},
}),
},
} satisfies CodegenConfig;
What are your thoughts on mentioning this config in the Guide: GraphQL Yoga / Apollo Server with Server Preset guide?
(Thanks for this library btw. I like the conventions it enforces)
Good idea @zach-betz-hln ! I'll add a new section about context type since it's a fairly common question
@eddeee888 question in this context 😸 ...
For typescript projects of type: module, when defining the context, can we configure exports to append the output filetype as .js?
Right now I'm achieving this using the following config:
const config: CodegenConfig = {
schema: 'src/**/schema.graphql',
generates: {
'src/gql-gen': defineConfig({
add: {
'./types.generated.ts': {
content: "import { MyContext } from '../types/MyContext.js'",
},
},
emitLegacyCommonJSImports: false,
typesPluginsConfig: {
federation: true,
contextType: 'MyContext',
},
}),
},
};
This totally works, but just took me a while to work out. If this is the way this needs to be done, should an example of this be added to docs/examples?
Is there a better way to do this?
Hello @LongLiveCHIEF ! Thanks for sharing your solution!
contextType could be used to declare the type extension if you prefer e.g.
const config: CodegenConfig = {
schema: 'src/**/schema.graphql',
generates: {
'src/gql-gen': defineConfig({
emitLegacyCommonJSImports: false,
typesPluginsConfig: {
federation: true,
contextType: 'path-to/MyContext.js#MyContext',
},
}),
},
};
Hi @LongLiveCHIEF I think this line is key, which emits imports with a .js ext:
emitLegacyCommonJSImports: false
For our projects that have:
-
"type": "module"inpackage.json -
"moduleResolution": "node16"intsconfig.json
Then though it is a TS project, imports must end with a .js ext. More info here on why.