NestJS + MySQL + Prisma + GraphQLç°å¢ã®æ§ç¯
ã¿ã¤ãã«ã®çµã¿åããã§ãGraphQLã®ãã¼ã¿åå¾Queryãå®è¡å¯è½ãªã¨ããã¾ã§æ§ç¯ããã
ãªããGraphQLã®å®è£
ã¯ã³ã¼ããã¡ã¼ã¹ãã¨ã¹ãã¼ããã¡ã¼ã¹ãã®2種é¡ãããããä»åã¯ã³ã¼ããã¡ã¼ã¹ãã§å®è£
ããã
â»Prismaã¯ã©ã¤ãã©ãªã®æ´æ°é度ãæ©ããã³ãã³ããé³è åãã¦ããå¯è½æ§ããããã注æ
ã³ãã³ãå®è¡å¾ã®ã¨ã©ã¼çã«ææ°verã§ã®å®è¡æ¹æ³ã®è£è¶³ã表示ããããããã¨ã©ã¼ãåºãå ´åã¯ãã¡ããåèã«ãã
ç°å¢
- NestJS 7ç³»
Init Nest
ããã±ã¼ã¸è¿½å ã¨ããã¸ã§ã¯ãã®åæåãè¡ãã
npm i -g @nestjs/cli
nest new app-name
Init MySQL
MySQLãèµ·åããdocker-compose.yml
ãç¨æããã
â»éçºç¨éã§èå¼±ãªè¨å®ã§ãããã注æã
version: '3.8' services: db: image: mysql:8 container_name: db environment: MYSQL_ROOT_PASSWORD: password ports: - '3306:3306' command: --default-authentication-plugin=mysql_native_password volumes: - ./mysql:/var/lib/mysql
MySQLãèµ·åããã
docker-compose up
Init Prisma
Prismaãè¨å®ããã
yarn add --dev prisma
npx prisma init
çæãããschema.prisma
ã®provider
ãMySQLã«å¤æ´ã
- provider = "postgresql" + provider = "mysql"
ã¾ãããã¼ã¿ãã¼ã¹ã®åæåç¨ã«IDã ãã®ã¦ã¼ã¶ã¼ã¢ãã«ã追è¨ããã
model User { id String @id @default(uuid()) }
.env
ã«æ¥ç¶æ
å ±ãå®ç¾©
# Database DATABASE_URL="mysql://root:password@localhost/db"
ãã¤ã°ã¬ã¼ã·ã§ã³ãå®è¡ããã
npx prisma migrate dev
nestjsã§Prismaã®Serviceãç¨æããã
nest g module prisma nest g service prisma
ä½æããprisma.service.ts
ãä¸è¨ã®ããã«ä¿®æ£ã
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } }
prisma.module.ts
ã§PrismaService
ãã¨ã¯ã¹ãã¼ãããã
import { Module } from '@nestjs/common'; import { PrismaService } from './prisma.service'; @Module({ providers: [PrismaService], exports: [PrismaService], }) export class PrismaModule {}
GraphQLè¨å®
å¿ è¦ãªã©ã¤ãã©ãªãã¤ã³ã¹ãã¼ã«ããã
yarn add @nestjs/graphql graphql-tools graphql apollo-server-express
app.module.ts
ã«GraphQLModuleã®ã¤ã³ãã¼ãè¨å®ã追è¨ã
import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { Request, Response } from 'express'; import { join } from 'path'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { PrismaModule } from './prisma/prisma.module'; @Module({ imports: [ GraphQLModule.forRoot({ autoSchemaFile: join(process.cwd(), 'src/schema.gql'), // Resolverã§expressã®req/resãå©ç¨ããå ´åè¨å®ãã // context: ({ req, res }): { req: Request; res: Response } => ({ // req, // res, // }), // corsã®è¨å®ãå¿ è¦ãªå ´å // cors: { // origin: process.env.ORIGINS?.split(','), // credentials: true, // }, debug: process.env.NODE_ENV === 'production' ? false : true, playground: process.env.NODE_ENV === 'production' ? false : true, }), PrismaModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
ã³ã¼ããã¡ã¼ã¹ãã®å®ç¾©ãç°¡ç¥åãããããnest-cli.json
ã«ä¸è¨è¨å®ã追è¨ã
{ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { "plugins": [ { "name": "@nestjs/graphql/plugin", "options": { "typeFileNameSuffix": [ ".input.ts", ".args.ts", ".entity.ts", ".model.ts" ] } } ] } }
GraphQLå®è£
User
ã¢ãã«ã®ãã¼ã¿ãåå¾ã§ãããªã¾ã«ããä½æããã
nest g mo Users nest g resolver Users nest g service Users
users.module.ts
ã®imports
ã«PrismaModule
ã追è¨ã
+ imports: [PrismaModule]
entityãå®ç¾©ããã
touch src/users/user.entity.ts
import { ObjectType } from '@nestjs/graphql'; @ObjectType() export class User { id!: string; }
users.service.ts
ã«Prismaã使ç¨ãã¦ã¦ã¼ã¶ã¼ãå
¨ä»¶åå¾ããã¡ã½ãããå®ç¾©ããã
import { Injectable } from '@nestjs/common'; import { PrismaService } from 'src/prisma/prisma.service'; @Injectable() export class UsersService { constructor(private readonly prisma: PrismaService) {} findAll() { return this.prisma.user.findMany(); } }
users.resolver.ts
ã«ã¦ã¼ã¶ã¼ãå
¨ä»¶åå¾ãããªã¾ã«ããå®ç¾©ããã
import { Query, Resolver } from '@nestjs/graphql'; import { User } from './user.entity'; import { UsersService } from './users.service'; @Resolver() export class UsersResolver { constructor(private readonly usersService: UsersService) {} @Query(() => [User], { name: 'users' }) findAll(): Promise<User[]> { return this.usersService.findAll(); } }
app.module.ts
ã«UsersModule
ã®importã追å ããã
... imports: [ ... UsersModule, ], ...
Prisma Studioãç¨ãã¦ãWebã¤ã³ã¿ã¼ãã§ã¼ã¹ããé©å½ã«Userã追å ããã
npx prisma studio
# ããã©ã«ãã§http://localhost:5555ã§Prisma Studioãèµ·åããã®ã§ãã¦ã¼ã¶ã¼ãã¼ãã«é¸æå¾ãAdd recordãããã¼ã¿ã追å ãã
æ¥ç¶ç¢ºèª
å®éã«ã¢ããªã±ã¼ã·ã§ã³ãèµ·åããGraphQL Playgroundããã¦ã¼ã¶ã¼ãã¼ã¿ãåå¾ããã
yarn start:dev
ã¢ããªã±ã¼ã·ã§ã³ãèµ·åãããhttp://localhost:3000/graphql
ã«ã¢ã¯ã»ã¹ããä¸è¨ã¯ã¨ãªãå®è¡ããã
query { users { id } }
ãã¼ã¿ãæ£å¸¸ã«åå¾ã§ããã°ã»ããã¢ããå®äºã
{ "data": { "users": [ { "id": "4d3147b8-0b2d-4c6b-a54d-b9bbb2d627b5" }, { "id": "590ee871-e7ba-42d0-be0c-ce55377112cf" }, { "id": "9177215b-b055-4140-84bf-e89233d1ef49" } ] } }