How to pass an array as args to Nexus? How to create multiple objects from this array using Prisma?

2.8k views Asked by At

I'm trying to learn to use Prisma and Nexus together. I'm hoping that someone more experienced can help me out.

I want to create a post with several images attached to it.

My Prisma models look like this:

model Post {
  id String @id @default(cuid())
  title String
  body String
  images Image[] @relation("ImagePost")
}

model Image {
  id String @id @default(cuid())
  post Post @relation("ImagePost", fields: [postId], references: [id])
  postId String
  name String
  url String
}

I need to write a Nexus mutation that can accept a post with a title, body, and array of image urls. I need to create an Image record for each of the urls, and attach them to the post.

const Mutation = objectType({
  name: 'Mutation',
  definition(t) {
    t.field('createPost', {
      type: 'Post',
      args: {
        title: nonNull(stringArg()),
        body: stringArg(),
        images: ????
      },
      resolve: (_, args, context: Context) => {
        return context.prisma.post.create({
          data: {
            title: args.title,
            body: args.body,
            images: ????
          },
        })
      },
    })
})

Can you help me to figure out how to do this correctly?

  1. I don't know how to pass an array of json objects to the args. There are things like stringArg() or intArg(), but how do you accept an array?
  2. What's the right way to create a bunch of Image objects and attach them to the Post? Should I have a for loop and create them manually one by one, and then attach them somehow? Or is there a better way?

Do you know if there are any examples of people doing this kind of thing?

3

There are 3 answers

0
Ryan On

Just like nonNull there's also a list type. You can use that and create an arg in that.

As for creating images, you can use create and pass the array of images to post as shown here.

0
luisbar On

I have done that using the extendInputType, here you go an example

  1. First you have to define de input
export const saleDetailInput = extendInputType({
  type: 'SaleDetailInput',
  definition(t) {
    t.field(SaleDetail.productId)
  }
});
  1. Define the args
export const createSale = extendType({
  type: 'Mutation',
  definition(t) {
    t.nonNull.list.field('createSale', {
      type: 'Sale',
      args: {
        total: nonNull(floatArg()),
        customerId: nonNull(intArg()),
        products: nonNull(list(nonNull('SaleDetailInput'))),
      },
      async resolve(parent, { products, ...others }, context) {
      },
    })
  },
})
0
Mejan On

Leaving a more detailed example from nexus. no need to create a new inputObjectType. It's just simple as the below arg example.

import { queryType, stringArg, list } from 'nexus'
queryType({
  definition(t) {
    t.field('tags', {
      type: list('String'), // -> [String]
      args: {
        ids: list(stringArg()) // or list('String') -> [String]
      },
      resolve() {
        // ...
      }
    })
  }
})