「Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API」記事の補足


Nexus や prisma を触ってみたいなと思っていたところ、ちょうどいいチュートリアル記事
Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API
があったので、やってみました。
途中でいくつか躓いた箇所があったので、そのメモです。

レポジトリ: https://github.com/y-takey/prisma_gql_example

前準備

Node

Node のバージョンは16系の最新を使用するのが無難。

DB

PostgreSQL はインストール済み、もしくはコンテナ等で使用可能な前提。

psql -d postgres

以下のように適当なユーザを作る。databaseを作る必要はないが、その場合はprismaが作ってくれるため CREATEDB を付与しておく必要がある。

CREATE USER user1 WITH PASSWORD 'pass' CREATEDB CREATEROLE;

Seeding the database

DATABASE_URL のフォーマット

.env.example をコピーし .env を作成後、DATABASE_URL のフォーマットは以下の通り。
database が存在しない場合は prisma が作成してくれる。

DATABASE_URL="postgresql://{user}:{pass}@127.0.0.1/{database}"

ts-node のインストール

prisma db seed を実行する際にts-nodeが必要となるが、元のpackage.jsonには含まれていなかったのでインストールする。
ちなみに npx prisma db seed --preview-feature と書かれているが、現在のprismaでは db seed が正式リリースされているため、 --preview-feature は不要。

yarn add -D ts-node

Building the GraphQL API

graphqlのバージョン指定

2021/11/23時点では graphql はバージョン 16 が最新だが、 nexus が未対応のためバージョン 15 を指定する

micro もインストール

インストールするものに micro が入っていないが必要だったので追加

prismaのエラー対応

M1 Mac を使っていると以下のエラーが出たので、書かれている通り prisma/schema.prismagenerator ブロックに binaryTargets を追加し yarn prisma generate を実行すると解決した。

/path/to/node_modules/@prisma/client/runtime/index.js:36467
      throw new PrismaClientInitializationError(errorText, this.config.clientVersion);
            ^

PrismaClientInitializationError: Query engine library for current platform "darwin-arm64" could not be found.
You incorrectly pinned it to darwin-arm64

This probably happens, because you built Prisma Client on a different platform.
(Prisma Client looked in "/path/to/node_modules/@prisma/client/runtime/libquery_engine-darwin-arm64.dylib.node")

Searched Locations:

  /path/to/node_modules/.prisma/client
  /path/to/node_modules/@prisma/client
  /path/to/node_modules/@prisma/client
  /path/to/node_modules/.prisma/client
  /path/to/prisma
  /tmp/prisma-engines
  /path/to/node_modules/.prisma/client


To solve this problem, add the platform "darwin-arm64" to the "binaryTargets" attribute in the "generator" block in the "schema.prisma" file:
generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native"]
}

Then run "prisma generate" for your changes to take effect.
Read more about deploying Prisma Client: https://pris.ly/d/client-generator
    at Object.getLibQueryEnginePath (/path/to/node_modules/@prisma/client/runtime/index.js:36467:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.loadEngine (/path/to/node_modules/@prisma/client/runtime/index.js:36128:33)
    at async Object.instantiateLibrary (/path/to/node_modules/@prisma/client/runtime/index.js:36094:5) {
  clientVersion: '3.4.2',
  errorCode: undefined
}

Updating the resolver to return paginated data from the database

型情報の自動生成

チュートリアルに従ってコードを書いていると途中で型エラーとなるかもしれないが、以下のような状態で保存すると型情報が自動生成されてエラーも解消される。ただし yarn dev を実行しておく必要がある。

export const LinksQuery = extendType({
  type: "Query",
  definition(t) {
    t.field("links", {
      type: Response,
      args: { first: intArg(), after: stringArg() },
      async resolve(_, args, ctx) {},
    });
  },
});

orderBy を修正

graphql/types/Link.ts でクエリの orderBy の値が間違っているので id に修正

const secondQueryResults = await ctx.prisma.link.findMany({
  take: first,
  cursor: { id: myCursor },
  orderBy: { id: "asc" },
});

おまけ

自動生成される型情報の利用

チュートリアルでは型情報を node_modules/@types/nexus-typegen/index.d.ts に出力するようにしていたが、それだと利用しにくいため generated/nexus-typegen.ts に変更。
また、以下のようにすることでエディタで補完が効くようになる。

// pages/index.tsx
import { NexusGenFieldTypes } from "../generated/nexus-typegen";

    fetchMore<NexusGenFieldTypes["Query"], { after: number }>({
      variables: { after: endCursor },
      updateQuery: (prevResult, { fetchMoreResult }) => {
        fetchMoreResult.links.edges = [
          ...prevResult.links.edges,
          ...fetchMoreResult.links.edges,
        ];
        return fetchMoreResult;
      },
    });