Prisma/PostgreSQL에 GraphQL Todolist 서버 구축
Github 및 데모
GraphQL 및 Prisma에 대한 간략한 소개
GraphQL은 2015년에 Facebook에서 개발했습니다. 클라이언트 측에서는 여러 URL 또는 ORM/데이터베이스 요청이 아닌 JSON과 같은 인터페이스(위 이미지 참조)를 통해 중첩 데이터 가져오기를 더 쉽게 만듭니다. 서버 측에서는 에이징 필드에서 행을 추가하거나 삭제하여 데이터 모델을 업데이트할 수 있습니다.
Prisma은 대체 ORM 및 SQL 쿼리 빌더입니다.
다음은 GraphQL 백엔드를 처음부터 빌드하는 방법을 보여줍니다.
전제 조건:
컴퓨터에 설치된 Node.js
PostgreSQL 데이터베이스 서버 실행 중
A. 설정 데이터베이스:
mkdir todo
mkdir todo/backend
cd todo/backend
npm init -y
npm install @prisma/cli - save-dev
npx prisma init
데이터베이스 모델:
code ./prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Post {
id Int @default(autoincrement()) @id
createdAt DateTime @default(now())
title String
content String? //question mark means opational
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
password String
posts Post[]
}
code ./prisma/.env
DATABASE_URL=postgresql://USER:PASSWORD@HOST:PORT/DATABASE
프리즈마 마이그레이션:
npx prisma migrate save --name init --experimental
npx prisma migrate up --experimental
npx prisma generate
나. 서버 구축
npm i graphql-yoga @prisma/client
code index.js
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()
const { GraphQLServer } = require('graphql-yoga')
const Query = require('./resolvers/query.js')
const Mutation = require('./resolvers/mutation.js')
const User = require('./resolvers/user.js')
const Post = require('./resolvers/post.js')
const resolvers = {
Query,
Mutation,
User,
Post
}
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: request => {
return {
...request,
prisma,
}
},
})
const PORT = process.env.PORT || 4000
server.start(PORT, () => console.log(`Server is running on http://localhost:4000`))
typeDefs
는 t 섹션에 작성된 스키마에 연결합니다. 데이터베이스 경로, 데이터 유형 및 이들 간의 관계를 정의했습니다. resolvers
는 각 관련 스크립트에서 데이터를 처리하는 방법을 정의했습니다. 예를 들어 데이터 가져오기를 담당하는 쿼리, CRUD/가입/로그인 기능에 대한 돌연변이, 나중에 다룰 것입니다. 나머지 두 개(Resolvers 필드의 User 및 Post)는 데이터 관계를 정의합니다. context
에는 해석기 체인을 통해 전달되는 사용자 지정 데이터가 포함되어 있습니다. C. typeDefs, 해석기 및 사용자 식별 빌드
code schema.graphql
type Query {
info: [Post!]!
}
type Mutation {
upsertPost (postId:ID!, title: String!, content: String): Post!
deletePost (postId:ID!): Post
signup(email: String!, password: String!, name: String!): AuthPayload
login(email: String!, password: String!): AuthPayload
}
type Post {
id: ID!
title: String!
content: String
author: User
createdAt: String!
}
type AuthPayload {
token: String
user: User
}
type User {
id: ID!
name: String
email: String!
posts: [Post]
}
npm i jsonwebtoken bcryptjs dotenv
mkdir resolvers
code ./resolvers/query.js
const { getUserId } = require('../utils')
function info(parent, args, context, info) {
const userId = getUserId(context)
const Posts = context.prisma.post.findMany({
where: {
authorId: parseInt(userId)
}
})
return Posts
}
module.exports = {
info
}
code ./resolvers/mutation.js
const { getUserId } = require('../utils')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
require('dotenv').config()
const APP_SECRET = process.env.APP_SECRET
function upsertPost(parent, args, context, info) {
const userId = getUserId(context)
const upsertPost = context.prisma.post.upsert({
where: {
id: parseInt(args.postId)
},
update: {
title: args.title,
content: args.content,
},
create: {
title: args.title,
content: args.content,
author: {
connect: { id: parseInt(userId) },
},
},
})
return upsertPost
}
function deletePost(parent, args, context, info) {
const deletePost = context.prisma.post.delete({
where: {
id: parseInt(args.postId),
},
})
return deletePost
}
async function signup(parent, args, context, info) {
const password = await bcrypt.hash(args.password, 10)
const user = await context.prisma.user.create({ data: { ...args, password } })
const token = jwt.sign({ userId: user.id }, APP_SECRET)
return {
token,
user,
}
}
async function login(parent, args, context, info) {
const user = await context.prisma.user.findOne({ where: { email: args.email } })
if (!user) {
throw new Error('No such user found')
}
const valid = await bcrypt.compare(args.password, user.password)
if (!valid) {
throw new Error('Invalid password')
}
const token = jwt.sign({ userId: user.id }, APP_SECRET)
return {
token,
user,
}
}
module.exports = {
upsertPost,
deletePost,
signup,
login,
}
code ./resolvers/user.js
function posts(parent, args, context) {
return context.prisma.user.findOne({ where: { id: parent.id } }).posts()
}
module.exports = {
posts,
}
code ./resolvers/post.js
function author(parent, args, context) {
return context.prisma.post.findOne({ where: { id: parent.id } }).author()
}
module.exports = {
author,
}
4개의 스크립트 기능은 위의 두 번째 항목(리졸버)에 대해 간략하게 설명했습니다.
code utils.js
const jwt = require('jsonwebtoken')
require('dotenv').config()
const APP_SECRET = process.env.APP_SECRET
function getUserId(context) {
const Authorization = context.request.get('Authorization')
if (Authorization) {
const token = Authorization.replace('Bearer ', '')
const { userId } = jwt.verify(token, APP_SECRET)
return userId
}
throw new Error('Not authenticated')
}
module.exports = {
getUserId,
}
code .env
APP_SECRET = Your_APP_SECRET
D. GraphQL 서버 시작
node index.js
GraphQL 왼쪽 열에서 다음 명령을 시도할 수 있습니다.
가입하기
mutation {
signup(
name: "__yourname__"
email: "[email protected]__"
password: "__yourpassword__"
) {
token
user {
id
}
}
}
로그인
mutation {
login(
email: "[email protected]__"
password: "__yourpassword__"
) {
token
user {
id
name
posts{
id
title
}
}
}
}
ㅏ. 헤더에 토큰 복사(왼쪽 하단)
{ "Authorization": "Bearer __Token__" }
비. 명령
mutation {
upsertPost(
postId:"0"
title: "www.graphqlconf.org"
) {
id
titile
}
}
할 일 삭제
mutation {
deletePost(
postId:"__Id__" //enter todo id
) {
id
}
}
Reference
이 문제에 관하여(Prisma/PostgreSQL에 GraphQL Todolist 서버 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pcreem/build-a-graphql-todolist-server-on-prisma-postgresql-2j63텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)