Open17

"Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API" やってみる

nbstshnbstsh
npx prisma db push

Note: prisma db push is useful for schema prototyping, where the goal is to synchronize a new schema with a development database. As your schema evolves, you will want to create and maintain a migration history, to do that you will use Prisma Migrate.

nbstshnbstsh
npx prisma db seed --preview-feature

Note: db seed is still in Preview, which means there may be bugs and it's not recommended to use it in production environments yet.

とあるが、実行したところ、

prisma:warn Prisma "db seed" was in Preview and is now Generally Available.
You can now remove the --preview-feature flag.

とでたので、--preview-feature は必要ない

nbstshnbstsh

tutorial だと package.json に

"ts-node": "ts-node --compiler-options '{\\\"module\\\":\\\"commonjs\\\"}'"

を追加しているが、npx prisma db seed --preview-feature を実行すると以下 warning が出たため、現在 (2021/12/4) は deprecated みたい。

risma:warn The "ts-node" script in the package.json is not used anymore since version 3.0 and can now be removed.
prisma:warn The "ts-node" script in the package.json is not used anymore since version 3.0 and can now be removed.
Error: To configure seeding in your project you need to add a "prisma.seed" property in your package.json with the command to execute it:

1. Open the package.json of your project
2. Add the following example to it:
---
"prisma": {
  "seed": "ts-node prisma/seed.ts"
}
---
If you are using ESM (ECMAScript modules):
---
"prisma": {
  "seed": "node --loader ts-node/esm prisma/seed.ts"
}
---
nbstshnbstsh

seeding

  1. prisma/seed.ts に seed script 用意
  2. package.json に prisma.seed を用意
"prisma": {
    "seed": "ts-node prisma/seed.ts"
}

(補足) まだ install してなかったら 以下を install

npm i -D ts-node typescript @types/node
  1. tsconfig.json に以下を追加し、ts-node 実行時は CommonJS を利用するよう設定 (https://github.com/TypeStrong/ts-node#commonjs)
 "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
  1. prissma seed を実行
npx prisma db seed
nbstshnbstsh

migrate を実行するたびに、ここで設定した seed script が実行される

nbstshnbstsh

GUI でデータ確認

以下コマンド実行後、 http://localhost:5555 にアクセス

npx prisma studio
nbstshnbstsh

tutorial 通りに進めていき、Sending queries using GraphQL playground の chapter で apollo server にアクセスしようとすると、Error: Cannot find module 'micro' というエラーが出たのでメモ。

対処法としては、追加で micro も install してあげればOK。

npm i micro

install したら、一度 dev server 止めてから、もう一度 dev server きどうすると問題なく http://localhost:3000/api/graphql にアクセスできる。

npm run dev

https://www.prisma.io/blog/fullstack-nextjs-graphql-prisma-2-fwpc6ds155#sending-queries-using-graphql-playground

nbstshnbstsh

Next の dev 環境で prisma-client を instanciate するコードが特殊だったのでメモ。

PrismaClient is attached to the global object in development to prevent
exhausting your database connection limit.
Learn more: https://pris.ly/d/help/next-js-best-practices

import { PrismaClient } from '.prisma/client';

let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  if (!global.prisma) {
    global.prisma = new PrismaClient();
  }
  prisma = global.prisma;
}

export default prisma;

https://pris.ly/d/help/next-js-best-practices

nbstshnbstsh

The flaws with our current GraphQL setup

  • Resolvers must match the same structure as the schema and vice-versa. Otherwise, you can end up with buggy and unpredictable behavior. These two components can accidentally go out of sync when the schema evolves or the resolver implementation changes.
  • The GraphQL schema is defined as strings, so no auto-completion and build-time error checks for the SDL code.

現状のワークフローのつらみ

graphql schema を作る => それに対応する resolver を実装 の作業を手動で進めていくと後々しんどくなる。つらみポイントの例として以下が挙げられている。

  • 開発規模の拡大に伴い、schema と resolver の実態が乖離してバグる恐れあり
  • 開発時の補完やら、エラーチェックやらがないので開発体験がよろしくない

解決策

この解決策として以下が存在する

  • GraphQL code-generator などの tool を駆使
  • code-first approach

この tutorial では code-first approach を実践する。

nbstshnbstsh

nexus を導入して、dev server 起動したところ以下のエラーが出た

TypeError: Class constructor GraphQLNonNull cannot be invoked without 'new'

issue に上がっていたが、graphql v16 の対応がまだできていないっぽい
https://github.com/graphql-nexus/nexus/issues/1009

尚、エラーが発生した nexus, graphql の version は以下の通り。

"graphql": "^16.0.1",
"nexus": "^1.1.0",
nbstshnbstsh

該当する issue 自体は fix されてるので、次の version ではおそらく問題は起こらないと思うhttps://github.com/graphql-nexus/nexus/pull/1017

nbstshnbstsh

Updating the resolver to return paginated data from the database

この chapter で以下のような型エラーが出た場合、nexus によって生成された index.d.ts を一度消すとうまくいく

resolve?: FieldResolver<TypeName, FieldName>;
            ~~~~~~~
    The expected type comes from property 'resolve' which is declared here on type 'NexusOutputFieldConfig<"Query", "links">'

~~~ 以下省略 ~~~

nbstshnbstsh

orderBy で指定する object でも型エラー出る

 // query after the cursor to check if we have nextPage
const secondQueryResults = await ctx.prisma.link.findMany({
  take: args.first,
  cursor: {
    id: myCursor,
  },
  orderBy: {
    index: 'asc', // <<< ここで型エラーです
  },
});