Comments (4)
Hi @loucadufault ,
On top of the "fields missing from the mapped type must be required" scenario, there are a few cases we need to consider:
- If the type of a mapper's field does not match the schema type's field with the same name, the field resolver must be impl. In the example below,
isAdmin
resolver is required in the following case becauseyes | no
must be converted toboolean
to avoid runtime error.
// schema
type User {
isAdmin: Boolean!
}
// mapper
type UserMapper = {
isAdmin: "yes" | "no"
}
- Mapper can be anything e.g.
string
, types fromnode_modules
, inferred type, even a class
To be able to handle more complex cases effectively, we need to be able to do static analysis to compare the mapper against the generated TypeScript type. This can be done most effectively using the TypeScript compiler.
However, adding static analysis into the typescript-resolvers
plugin may not be as effective as it sounds. One reason is performing static analysis in TypeScript could be complex, and adding it to the base plugin could make it much harder to maintain.
This is why Server Preset (@eddeee888/gcg-typescript-resolver-files) was created. It uses the generated types from typescript-resolvers
plugins and compare it against the mapper types, handling the mentioned missing fields and other complex cases.
In your example, it'd automatically generate resolver files and mark the resolvers that need mappings, and tell the developer why it needs to be implemented:
export const Book: BookResolvers = {
author: () => {
/* Book.author resolver is required because Book.author exists but BookMapper.author does not */
},
}
Here's another demo where server preset adds required resolvers on mapper type changes:
server-preset.mov
There's more to features as well, you can read more on how it works and how to set it up here: https://the-guild.dev/graphql/codegen/docs/guides/graphql-server-apollo-yoga-with-server-preset
from graphql-code-generator.
Closing this because this is better addressed in Server Preset. If you have issues related to Server Preset, please create an issue in https://github.com/eddeee888/graphql-code-generator-plugins (It's in a separate repo but I'm working closely with the Codegen team)
from graphql-code-generator.
Thanks for the reply
If the type of a mapper's field does not match the schema type's field with the same name, the field resolver must be impl.
Are these actual graphql-js semantics, that it will attempt to call the next resolver if the current one returned an unexpected type?
- Mapper can be anything e.g. string, types from node_modules, inferred type, even a class
To be able to handle more complex cases effectively, we need to be able to do static analysis to compare the mapper against the generated TypeScript type. This can be done most effectively using the TypeScript compiler.
However, adding static analysis into the typescript-resolvers plugin may not be as effective as it sounds. One reason is performing static analysis in TypeScript could be complex, and adding it to the base plugin could make it much harder to maintain.
Can you elaborate on this supposed complexity? To me it just seems like a deep type equality check, I can't imagine that is an unsolved problem in the TypeScript world. As far as checking for all the possible types, since TS types just wrap JS primitives, in this case an object, it comes down to checking properties.
I'm mainly not understanding the argument as to why this must be in a separate project; in my view this feature of codegen is fundamentally broken as it stands.
from graphql-code-generator.
that it will attempt to call the next resolver if the current one returned an unexpected type?
The next resolver in the chain will always be called if provided. If the last one in the chain return a type that does not match the final output type, it'd send an error.
Can you elaborate on this supposed complexity?
Sure, here's one of the issues of doing it in base resolver plugin:
Generally, to effectively run TypeScript checks we need to load files into compiler's Program
with compiler options. Then, we load files (virtual or physical), and do property checks, etc. Using the TypeScript compiler helps us do inferred type, type alias, interfaces, etc. mappers correctly
So, here's what we'd need to do:
- The base resolver generates some output, but before we generate this output to physical files...
- We need to load that output into the Program, load all mappers into the Program...
- Do statical analysis to find missing fields...
- Re-run codegen logic with missing fields to make them required...
- Return the output to Codegen engine to generate the physical files
Apart from running the same logic twice, we need to use typescript
or ts-morph as a hard dependency for the base resolver.
This will have performance impact to all existing users.
in my view this feature of codegen is fundamentally broken as it stands.
If you have ideas how to fix issues at the base plugin level, feel free to create a PR 🙂
from graphql-code-generator.
Related Issues (20)
- Need update dependence called @graphql-tools/prisma-loader to 8.0.2 for addressing vulnerabilities in jose v4.14.4 HOT 1
- Separation of generated Plugin pages content (top & API config components)
- `skipDocumentsValidation` is missing in `CodegenConfig`
- ignoreNoDocuments suppresses errors
- Use --env-file in node 20 HOT 4
- top level await fails codegen HOT 2
- Add support for removing fragments in a payload
- BUG codegen incorrectly changes order for persisted operations
- schema import types (or GraphQLSchema) from typescript HOT 11
- Update @whatwg-node/fetch to avoid punycode deprecation warning in Node HOT 2
- Non-nullable fields on an input object type
- Codegen forces resolution of relationships even if they aren't requested in the query HOT 2
- Decorator auto accessors syntax is not supported
- Typeerror occurs when trying to pass whole fragment array to another FragmentType<>[] prop
- Urql variables should support Vue refs (MaybeRef)
- [cli] CLI stops handling local plugins written in TypeScript since v3.2.2
- Fragment match export name
- [plugin/add] Cannot import config type
- Remove need for babel or swc plugin on client preset for reducing bundle size/code splitting HOT 13
- [preset/client] Custom hash function for persisted operations HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql-code-generator.