graphql-zeus has become my favorite GraphQL client in large part to not having to constantly run code generation every time I write a new query, only when my schema changes. Queries are simple and type safe:
const response = await client('query')({
tags: [{
where: {
site_id: {
_eq: siteId
}
}
}, {
id: true,
name: true
}]
});
There's a lot of TypeScript wizardry going on behind the scenes to make type safety a reality. If you've ever opened up the generated zeus.ts
file, you know what I'm talking about.
While it is obvious how to create a new instance of Chain
to run queries, it's not obvious how to possibly pass the client around to functions to share an instance when needed. I mean, look at this:
export const Thunder = (fn: FetchFunction) => <
O extends keyof typeof Ops,
R extends keyof ValueTypes = GenericOperation<O>
>(
operation: O,
) => <Z extends ValueTypes[R]>(o: Z | ValueTypes[R], ops?: OperationOptions) =>
fullChainConstruct(fn)(operation)(o as any, ops) as Promise<InputType<GraphQLTypes[R], Z>>;
TypeScript makes this very simple to do, thanks to ReturnType. Define your own type by defining the following somewhere shared outside your generated client:
import { Chain } from "zeus";
export type GraphQLClient = ReturnType<typeof Chain>;
Then use this type whenever you need to pass or return Chain
:
const getTaggedPosts = ({
client
}: {
client: GraphQLClient;
}) => {
// run query here using `client`
}
It's possible something like this is built in but I couldn't find it after a little digging.