How to pass arguments to resolve function in a GraphQL Object? - arguments

I'm using GraphQL in Javascript, and I'd like to be able to pass arguments to a resolve() function in a GraphQLObjectType's field.
Here is the GraphQLObjectType declaratio:
export const ModelSchema = new GraphQLObjectType({
name: 'Model',
description: 'Model information',
fields: () => ({
tags: {
type: TagList,
description: 'Model\'s UUID',
async resolve(obj, args) {
console.log('args', args); // expecting to see an object
},
},
}),
});
And here is how I want to query in GraphQLI:
{
getModels(UUIDs:"0AAAA2EFF6677194ED227EE4AAAA8D4A") {
total
models {
tags (limit: 1) {
tags {
UUID
name
}
}
}
}
}
So I want to be able to send parameters (in this case limit) to tags so when the resolve() function is being invoked, I can use this parameter and limit the results, or do something else.
How can I do it?
Thanks

Ok, got it... Needed to add args like so:
export const ModelSchema = new GraphQLObjectType({
name: 'Model',
description: 'Model information',
args: {
limit: {
type: GraphQLInt,
},
},
fields: () => ({
tags: {
type: TagList,
description: 'Model\'s UUID',
async resolve(obj, args) {
console.log('args', args); // expecting to see an object
},
},
}),
});
And now it works.

Related

How to change property values for an object nested in an array in graphql?

I've just started to learn GraphQL recently and have decided to implement it in a react based polling app where users can create and vote on polls.
I've created a mongoose model that looks like this https://github.com/luckyrose89/Voting-App/blob/master/backend/models/poll.js.
I'm facing an issue with adding upvotes to a poll option while writing Graphql mutations. So far my schema looks like this:
const AnswerType = new GraphQLObjectType({
name: "Answer",
fields: () => ({
id: { type: GraphQLID },
option: { type: GraphQLString },
votes: { type: GraphQLInt }
})
});
const QuestionType = new GraphQLObjectType({
name: "Question",
fields: () => ({
id: { type: new GraphQLNonNull(GraphQLID) },
question: { type: GraphQLString },
answer: { type: GraphQLList(AnswerType) }
})
});
const AnswerTypeInput = new GraphQLInputObjectType({
name: "AnswerInput",
fields: () => ({
option: { type: GraphQLString },
votes: { type: GraphQLInt }
})
});
const QuestionTypeInput = new GraphQLInputObjectType({
name: "QuestionInput",
fields: () => ({
question: { type: new GraphQLNonNull(GraphQLString) },
answer: { type: new GraphQLNonNull(GraphQLList(AnswerTypeInput)) }
})
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addPoll: {
\\\\ code here
},
deletePoll: {
\\\\\ code here
},
upvotePoll: {
type: QuestionType,
args: { id: { type: new GraphQLNonNull(GraphQLID) } },
resolve(parent, args) {}
}
}
});
So I've defined my types and I can add and delete polls and access a single poll(I've skipped my queries section here). But I don't understand how to access a single poll's AnswerType object without retrieving unnecessary data and use it to write my upVote mutation.
I hope someone can guide me with this

How to do a nested mutation resolver with nexus-prisma

I have the following datamodel:
type Job {
// ...
example: String
selections: [Selection!]
// ...
}
type Selection {
...
question: String
...
}
I define my object type so:
export const Job = prismaObjectType({
name: 'Job',
definition(t) {
t.prismaFields([
// ...
'example',
{
name: 'selections',
},
// ...
])
},
})
I do my resolver this way:
t.field('createJob', {
type: 'Job',
args: {
// ...
example: stringArg(),
selections: stringArg(),
// ...
},
resolve: (parent, {
example,
selections
}, ctx) => {
// The resolver where I do a ctx.prisma.createJob and connect/create with example
},
})
So now in the resolver I can receive the selections as json string and then parse it and connect/create with the job.
The mutation would look like this:
mutation {
createJob(
example: "bla"
selections: "ESCAPED JSON HERE"
){
id
}
}
I was wondering if there's anything more elegant where I could do something like:
mutation {
createJob(
example: "bla"
selections: {
question: "bla"
}
){
id
}
}
or
mutation {
createJob(
example: "bla"
selections(data: {
// ...
})
){
id
}
}
I've noticed that with nexus-prisma you can do stringArg({list: true}) but you can't really do objects.
My main question is what is the most elegant way to do either nested mutation or connect all in one.
You can use an inputObjectType as shown in the docs:
export const SomeFieldInput = inputObjectType({
name: "SomeFieldInput",
definition(t) {
t.string("name", { required: true });
t.int("priority");
},
});
Make sure to include the type as part of the types you pass to makeSchema. You can then use it to define an argument, like
args: {
input: arg({
type: "SomeFieldInput", // name should match the name you provided
}),
}
Now, the argument value will be available to your resolver as a regular JavaScript object, not a String. If you need a list of input objects, or want to make the argument required, you do so using the same options you would provide with when using a scalar -- list, nullable, description, etc.
Here's a complete example:
const Query = queryType({
definition(t) {
t.field('someField', {
type: 'String',
nullable: true,
args: {
input: arg({
type: "SomeFieldInput", // name should match the name you provided
}),
},
resolve: (parent, { input }) => {
return `You entered: ${input && input.name}`
},
})
},
})
const SomeFieldInput = inputObjectType({
name: "SomeFieldInput",
definition(t) {
t.string("name", { required: true });
},
});
const schema = makeSchema({
types: {Query, SomeFieldInput},
outputs: {
...
},
});
Then query it like:
query {
someField(
input: {
name: "Foo"
}
)
}
Or using variables:
query($input: SomeFieldInput) {
someField(input: $input)
}

Graphql multiple arguments in field

I'm using GraphQL.
I'm able to pass one argument in a field. But I would like to know how to pass multiple arguments to a field.
This is my code:
GraphlQL Object type: Price availability
const priceAvailability = new GraphQLObjectType({
name: "priceAvailability",
description: "Check price and availability of article",
fields: () => ({
articleID: {
type: GraphQLString
},
priceType:{
type:GraphQLString
},
stockAvailability: {
type: StockAvailabilityType,
resolve(parentValue, args) {
// stuff to get the price and availability
return (data = getStockAvailability.getStockAvailability(
parentValue.isbn, parentValue.omgeving
));
}
}
})
});
The root query
const RootQuery = new GraphQLObjectType({
name: "RootQuery",
fields: () => ({
price: {
type: new GraphQLList(priceAvailability),
args: [{
articleID: {
type: new GraphQLList(GraphQLString),
description:
'List with articles. Example: ["artid1","artid2"]'
},
priceType: {
type: new GraphQLList(GraphQLString) ,
description:
'PriceType. Example: "SalePrice","CurrentPrice"'
}]
},
resolve: function(_, { articleID , priceType}) {
var data = [];
// code to return data here
return data;
}
}
})
});
Schema
module.exports = new GraphQLSchema({
query: RootQuery
});
This is the query I use in GraphiQL to test:
{
query: price(articleID:"ART03903", priceType:"SalePrice" ){
stockAvailability {
QuantityAvailable24hrs
QuantityAvailable48hrs
}
}
}
I can get the articleID via parentValue.articleID, but I have issues with getting parentValue.priceType.
Also GraphiQL tells me that priceType does not exists:
Unknown argument “priceType”. On field “price” of type “RootQuery”
args for a field takes an object instead of an array. Try:
args: {
articleID: {
type: new GraphQLList(GraphQLString),
description: 'List with articles. Example: ["artid1","artid2"]'
},
priceType: {
type: new GraphQLList(GraphQLString) ,
description: 'PriceType. Example: "SalePrice","CurrentPrice"'
},
}

Dynamic GraphQLObjectType

I'm trying to create a dynamic GraphQLObjectType with graphQl, something like this:
export const Project = (data) => {
return new GraphQLObjectType({
name: 'Project',
fields: () => ({
id: {
type: GraphQLString
},
type: {
type: GraphQLString
},
author: {
type: User,
resolve: (root, args, req) => {
...
}
}
})
})
};
I call this model on my query in this way:
getProjectById: {
type: Project(structure),
args: {
id: { type: GraphQLString }
},
resolve(source, args, req) {
const projectService = new ProjectService(req);
return projectService.getProjectById(args.id)
}
}
the problem is that doing this I get this error:
Schema must contain unique named types but contains multiple types
named "Project"
where is the error? do you have some advice? many thanks
The call Project(structure) in turn calls new GraphQLObjectType({name: 'Project',...}) . If you invoke Project(structure) more than once, you try to declare multiple GraphQLObjectTypes with the same name (which makes no sense).
If you would create/declare GraphQLObjectType dynamically, you have to generate a unique name property. E.g. like this:
// assuming data.name is unique
export const Project = (data) => {
return new GraphQLObjectType({
name: `Project${data.name}`,
...
})
}

How do i create a graphql schema for a self referencing data hierarchy?

This doesnt work because the type refers to its self in the routes field definition:
var routeType = new GraphQLObjectType({
name: 'MessageRoute',
fields: {
name: {
type: GraphQLString
},
routes: {
type: new GraphQLList(routeType),
resolve: (route) => {
return route.routes;
}
}
}
});
so how do I do it?
A GraphQL type can refer to itself (or refer to another type defined later in a file) by defining fields as a function that returns an object rather than an object. The function will be called after the page has been fully parsed.
For your example:
var routeType = new GraphQLObjectType({
name: 'MessageRoute',
fields: function () {
return {
name: {
type: GraphQLString
},
routes: {
type: new GraphQLList(routeType),
resolve: (route) => {
return route.routes;
}
}
};
}
});
Or, if you're using ES6, a nice shorthand for this using arrow functions:
var routeType = new GraphQLObjectType({
name: 'MessageRoute',
fields: () => ({
name: {
type: GraphQLString
},
routes: {
type: new GraphQLList(routeType),
resolve: (route) => {
return route.routes;
}
}
})
});
I'd like to point out that you can use a function for any property inside an object using Javascript getter.
So instead of wrapping the whole fields property within a function you can use a function just for the type property like this:
var routeType = new GraphQLObjectType({
name: 'MessageRoute',
fields: {
name: {
type: GraphQLString
},
routes: {
get type() {
return new GraphQLList(routeType)
},
resolve: (route) => {
return route.routes;
}
}
}
});

Resources