-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Express 김세환 sprint7 #6
base: express-김세환
Are you sure you want to change the base?
The head ref may contain hidden characters: "express-\uAE40\uC138\uD658-sprint7"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Node.js 기본 | ||
node_modules/ | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# 환경 변수 파일 | ||
.env | ||
env.js | ||
|
||
# 빌드 디렉터리 | ||
dist/ | ||
build/ | ||
|
||
# OS 및 편집기 파일 | ||
.DS_Store | ||
Thumbs.db | ||
|
||
# IDE/Editor 관련 | ||
.vscode/ | ||
.idea/ | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
|
||
# 로그 파일 | ||
*.log | ||
|
||
# 테스트 관련 | ||
coverage/ | ||
requests.http |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
FROM node:18 | ||
|
||
WORKDIR /app | ||
|
||
COPY package*.json ./ | ||
|
||
RUN npm install | ||
|
||
COPY . . | ||
|
||
EXPOSE 3000 | ||
|
||
CMD ["npm", "start"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import * as dotenv from 'dotenv'; | ||
dotenv.config(); | ||
import express from 'express'; | ||
import { PrismaClient } from '@prisma/client'; | ||
|
||
const prisma = new PrismaClient(); | ||
|
||
const app = express(); | ||
app.use(express.json()); | ||
|
||
function asyncHandler(handler) { | ||
return async function (req, res) { | ||
try { | ||
await handler(req, res); | ||
|
||
} catch (err) { | ||
if (err.name === 'ValidationError') { | ||
res.status(400).send({ message: err.message }); | ||
} else if (err.name === 'CastError') { | ||
res.status(404).send({ message: 'article not found' }); | ||
} else { | ||
res.status(500).send({ message: err.message }); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// app.get('/articles', asyncHandler(async (req, res) => { | ||
// const articles = await prisma.article.findMany(); | ||
// res.json(articles); | ||
// })); | ||
|
||
app.get('/articles', asyncHandler(async (req, res) => { | ||
const { sort, page = 1, limit = 10, search = "" } = req.query; | ||
|
||
const skip = (page - 1) * limit; | ||
|
||
const searchQuery = { | ||
OR: [ | ||
{ title: { contains: search, mode: 'insensitive' } }, | ||
{ content: { contains: search, mode: 'insensitive' } } | ||
] | ||
}; | ||
|
||
const sortOptions = { | ||
createdAt: sort === 'recent' ? 'desc' : 'asc' | ||
}; | ||
|
||
const articles = await prisma.article.findMany({ | ||
where: searchQuery, | ||
orderBy: sortOptions, | ||
skip: skip, | ||
take: parseInt(limit), | ||
select: { | ||
id: true, | ||
title: true, | ||
content: true, | ||
createdAt: true | ||
} | ||
}); | ||
|
||
const total = await prisma.article.count({ | ||
where: searchQuery | ||
}); | ||
|
||
res.send({ | ||
total, | ||
page: parseInt(page), | ||
limit: parseInt(limit), | ||
articles, | ||
}); | ||
})); | ||
|
||
app.get('/articles/:id', asyncHandler(async (req, res) => { | ||
const { id } = req.params; | ||
const article = await prisma.article.findUnique({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. findUniqueOrThrow 를 해주시면 바로 validation 에러를 내뱉어줘서 에러 핸들링이 더 쉽습니다~ 현재는 없을때 서버에러가 날거라서요! |
||
where: { id }, | ||
}); | ||
res.json(article); | ||
})); | ||
|
||
app.post('/articles', asyncHandler(async (req, res) => { | ||
const { title, content } = req.body; | ||
const article = await prisma.article.create({ | ||
data: { | ||
title, | ||
content, | ||
}, | ||
}); | ||
res.json(article); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. create의 경우 201 상태코드를 같이 내려주는게 좋을것 같아요 |
||
})); | ||
|
||
app.patch('/articles/:id', asyncHandler(async (req, res) => { | ||
const { id } = req.params; | ||
const { title, content } = req.body; | ||
const article = await prisma.article.update({ | ||
where: { id }, | ||
data: { | ||
title, | ||
content, | ||
}, | ||
}); | ||
res.json(article); | ||
})); | ||
|
||
app.delete('/articles/:id', asyncHandler(async (req, res) => { | ||
const { id } = req.params; | ||
const article = await prisma.article.delete({ | ||
where: { id }, | ||
}); | ||
res.json(article); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delete의 경우 204 상태코드와 함께 보통 빈 응답을 내려줍니다 ㅎㅎ |
||
})); | ||
|
||
const runningPort = process.env.PORT || 3000; | ||
app.listen(runningPort, () => { | ||
console.log(`Server is running on http://localhost:${runningPort}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. runningPort로 까지는 안빼도 될것 같아요~ ${process.env.PORT || 3000} 요렇게 해주시면 될것 같습니다! |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
const data = { | ||
list: [ | ||
{ | ||
name: "테스트", | ||
description: "상품 등록 테스트", | ||
price: 16, | ||
tags: ["테스트", "테스트입니다"], | ||
images: [], | ||
ownerId: 496, | ||
favoriteCount: 0, | ||
createdAt: "2024-12-04T12:38:15.916Z", | ||
updatedAt: "2024-12-04T12:38:15.916Z", | ||
}, | ||
{ | ||
name: "살찐 고양이", | ||
description: "파는건 아니에요", | ||
price: 3333333, | ||
tags: ["고양이", "거북목", "집사"], | ||
images: [ | ||
"https://sprint-fe-project.s3.ap-northeast-2.amazonaws.com/Sprint_Mission/user/466/1733310657338/KakaoTalk_Photo_2024-12-03-15-08-50.jpeg", | ||
], | ||
ownerId: 466, | ||
favoriteCount: 1, | ||
createdAt: "2024-12-04T11:10:57.618Z", | ||
updatedAt: "2024-12-04T11:13:04.951Z", | ||
}, | ||
{ | ||
name: "네모박스", | ||
description: "네모박스팔아요", | ||
price: 0, | ||
tags: ["1", "2"], | ||
images: [ | ||
"https://sprint-fe-project.s3.ap-northeast-2.amazonaws.com/Sprint_Mission/user/493/1733242431404/Group%2033744.png", | ||
], | ||
ownerId: 493, | ||
favoriteCount: 0, | ||
createdAt: "2024-12-03T16:13:52.399Z", | ||
updatedAt: "2024-12-03T16:13:52.399Z", | ||
}, | ||
{ | ||
name: "상품 이름", | ||
description: "string", | ||
price: 0, | ||
tags: ["전자제품"], | ||
images: ["https://example.com/..."], | ||
ownerId: 19, | ||
favoriteCount: 0, | ||
createdAt: "2024-11-30T08:22:16.098Z", | ||
updatedAt: "2024-11-30T08:22:16.098Z", | ||
}, | ||
{ | ||
name: "상품 이름", | ||
description: "string", | ||
price: 0, | ||
tags: ["전자제품"], | ||
images: ["https://example.com/..."], | ||
ownerId: 19, | ||
favoriteCount: 0, | ||
createdAt: "2024-11-30T08:21:11.338Z", | ||
updatedAt: "2024-11-30T08:21:11.338Z", | ||
}, | ||
{ | ||
name: "상품 이름", | ||
description: "string", | ||
price: 0, | ||
tags: ["전자제품"], | ||
images: ["https://example.com/..."], | ||
ownerId: 479, | ||
favoriteCount: 0, | ||
createdAt: "2024-11-28T14:39:07.254Z", | ||
updatedAt: "2024-12-04T10:35:40.507Z", | ||
}, | ||
{ | ||
name: "상품 이름테스트", | ||
description: "string", | ||
price: 0, | ||
tags: ["전자제품"], | ||
images: ["https://example.com/..."], | ||
ownerId: 475, | ||
favoriteCount: 1, | ||
createdAt: "2024-11-26T06:52:13.772Z", | ||
updatedAt: "2024-12-03T06:06:18.058Z", | ||
}, | ||
{ | ||
name: "jetbrain", | ||
description: "jetbrain mono", | ||
price: 123456, | ||
tags: [], | ||
images: [], | ||
ownerId: 464, | ||
favoriteCount: 0, | ||
createdAt: "2024-11-20T12:47:01.832Z", | ||
updatedAt: "2024-11-20T12:47:01.832Z", | ||
}, | ||
{ | ||
name: "상품 이름", | ||
description: "string", | ||
price: 1000, | ||
tags: ["전자제품"], | ||
images: [], | ||
ownerId: 462, | ||
favoriteCount: 0, | ||
createdAt: "2024-11-14T11:09:01.391Z", | ||
updatedAt: "2024-11-14T11:09:01.391Z", | ||
}, | ||
{ | ||
name: "노이미지 상품", | ||
description: "노이미지 상품 테스트", | ||
price: 1000, | ||
tags: ["no", "image"], | ||
images: [ | ||
"https://sprint-fe-project.s3.ap-northeast-2.amazonaws.com/Sprint_Mission/user/462/1731555173279/Codeit_FE9.png", | ||
], | ||
ownerId: 462, | ||
favoriteCount: 1, | ||
createdAt: "2024-11-14T03:32:58.831Z", | ||
updatedAt: "2024-11-14T03:33:15.885Z", | ||
}, | ||
], | ||
totalCount: 182, | ||
}; | ||
|
||
export default data; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import mongoose from 'mongoose'; | ||
import data from './mock.js'; | ||
import Product from '../models/Product.js'; | ||
import { DATABASE_URL } from '../env.js'; | ||
|
||
mongoose.connect(DATABASE_URL); | ||
|
||
await Product.deleteMany({}); | ||
await Product.insertMany(data.list); | ||
|
||
mongoose.connection.close(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
GET http://localhost:4000/articles?sort=recent&limit=10&page=1&search=PS5 | ||
|
||
### | ||
|
||
GET http://https://backend-c2ut.onrender.com/articles?sort=oldest&limit=10&page=1&search=PS5 | ||
|
||
### | ||
|
||
GET http://localhost:4000/articles/cm4skodgm00036u331w9xxd95 | ||
### | ||
|
||
POST http://localhost:4000/articles | ||
Content-Type: application/json | ||
|
||
{ | ||
"title": "PS5 30주년 버전 팝니다13", | ||
"content": "PS5 30주년 버전 팝니다13" | ||
} | ||
|
||
### | ||
|
||
PATCH http://localhost:4000/articles/cm4sl1iwu0001a96yr1ry9yu8 | ||
Content-Type: application/json | ||
|
||
{ | ||
"title": "PS5 30주년 버전 팝니다2 -> 3", | ||
"content": "PS5 30주년 버전 팝니다2 -> 3" | ||
} | ||
|
||
### | ||
|
||
DELETE http://localhost:4000/articles/cm4sl1iwu0001a96yr1ry9yu8 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
GET http://localhost:3001/products?sort=oldest&limit=10&page=1&search=PS5 | ||
|
||
### | ||
|
||
GET http://https://backend-c2ut.onrender.com/products?sort=oldest&limit=10&page=1&search=PS5 | ||
|
||
### | ||
|
||
GET http://localhost:3000/products/6753d92d0ba17d1e827bb | ||
### | ||
|
||
POST http://localhost:3000/product | ||
Content-Type: application/json | ||
|
||
{ | ||
"name": "PS5 30주년 버전 팝니당", | ||
"description": "PS5 30주년 버전 팝니다", | ||
"price": 700000, | ||
"images": ["https://img.youtube.com/vi/NULUo-7gNAI/maxresdefault.jpg"] | ||
} | ||
|
||
### | ||
|
||
PATCH http://localhost:3000/products/6753d9080ba17d1e82ef97b9 | ||
Content-Type: application/json | ||
|
||
{ | ||
"name": "PS5 30주년 버전 팝니당", | ||
"description": "PS5 30주년 버전 팝니다", | ||
"price": 600000, | ||
"images": ["https://img.youtube.com/vi/NULUo-7gNAI/maxresdefault.jpg"], | ||
"tags": ["30주년", "PS5", "급처"] | ||
} | ||
|
||
### | ||
|
||
DELETE http://localhost:3000/products/6753d9080ba17d1e82ef97b9 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오.. 배포를 docker로 하시는건가요? 더할나위없이 좋습니다!