maoosi / prisma-appsync

⚡ Turns your ◭ Prisma Schema into a fully-featured GraphQL API, tailored for AWS AppSync.
https://prisma-appsync.vercel.app
BSD 2-Clause "Simplified" License
226 stars 18 forks source link

Issue: Nested one-to-many creates don't infer the connected model #101

Closed Tenrys closed 10 months ago

Tenrys commented 1 year ago

With this schema:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "rhel-openssl-1.0.x"]
  // previewFeatures = ["clientExtensions"]
}

generator appsync {
  provider = "prisma-appsync"
}

model User {
  uuid      String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name String

  post Post[]
}

model Post {
  uuid      String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  content String

  userUuid String @unique
  user     User   @relation(fields: [userUuid], references: [uuid])
}

And this query:

mutation MyMutation {
  createUser(data: {name: "test user", post: {create: {content: "test post"}}}) {
    name
    post {
      content
    }
  }
}

Because user is required on a Post, when you try to create one at the same time as updating or creating a User, it uses the model's normal <Model>CreateInput which requires to a user relationship again, giving this error:

{
  "errors": [
    {
      "message": "Field \"PostCreateInput.user\" of required type \"PostUserCreateRelationInput!\" was not provided.",
      "locations": [
        {
          "line": 2,
          "column": 55
        }
      ]
    }
  ]
}

Prisma has a lot of different types for nested relation mutations, like PostCreateWithoutUserInput. Maybe we should try to see how to best replicate them as input types and use them everywhere relevant to try and maximize similar behavior?

The workaround for this currently, if you're updating a model, is to create the model and connect it manually.

Tenrys commented 1 year ago

I should note that this isn't just a feature request, because if you actually add the user in the query, you will get a different error from Prisma itself rather than GraphQL, because it does not expect it since it already infers who the created model will be for.

StephanDecker commented 1 year ago

Thanks for solving this issue when creating a user + nested post, see https://github.com/maoosi/prisma-appsync/tree/feat/create-without But it still does not work for the updateUser + create nested post mutation. Could you consider this as well? Would be awesome!

mutation MyMutation {
  updateUser(where: {id: "1234"}, data: {name: "test user", post: {create: {content: "test post"}}}) {
    name
    post {
      content
    }
  }
}
StephanDecker commented 1 year ago

Another issue is that duplicate graphql ...CreateWithout...Input fields are generated when referring to the same entity > 1

model User {
  uuid      String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name String

  post Post[]
  anotherPost Post[]
}

This field will be generated twice:

input PostCreateWithoutUserInput {
....
}
maoosi commented 1 year ago

@StephanDecker I started working on a fix here, but it is not ready to use just yet.

Good catch on the duplicate! Happy for you to open a PR if you want to work on this, otherwise I'll continue working on the fix after the next release.

Tenrys commented 11 months ago

Are there any news on this? I see there is a feat/without branch, is it related? Any way to use it yet?

maoosi commented 11 months ago

@Tenrys yes, it's related and almost ready for release. The packages/generator has been completely rewritten using a new approach, which will resolve multiple issues simultaneously, including this one.

It will be included in the first stable release (transitioning out of RC). You can test it now by installing prisma-appsync@1.0.0-preview.8.9.

maoosi commented 10 months ago

Released in v1.0.0.