Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
node_modules
.DS_Store
.env
# Node.js
package-lock.json
migrations/
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnp/
.pnp.js

# Environment variables
.env
.env.*

# Build artifacts
dist/
build/
public/build/ # If you have a separate frontend build output within public

# Logs
logs/
*.log
migrations/

# IDE and OS specific files
.vscode/
.idea/
.DS_Store
Thumbs.db

# Test coverage
coverage/

# Uploads
uploads/ # If your application handles file uploads
9 changes: 6 additions & 3 deletions http/article.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxOWY5ZDYxNy1kYTA5LTRjZTUtYTk3ZS02ZDViNDk5ZmM4ZjEiLCJpYXQiOjE3NDk4Mjk3NTcsImV4cCI6MTc0OTgzMzM1N30.YV_QSmOkZaeNrg-BCjbwVpof3cy1LxoMpaRCP7hcv8g
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI4NjQ5YzdiZS00NTdhLTQ5YWEtYmI3My1kNDI4N2IzOGU2M2IiLCJpYXQiOjE3NTA4NjQwODIsImV4cCI6MTc1MDg2NzY4Mn0.Ni56jZpM4i2e_kMHS4gzJXWflDlxnirSlWp0gvLUses

### 게시글 등록
POST http://localhost:8080/articles
Expand All @@ -11,10 +11,13 @@ Cookie: accessToken={{accessToken}}
}

### 게시글 목록 조회
GET http://localhost:8080/articles?page=1&pageSize=10
GET http://localhost:8080/articles?page=1&pageSize=10&orderBy=like

###
GET http://api.panda-market.store/articles?page=1&pageSize=10

### 게시글 상세 조회
GET http://localhost:8080/articles/2
GET http://localhost:8080/articles/1
Cookie: accessToken={{accessToken}}

### 게시글 수정
Expand Down
23 changes: 4 additions & 19 deletions http/comment.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxOWY5ZDYxNy1kYTA5LTRjZTUtYTk3ZS02ZDViNDk5ZmM4ZjEiLCJpYXQiOjE3NDk4Mjk3NTcsImV4cCI6MTc0OTgzMzM1N30.YV_QSmOkZaeNrg-BCjbwVpof3cy1LxoMpaRCP7hcv8g
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJiMGEyMTM1Ni04NjkyLTQ4ZGQtYWM3My1mYWNkNWVkZTc0YTciLCJpYXQiOjE3NTAzODYzNDcsImV4cCI6MTc1MDM4OTk0N30.BaX5CBdJ-Z3FcB-3mO8yOQLms_L7UqRo5eueTm9x-NU

### 게시글 댓글 목록 조회
GET http://localhost:8080/articles/1/comments
Expand All @@ -14,7 +14,6 @@ Cookie: accessToken={{accessToken}}

### 상품 댓글 목록 조회
GET http://localhost:8080/products/1/comments
Cookie: accessToken={{accessToken}}

### 상품 댓글 등록
POST http://localhost:8080/products/1/comments
Expand All @@ -26,21 +25,7 @@ Cookie: accessToken={{accessToken}}
}

### 댓글 수정
PATCH http://localhost:8080/comments/11
Content-Type: application/json
Cookie: accessToken={{accessToken}}

{
"content": "수정된 댓글"
}

### 댓글 삭제
DELETE http://localhost:8080/comments/9
Cookie: accessToken={{accessToken}}


### 댓글 수정
PATCH http://localhost:8080/products/1/comments/1
PATCH http://localhost:8080/comments/1
Content-Type: application/json
Cookie: accessToken={{accessToken}}

Expand All @@ -49,9 +34,9 @@ Cookie: accessToken={{accessToken}}
}

### 댓글 삭제
DELETE http://localhost:8080/products/1/comments/5
DELETE http://localhost:8080/comments/28
Cookie: accessToken={{accessToken}}

### 댓글 목록 무한스크롤
GET http://localhost:8080/products/1/comments?cursor=6&limit=3
GET http://localhost:8080/products/1/comments?cursor=2&limit=3
Cookie: accessToken={{accessToken}}
4 changes: 2 additions & 2 deletions http/product.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxOWY5ZDYxNy1kYTA5LTRjZTUtYTk3ZS02ZDViNDk5ZmM4ZjEiLCJpYXQiOjE3NDk4NzcxNTMsImV4cCI6MTc0OTg4MDc1M30.c-esTK2icQuK_R68ReUOo07pnZgmDwGUW3_7QOvRaBY
@accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI4NjQ5YzdiZS00NTdhLTQ5YWEtYmI3My1kNDI4N2IzOGU2M2IiLCJpYXQiOjE3NTA0MDA3NTksImV4cCI6MTc1MDQwNDM1OX0.kIDdQWBcPXKkZrF4C0_tt4sj0U-Ieznc2lNW5LnfqeQ

### 상품 등록
POST http://localhost:8080/products
Expand All @@ -16,7 +16,7 @@ Cookie: accessToken={{accessToken}}
}

### 상품 목록 조회
GET http://localhost:8080/products?page=1&pageSize=10&orderBy=favorite
GET https://api.panda-market.store/products?page=1&pageSize=6

### 상품 상세 조회
GET http://localhost:8080/products/1
Expand Down
28 changes: 20 additions & 8 deletions http/user.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxOWY5ZDYxNy1kYTA5LTRjZTUtYTk3ZS02ZDViNDk5ZmM4ZjEiLCJpYXQiOjE3NDk4MzAxMTksImV4cCI6MTc0OTgzMzcxOX0.hVVyGhQZQXDB8FDxlD2KfMLaZfoCV3pCVg0L7lW5kag
@token=

### 회원가입
POST http://localhost:8080/auth/signUp
Expand All @@ -7,26 +7,38 @@ Content-Type: application/json
{
"email": "test@test.com",
"nickname": "test",
"password": "testtest",
"passwordConfirmation": "testtest"
"password": "test1234",
"passwordConfirmation": "test1234"
}

###
POST https://api.panda-market.store/auth/signUp
Content-Type: application/json

{
"email": "kk123@gmail.com",
"nickname": "kk",
"password": "kk123123",
"passwordConfirmation": "kk123123"
}


### 로그인
POST http://localhost:8080/auth/signIn
POST https://api.panda-market.store/auth/signIn
Content-Type: application/json

{
"email": "test@test.com",
"password": "testtest"
"password": "test1234"
}

### 로그인2
POST http://localhost:8080/auth/signIn
POST https://api.panda-market.store/auth/signIn
Content-Type: application/json

{
"email": "test1@test.com",
"password": "testtest"
"email": "kk123@gmail.com",
"password": "kk123123"
}

### 토큰 갱신
Expand Down
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { createDefaultPreset } = require("ts-jest");

const tsJestTransformCfg = createDefaultPreset().transform;

/** @type {import("jest").Config} **/
module.exports = {
testEnvironment: "node",
transform: {
...tsJestTransformCfg,
},
};
1 change: 0 additions & 1 deletion jsconfig.json

This file was deleted.

17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
"build": "tsc",
"start": "node --enable-source-maps dist/app.js",
"seed": "ts-node prisma/seed/seed.ts",
"postinstall": "prisma generate"
"ssh": "dotenv -- bash -c 'ssh -i \"$SSH_KEY_PATH\" -L 5432:$DB_HOST:5432 $EC2_USER@$EC2_HOST'",
"postinstall": "prisma generate",
"test": "jest",
"test:watch": "jest --watchAll"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@prisma/client": "^6.6.0",
"@aws-sdk/client-s3": "^3.832.0",
"@aws-sdk/s3-request-presigner": "^3.839.0",
"@prisma/client": "^6.10.1",
"bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
Expand All @@ -24,6 +29,7 @@
"express-validator": "^7.2.1",
"jsonwebtoken": "^9.0.2",
"multer": "^1.4.5-lts.2",
"multer-s3": "^3.0.1",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"passport-kakao": "^1.0.1",
Expand All @@ -35,16 +41,21 @@
"@types/cookie-parser": "^1.4.9",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.1",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "^9.0.9",
"@types/multer": "^1.4.13",
"@types/multer-s3": "^3.0.3",
"@types/node": "^22.13.10",
"@types/passport": "^1.0.17",
"@types/passport-google-oauth20": "^2.0.16",
"@types/passport-kakao": "^1.0.3",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.8",
"dotenv-cli": "^8.0.0",
"jest": "^30.0.4",
"nodemon": "^3.1.10",
"prisma": "^6.6.0",
"prisma": "^6.10.1",
"ts-jest": "^29.4.0",
"ts-node": "^10.9.2",
"ts-node-dev": "^2.0.0",
"tsx": "^4.19.3",
Expand Down
112 changes: 56 additions & 56 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,54 @@ datasource db {
url = env("DATABASE_URL")
}

model User {
id String @id @default(uuid())
email String @unique
nickname String @unique
image String?
hashedPassword String?
refreshToken String?
provider String @default("local")
providerId String? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

articles Article[]
products Product[]
comments Comment[]
likes Like[]
}

model Article {
id Int @id @default(autoincrement())
title String
content String
images String[]
likeCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
writerId String
writer User @relation(fields: [writerId], references: [id], onDelete: Cascade)
articleComments Comment[]
articleFavorites ArticleFavorite[]
id Int @id @default(autoincrement())
title String
content String
image String?
writerId String
likeCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

writer User @relation(fields: [writerId], references: [id], onDelete: Cascade)
articleComments Comment[]
likes Like[]
}

model Product {
id Int @id @default(autoincrement())
name String
description String
price Int
tags String[]
images String[]
ownerId String
favoriteCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
id Int @id @default(autoincrement())
name String
description String
price Int
tags String[]
images String[]
ownerId String
likeCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
productComments Comment[]
productFavorits ProductFavorite[]
likes Like[]
}

model Comment {
Expand All @@ -45,43 +65,23 @@ model Comment {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
writerId String
article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade)
product Product? @relation(fields: [productId], references: [id], onDelete: Cascade)
writer User @relation(fields: [writerId], references: [id], onDelete: Cascade)
}

model User {
id String @id @default(uuid())
email String @unique
nickname String @unique
image String?
hashedPassword String?
refreshToken String?
provider String @default("local")
providerId String? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
articles Article[]
products Product[]
comments Comment[]
productFavorites ProductFavorite[]
articleFavorites ArticleFavorite[]
article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade)
product Product? @relation(fields: [productId], references: [id], onDelete: Cascade)
writer User @relation(fields: [writerId], references: [id], onDelete: Cascade)
}

model ProductFavorite {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
model Like {
id Int @id @default(autoincrement())
userId String
productId Int

@@id([userId, productId])
}
productId Int?
articleId Int?
createdAt DateTime @default(now())

model ArticleFavorite {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
article Article @relation(fields: [articleId], references: [id], onDelete: Cascade)
userId String
articleId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
article Article? @relation(fields: [articleId], references: [id])
product Product? @relation(fields: [productId], references: [id], onDelete: Cascade)

@@id([userId, articleId])
@@unique([userId, productId])
@@unique([userId, articleId])
}
Loading