PR
Apollo ServerGraphQLNexusPrisma DateTimegraphql-iso-date

【Nexus・Prisma】DateTime 型を実装する

apollo-server-nexus-02 Apollo Server

この記事は 2023 年 10 月時点の記録です(2026 年 7 月 追記)

カスタムスカラーを定義して makeSchematypes に登録する、という流れは今も同じです。ただし使っているパッケージが引き継がれています。そして、そのことが本文の「動かなかった」箇所とも関係していそうです。

1. graphql-iso-date は graphql-scalars に移りました

graphql-iso-date のリポジトリには、「このリポジトリで定義されているスカラーは graphql-scalars リポジトリに移動し、そちらで保守される」と明記されています。npm 上の最新公開もかなり前で止まっています。

yarn add graphql-scalars

@types/graphql-iso-date も不要になります。graphql-scalars は型定義を同梱しています。

2.「NOT WORKING」の箇所について

本文では、次のコードをコメントアウトして「動かない」と書いています。

// ❌ NOT WORKING
// import { asNexusMethod } from "nexus";
// export const DateTime = asNexusMethod(GraphQLDateTime, "date");

asNexusMethod は Nexus が公式に用意している仕組みで、既存の GraphQL スカラーを Nexus のメソッドとして使えるようにするものです。本来はこれが正攻法です。

動かなかった原因は特定できていませんが、パッケージの組み合わせが関係している可能性があります。Nexus は内部で graphql パッケージの GraphQLScalarType を使うため、渡すスカラーが同じクラスのインスタンスである必要があります。graphql-iso-date が古く、依存している graphql のバージョンが食い違っていると、ここで噛み合わなくなります。

実際、同じ時期に書いたJson 型の記事では、最初から graphql-scalars を使っており、asNexusMethod が問題なく動いています。パッケージの違いが原因だった可能性が高いと考えています。

graphql-scalars に切り替えたうえで、次の形をお試しください。

// src/graphql/DateTime.ts
import { asNexusMethod } from 'nexus';
import { DateTimeResolver } from 'graphql-scalars';

export const DateTime = asNexusMethod(DateTimeResolver, 'dateTime');

これが通ると、objectType の中で次のように書けるようになります。

t.nonNull.dateTime('createdAt');   // ← 型補完が効く

本文の t.nonNull.field("createdAt", { type: "DateTime" }) でも動きますが、型名を文字列で書くことになるので、綴りを間違えても書いている最中には気づけません。Nexus を使う利点は型安全なので、可能ならメソッドの形にしておくほうが恩恵を受けられます。

なお、graphql-scalarsDateTimeResolver は ISO-8601 準拠で、Prisma の DateTime 型と同じ表現です。相性の面でも素直な選択になります。

3. スカラーは types への登録を忘れずに

本文でも src/graphql/index.ts から export していますが、makeSchematypes に含まれていないとスキーマに現れません。「定義したのに型が見つからない」というときは、まずここを確認してください。Json 型でも同じです。

※ 1 は 2026 年 7 月時点の公開情報に基づきます。2 は原因の推測を含み、当方の環境で再現・検証したものではありません。実装時はお使いのバージョンの公式ドキュメントとあわせてご確認ください。

Prisma チームは現在、nexus-plugin-prisma の長期的に保守できるようにプラグインを書き直しているため、DateTimeタイプはサポートされていません。

そもそも、DateTime 型は GraphQL (または Nexus) でネイティブにサポートされていないため、最初にそれを GraphQL スキーマに追加する必要があります。 GraphQL スカラーの標準 ISO 日付実装は、graphql-iso-date npm パッケージから使用できます。

まず、パッケージをプロジェクトに追加します。

スポンサーリンク

パッケージを追加する

try🐶everything backend$ yarn add graphql-iso-date
try🐶everything backend$ yarn add @types/graphql-iso-date --dev

新しい Types を指定する

以前記事の src/schema.ts を下記のように変更します。(Line 5、8)

// src/schema.ts

import { makeSchema } from "nexus";
import { join } from "path";
import * as types from "./graphql";

export const schema = makeSchema({
  types,
  outputs: {
    typegen: join(__dirname, "generated", "nexus-typegen.ts"),
    schema: join(__dirname, "generated", "schema.graphql"),
  },
});

DateTime タイプを定義する

src/graphql/DateTime.ts を作成します。

// src/graphql/DateTime.ts

import { GraphQLDateTime } from "graphql-iso-date";
export const DateTime = GraphQLDateTime;

// ❌ NOT WORKING
// import { asNexusMethod } from "nexus";
// export const DateTime = asNexusMethod(GraphQLDateTime, "date");

src/graphql/index.ts を作成します。

// src/graphql/index.ts

export { DateTime } from "./DateTime";
export { Post } from "./Post";
export { Profile } from "./Profile";
export { User } from "./User";

DateTime タイプを適用する

createdAtupdatedAt フィルドに DateTime 型を適用します。(Line 9-10、23-24)

src/graphql/Post.ts を作成します。

// src/graphql/Post.ts

import { objectType } from "nexus";

/*
  *** Prisma type ***
  model Post {
    id        Int      @id @default(autoincrement())
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt
    title     String   @db.VarChar(255)
    content   String?
    published Boolean  @default(false)
    author    User     @relation(fields: [authorId], references: [id])
    authorId  Int
  }
*/

export const Post = objectType({
  name: "Post",
  definition(t) {
    t.nonNull.int("id");
    t.nonNull.field("createdAt", { type: "DateTime" });
    t.nonNull.field("updatedAt", { type: "DateTime" });
    t.nonNull.string("title");
    t.string("content");
    t.boolean("published");
    t.field("author", {
      type: "User",
      resolve: (parent, _, ctx) => {
        return ctx.prisma.user.findUnique({ where: { id: parent.id } }).user();
      },
    });
  },
});

※ Json 型 設定記事は ⬇︎⬇︎

全体記事

参考文献

Removing nexus-plugin-prisma from your project

コメント

タイトルとURLをコピーしました