"Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API" やってみる
これやってみる
local で postgresql setup するのに参考にしたサイト
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.
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
は必要ない
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"
}
---
seeding
-
prisma/seed.ts
に seed script 用意 - package.json に
prisma.seed
を用意
"prisma": {
"seed": "ts-node prisma/seed.ts"
}
(補足) まだ install してなかったら 以下を install
npm i -D ts-node typescript @types/node
- tsconfig.json に以下を追加し、ts-node 実行時は CommonJS を利用するよう設定 (https://github.com/TypeStrong/ts-node#commonjs)
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
}
- prissma seed を実行
npx prisma db seed
migrate を実行するたびに、ここで設定した seed script が実行される
GUI でデータ確認
以下コマンド実行後、 http://localhost:5555
にアクセス
npx prisma studio
part2 に続く
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
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;
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 を実践する。
nexus を導入して、dev server 起動したところ以下のエラーが出た
TypeError: Class constructor GraphQLNonNull cannot be invoked without 'new'
issue に上がっていたが、graphql v16 の対応がまだできていないっぽい
尚、エラーが発生した nexus, graphql の version は以下の通り。
"graphql": "^16.0.1",
"nexus": "^1.1.0",
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">'
~~~ 以下省略 ~~~
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', // <<< ここで型エラーです
},
});