-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
feat: custom queries and mutations #13029
Conversation
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.
I made a pass. Have a few nits and a couple more substantive comments.
packages/api-graphql/src/internals/generateCustomOperationsProperty.ts
Outdated
Show resolved
Hide resolved
const ops = {} as CustomOpsProperty<T, OpType>; | ||
for (const operation of Object.values(operations)) { | ||
(ops as any)[operation.name] = customOpFactory( |
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.
I think we need the as
either way, but why not compose the objects and then as
it once its complete on the final assignment instead of starting empty with a proper type and composing it through attribute assignment?
I can't convince myself that there are any real differences, but it seems better to assign the type to something we're confident is right rather than assigning it to something we know doesn't meet the type and then build it up.
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.
I think it's visually better to start with {} as any
, which ends up being the same lie either way. The only difference in my mind that pushes me towards {} as SomeIntendedType
with more casts later on is that it communicates intent of the variable and forces me to check the "yes, this is on purpose" box every time by casting.
packages/api-graphql/__tests__/internals/generateClient.test.ts
Outdated
Show resolved
Hide resolved
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.
With the exception of what Aaron has already commented on, this PR looks good to me. Most of my comments are non-blocking nits. This is also non-blocking, but it looks like something is up with your Prettier configuration. The only truly blocking comment is for removal of the console.log
.
* @returns Boolean: `true` if the `o[field]` is a `string` | ||
*/ | ||
function hasStringField<Field extends string>( | ||
o: any, |
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.
Any possibility not using any
? JS codebase is in the progress of migration to stricter linter rules where any
is forbidden.
For example, at this particular spot, the type of o
could be Record<unknown, unknown>
?
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.
The amount of casting we're doing in general, including all the any
's is starting to feel somewhat egregious and a little risky. So, I agree with your general point. But, I think we should make an effort of it... I'm actually planning on spending a little time composing a sampling of the scary type/runtime mismatches that concern me, and we can plan something from there for the general case.
For this particular spot, I've taken a couple passes at changing the any
to something less broad, and it's more of a riddle than it might be worth right now. It doesn't like Record<unknown, unknown>
, and similar changes looks like they end up punting the any
elsewhere and causing a rippling effect. It looks like it'll be a similar story with some of the other any
's laying around.
And for what it's worth, I don't actually think this particular instance is high risk, since the runtime logic in the guard aligns very narrowly with the type assurance it offer. It's largely intended to take "anything" and just tell you whether "the thing" you give it has a particular [T]: string
field on it. Not a high risk any
, IMO.
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.
(I am taking a pass at clearing up the low hanging fruit on code I touched though. Stay tuned!)
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.
Not as much wiggle room as I'd have liked on some of those any's. But, I squashed a few of them.
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.
Wait. Push failed ..
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.
Ok. Pushed. Sorry for the noise.
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.
I am in alignment with this. I would be a fan of adding as much strong typing as we can and where we can't having a dev mode that turns on runtime type validation so that we can run some amount of minimal interface testing that raises when types don't match expectations.
The two cases that are hard:
- Dynamically typed interfaces, like offering custom methods for retrieving certain graphql queries.
- JSON input parsing.
In both cases, we could document the type interface in a tool like Zod (or using the same strategies) and use the same interface for enforcing runtime type guarantees when it doesn't meet the type expectations.
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.
LGTM!
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.
LGTM
7d221dd
Description of changes
Adds basic custom queries and mutations support.
E.g. schema:
E.g, client code (implemented by this PR):
Issue #, if available
Description of how you validated changes
Checklist
yarn test
passesBy submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.