[Feature request] Late resolver declaration
- Dominant language
- TypeScript
- Stars
- 2.6k
- Forks
- 184
- Avg merge
- 4h 25m
- Merged PRs (30d)
- 137
Description
Hello !
First of all, thanks a lot for Pothos, I have been playing around with it lately, and it is very comfortable and nice to use. I always try to push type safety as far as possible, so I really like the approach you had on this schema builder :)
# Feature request
I think, though, that it would be nice to be able to declare the resolvers implementation separately from the schema types. Something like:
```ts
const builder = new SchemaBuilder({});
builder.queryType({
fields: (t) => ({
hello: t.string({
args: {
name: t.arg.string(),
},
// No `resolve` attribute
}),
}),
});
// This would work fine, any resolver called at this point would throw something like `new Error("Not implemented")`
export const schema = builder.toSchema({})
// Then later or anywhere else in the codebase
builder.defineResolver({
query: {
hello: () => "Hello, world !" // Ideally, this would remain type-safe
}
})
```
# Motivation
In large projects, the resolvers usually include a lot of domain-related code, dependencies, etc.
It eventually leads to slow builds, and heavy codebases. Even worse, if I use the schema output from Pothos and generate a client out of it as it is described [here](https://pothos-graphql.dev/docs/guide/generating-client-types), not only my backend is slow to transpile, but so becomes my frontend.
Smaller projects can afford to rely on the pattern "the API declares a graphql schema, and thus a client is generated to be used afterwards in the frontend". As long as the API remains lightweight, fast to transpile, generally-speaking *simple*, well this chain-like pipeline is not to be worried about, because everything is fast.
That being said, larger projects will quickly suffer from such a pipeline. If my API takes, let us say 30 seconds to be transpiled on my local computer, then every transpilation of my frontend code will start with a 30 seconds long API transpilation, before even it can generate the client to use.
In CIs, it is dramatically worse: In addition to a slower build (30 seconds locally can easily lead to minutes in a CI/CD pipeline), I need to download and install a much larger amount of dependencies before I can even start the build pipeline of the frontend. All of these dependencies, except the `graphql` package are not necessary for pothos to declare my schema, and thus generate a client, because they are all related to business logic declared in the resolver.
Larger organizations see GraphQL as a leverage to turn the dependency chain into something like "The frontend team and the backend team settle on an interface to follow, and then they are loosely-coupled for the implementation details". This is precisely what I would like to reach in my team. This ability would lead to huge improvements in our CI time as well.
# Current solutions
Currently, it is possible to hack into a result that looks a bit like this using [the mocks plugin](https://pothos-graphql.dev/docs/plugins/mocks). Yet, it feels like a square peg in a round hole (not sure about this expression but that is the best translation I got for the french "Mettre des ronds dans des carrés").
- I lose the typing by doing so, my mocks are not type-checked
- I have to manually write `resolve: () => throw new Error("not implemented")` everywhere
- I can only declare my mocks when calling `builder.toSchema` and not using the rest of the `SchemaBuilder` API
- [secondary] I have to declare the plugins where I declare my schema and not my server (end up being weird for plugins like the tracing one)
If you feel like it could be a valuable addition to Pothos, I am 100% willing to discuss this further with you and to provide contributions for having it implemented. If anything in here is not clear, feel free to ask for clarifications, I would be happy to provide them.
Once again, Pothos is really cool, and I would love to make it fit my requirements in order to use it in my team.
Contributor guide
Research direction
Start by reading the SchemaBuilder API, the builder.toSchema flow, and the mocks plugin documentation linked in the issue. Compare how schema declarations and mocks are currently handled; done would mean a supported, type-safe way to declare resolvers later while still generating a schema with unimplemented resolvers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, typescript
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100