Chapter 06

Todo APIのGraphQLスキーマを定義する

Eringi_V3
Eringi_V3
2021.09.16に更新

GraphQLのスキーマがApolloのチュートリアルの状態のままなので、Todoアプリのスキーマを定義します。

shema.graphql
type Query {
  getUser: User
  getTodos: [Todo]!
  getTodoById(id: Int!): Todo
}

type Mutation {
  addTodo(input: AddTodoInput): Todo
  updateTodo(id: Int, input: UpdateTodoInput): Todo
  deleteTodo(id: Int): Todo
  createUser(id: String, input: UserInput): User
  updateUser(id: String, input: UserInput): User
}

input AddTodoInput {
  title: String!
  description: String
}

input UpdateTodoInput {
  title: String
  description: String
  status: TodoStatus
}

input UserInput {
  name: String!
}

enum TodoStatus {
  done
  pending
}

type Todo {
  id: Int
  createdAt: Date
  updatedAt: Date
  title: String
  description: String
  status: TodoStatus!
  user: User
  userId: String
}

type User {
  id: String
  name: String
  todos: [Todo]
}

scalar Date

GraphQLのデフォルトでは使用できないDate型はカスタムスカラー型として定義します。

src/resolvers/scalar/date.ts
import { GraphQLScalarType, Kind } from 'graphql';

export const dateScalar = new GraphQLScalarType({
  name: 'Date',
  description: 'Date custom scalar type',
  serialize(value) {
    return value.getTime();
  },
  parseValue(value) {
    return new Date(value);
  },
  parseLiteral(ast) {
    if (ast.kind === Kind.INT) {
      return new Date(parseInt(ast.value, 10));
    }
    return null;
  },
});

また、このままではTodoStatusについて、GraphQL codegenで生成される型がenumで、Prisma Clientが生成する型がunionとなってしまい、型エラーが起きてしまいます。
これを回避するには、codegenのenumsAsTypesオプションを有効にします。
これを有効にするとGraphQLのスキーマではenumで定義されていても、吐き出されるTypeScriptの型はstringのUnionとなります。

overwrite: true
generates:
  ./src/types/generated/graphql.ts:
    schema: schema.graphql
    config:
      useIndexSignature: true
      contextType: ../context#Context
      enumsAsTypes: true
    plugins:
      - typescript
      - typescript-resolvers

スキーマに変更を加えたのでcodegenしておきましょう。

yarn codegen