New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use GraphQL Codegen to generate more accurate resolver types #5216
Conversation
✅ Deploy Preview for redwoodjs-docs canceled.
|
try { | ||
// Extract the models from the prisma client and use those to | ||
// set up internal redirects for the return values in resolvers. | ||
const localPrisma = require('@prisma/client') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require
-ing from the user's node_modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out - I get your reservation that it feels a little off, but I also think Prisma is designed to do this, with the generated types ending going into node_modules anyway!
This feels somewhat the right thing to do with the services definitions. |
@orta not really related to the changes here but what would you imagine for the Relay style resolver generator? |
wow cool - dotansimha/graphql-code-generator#6379 its in the space for what I was thinking, yep - that's a clever TypeScript approach (using the string of the query to be a matcher against a central type mapping) I think structurally I'd still end up with something a bit simpler. E.g. each set of resolvers in each SDL string would end up with a corresponding It's a clever exploration as it looks like there are WIP builds, I will give it a run at some point (that shouldn't need to block this PR) - thanks |
Nice one @orta - I do prefer this approach a lot more - as it keeps the type generation all in "one place". Let me try a few things out and I'll merge - looks like you've covered all the tests and stuff already! Thank you so much! |
Needs one small change, fixing and will merge afterwards! |
packages/cli/src/commands/generate/service/templates/service.ts.template
Outdated
Show resolved
Hide resolved
Added a few small fixes and tested with:
|
Nice |
…ok-smoke-test * 'main' of github.com:redwoodjs/redwood: Use GraphQL Codegen to generate more accurate resolver types (redwoodjs#5216) chore(deps): update dependency @clerk/clerk-sdk-node to v3.3.8 (redwoodjs#5345) fix(deps): update dependency jest-watch-typeahead to v1.1.0 (redwoodjs#5339)
…-core-tests * 'main' of github.com:redwoodjs/redwood: (668 commits) Fix broken link in authentication.md (redwoodjs#5394) Update local-postgres-setup.md (redwoodjs#5353) modify typescript example (redwoodjs#5377) fix(deps): update dependency core-js to v3.22.3 (redwoodjs#5376) fix(deps): update dependency @types/node to v16.11.32 (redwoodjs#5374) fix(deps): update prisma monorepo to v3.13.0 (redwoodjs#5375) chore(deps): update dependency typescript to v4.6.4 (redwoodjs#5372) chore(deps): update dependency nodemon to v2.0.16 (redwoodjs#5364) fix(docs): add WindiCSS in setup ui list (redwoodjs#5369) chore(deps): update dependency @nhost/nhost-js to v1.1.6 (redwoodjs#5363) Add back git fetch step for lerna chore(deps): update dependency @clerk/clerk-sdk-node to v3.3.10 (redwoodjs#5358) fix(deps): update dependency @types/node to v16.11.28 (redwoodjs#5326) update all contributors (redwoodjs#5357) Patch all-contributors-cli (redwoodjs#5356) Remove unused `SubmitHandler` in example JavaScript code (redwoodjs#5352) Use GraphQL Codegen to generate more accurate resolver types (redwoodjs#5216) chore(deps): update dependency @clerk/clerk-sdk-node to v3.3.8 (redwoodjs#5345) fix(deps): update dependency jest-watch-typeahead to v1.1.0 (redwoodjs#5339) Update yarn.lock ...
Forgot to note for folks how extend the GraphQL context - so here's a quick example from my codebase's import { createGraphQLHandler } from "@redwoodjs/graphql-server"
import directives from "src/directives/**/*.{js,ts}"
import sdls from "src/graphql/**/*.sdl.{js,ts}"
import services from "src/services/**/*.{js,ts}"
import { getCurrentUser } from "src/lib/auth"
import { db } from "src/lib/db"
import { logger } from "src/lib/logger"
import { APIGatewayProxyEvent } from "aws-lambda"
// Extends the context API type with a new string
declare module "@redwoodjs/graphql-server/dist/functions/types" {
interface RedwoodGraphQLContext {
gamePlayUserID: string
}
}
// Then this is how I add to the context via extraPlugins
export const handler = (event: APIGatewayProxyEvent, context: any) =>
createGraphQLHandler({
getCurrentUser,
loggerConfig: { logger, options: {} },
directives,
sdls,
services,
extraPlugins: [
{
onExecute: async (e) => {
e.extendContext({ gamePlayUserID: event.headers["thingy-gameplay-id"] })
},
},
],
// ...
})(event, context) |
Thanks @orta - the other way you can do this is, which admittedly is undocumented (but in the types). I'll make sure I add it into the docs shortly export const handler = (event: APIGatewayProxyEvent, context: GlobalContext) =>
createGraphQLHandler({
getCurrentUser,
loggerConfig: { logger, options: {} },
directives,
sdls,
services,
context: () => {
return {
...context,
gamePlayUserID: event.headers["thingy-gameplay-id"] }
}
}
// ...
})(event, context) I haven't tried it recently, but I think you can also avoid wrapping the function if you want, because the context already has the event as |
Alternative to #4786
This method tweaks GraphQL codegen to get accurate types, instead of bending the type system to fit (e.g. #4786), this work certainly makes me yearn for relay-compiler style generation of resolver types where it creates the exact types you need instead of a multi-thousand line file where we can pick useful bits out.
Anyway, this seems to work pretty well in strict and unstrict environments. It handles the date/string mismatch by making Prisma models be the default expectation of an resolver. This option has its downsides (I have a few resolvers which return dumb js objects in some places, but that's a rarity.)
Here's an example of a file using this setup:
( dnull is essential to working with prisma/graphql to handle this issue and avoid data loss, it might be worth thinking about integrating it properly in some way )