🤔

graphql-codegenと@prisma/clinetの間のデータマッピングで少しハマった話

2024/02/03に公開

事象

graphql-codegenで自動生成されるリゾルバー関数のなかにuser:()=>{}が作成されている。あれ。。。?
この時codegenをウォッチモードで動かしていたので、編集中に保存して処理が走ってしまっただけかと思い、user:()=>{}を削除するも、graphql-codegenが実行される度にuser:()=>{}が復活していることに気づきました。

article/resolvers/Article.ts
import type { ArticleResolvers } from './../../types.generated';
export const Article: ArticleResolvers = {
  // ここが毎回自動生成されてしまい、エラーが出てしまう
  user: () => { 
    /* Article.user resolver is required because Article.user exists but ArticleMapper.user does not */
  },
};
各種構成

graphql

schema.graphql
extend type Query {
  article(id: String!): Article
}

type Article {
  id: String!
  title: String!
  user: User!     //原因箇所
}

prisma

schema.prisma
model User {
  id             String          @id @default(cuid())
  name           String?
  @@map("users")
}

model Article {
  id          String   @id @default(cuid())
  title       String
  creatorId   String   @map("creator_id")
  user User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
  @@map("articles")
}

自動生成設定

https://zenn.dev/takumi776/articles/10476352d995f6#2.完成サンプルコード

原因

@prisma/clientで生成されたtype Articleの中には、参照先の{ user: User }までは含まれていませんでした。

schema.mappers.ts(修正前)
export type { Article as ArticleMapper } from '@prisma/client';

// Article型の中身です。参照先のUserテーブルは型定義に含まれていません。
type Article = {
  id: string;
  title: string;
  creatorId: string;
}

そのため、GraphqlのQueryのarticle(id: String!): Articleの期待する返り値と不整合が起きて、ArticleResolvers側で不整合を解消するための処理を追記するようにuser:()=>{}が自動追加されます。

解決方法

結論ですが、prisma側のデータモデルとgraphql側のデータモデルのマッピングに不備があったせいで、毎回作成されていました。以下のように設定することでデータモデルの不整合を解消し、参照先テーブルの項目もprisma経由で取得することができました。

schema.mappers.ts(修正後)
import type { Article, User } from '@prisma/client';
export type ArticleMapper = Article & { user: User };

Discussion