Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PrismaUtils prismaCreate does not respect Prisma.XxxxInput interface #1135

Open
cyrilchapon opened this issue Jan 22, 2024 · 1 comment
Open

Comments

@cyrilchapon
Copy link

Hi !

Running through the documentation, I applied the chapter "Creating input for mutations" and found a strange behavior :

export const UserSelfCreateInput: InputObjectRef<Prisma.UserCreateInput> =
  builder.prismaCreate('User', {
    name: 'UserCreateInput',
    fields: () => ({
      // Empty
    }),
  });

This perfectly TS compile, while Prisma.UserCreateInput is like this :

type Prisma.UserCreateInput = {
    id?: string | undefined;
    contactEmail: string;
    name: string;
}

The consequence is in the resolver, when using it like so :

  t.prismaField({
    type: User,
    // used here
    args: { input: t.arg({ type: UserSelfCreateInput, required: true }) },

    resolve: async (query, parent, { input: payload }, context) => {
      // `payload` resolves to `Prisma.UserCreateInput`

      const createdUser = await database.user.create({
        // So compiler is happy here
        data: payload,
      });

      return createdUser;
    },
  }),

And the generate GraphQL is like so :

input UserCreateInput

(empty input)

Which lead to runtime errors; because the GraphQL schema is not consistent to what is passed to the resolver.


I observed the exact same behavior with any kind of more complex configuration, example :

export const UserSelfCreateInput: InputObjectRef<Prisma.UserCreateInput> =
  builder.prismaCreate('User', {
    name: 'UserCreateInput',
    fields: (t) => ({
      contactEmail: t.string({
        required: true,
        validate: { schema: z.string().email() },
      }),
      name: t.string({
        // This shouldn't be accepted as it's not nullable in the model
        required: false
      }),
    }),
  });

My observation is that prismaCreate.fields is basically just not producing something type-checkable with a type like so :

const variable: InputObjectRef<Prisma.UserCreateInput>
@hayes
Copy link
Owner

hayes commented Jan 23, 2024

This used to be stricter, but some changes prisma made, made maintaining it very painful.

You could probably define your type as:

export const UserSelfCreateInput: InputObjectRef<Partial<Prisma.UserCreateInput>> =
  builder.prismaCreate('User', {
    name: 'UserCreateInput',
    fields: () => ({
      // Empty
    }),
  });

For a lot of create inputs, you want to mix user provided inputs with things provided in the resolver, it is rare that the user is providing all fields in their input. This does lead to some lack of type-saftey.

I am not against having the types be more accurate here, but getting this to work reliably with prisma's input types without compromising other parts of the developer experience is tricky and there are higher priority features I am working on right now, so I probably won't be able to improve this until after v4 releases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants