Closed rolivegab closed 1 month ago
Using t.string in your helper is probably defining things backwards, and it looks like it might result in using arg fields where input object fields are expected.
The way I would build this is so that you define your helper more like:
args: inputArgs(itemObjectType, t, {
id: 'string',
}),
Then in your helper you can match on the input type to define the correct field type based on that
The slightly complicated part about that will be creating the right type, but if these are all scalar fields, you could use the Scalar type-names. This isn't exactly what you are looking for (needs some tweaking of arguments) but it shows how this could work:
builder.queryField('test', (t) =>
t.field({
type: 'String',
args: getInputType(t, {
foo: 'String',
}),
resolve: (_, args) => {
console.log(args.AND?.foo);
return 'test';
},
}),
);
type WhereInputShape<Types extends SchemaTypes, T extends Record<string, ScalarName<Types>>> = {
[k in keyof T]: InputShape<Types, T[k]>;
} & {
AND: WhereInputShape<Types, T> | null;
OR: WhereInputShape<Types, T> | null;
};
function getInputType<
Types extends SchemaTypes,
T,
Fields extends Record<string, ScalarName<Types>>,
>(
fieldBuilder: PothosSchemaTypes.FieldBuilder<Types, T>,
fields: Fields,
): {
[k in keyof WhereInputShape<Types, Fields>]: InputFieldRef<WhereInputShape<Types, Fields>[k]>;
} {
const WhereInput = builder.inputRef<WhereInputShape<Types, Fields>>(
`WhereInput${fieldBuilder.typename}`,
);
WhereInput.implement({
fields: (t) =>
({
...Object.fromEntries(
Object.entries(fields).map(([key, value]) => [key, t.field({ type: value as never })]),
),
AND: t.field({ type: [WhereInput] }),
OR: t.field({ type: [WhereInput] }),
}) as any,
});
return {
...Object.fromEntries(
Object.entries(fields).map(([key, value]) => [
key,
fieldBuilder.arg({ type: value as never }),
]),
),
AND: fieldBuilder.arg({ type: [WhereInput] }),
OR: fieldBuilder.arg({ type: [WhereInput] }),
} as any;
}
Thank you @hayes ! Your idea worked very well and I learned a lot from it.
I'm creating an assist to help me writing graphql types without write a lot of things, so something like this:
can turn into this:
the thing is that, while it's already working, I don't have a way to know if a
t.arg.string()
is a string during runtime, so I'm forced to write the args like this:It would be much nicer if I have a way to tell, during runtime, that a
t.arg.string()
is from type 'string' without being forced to provide more information.This is how implementation looks like internally: