Skip to content

Commit 7492d0a

Browse files
authored
Merge pull request #5 from chan000518/feat_chan
프로토 타입 완성
2 parents f82938f + c8d2f55 commit 7492d0a

File tree

30 files changed

+2104
-58
lines changed

30 files changed

+2104
-58
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ on:
44
push:
55
branches:
66
- main
7-
pull_request:
8-
branches:
9-
- main
107

118
jobs:
129
build-and-push:
@@ -25,7 +22,10 @@ jobs:
2522
- name: Build and Push Docker image
2623
run: |
2724
IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/docker-test-app
28-
docker build -t $IMAGE_NAME:latest .
25+
docker build \
26+
--build-arg DATABASE_URL=${{ secrets.DATABASE_URL }} \
27+
--build-arg JWT_SECRET=${{ secrets.JWT_SECRET }} \
28+
-t $IMAGE_NAME:latest .
2929
docker push $IMAGE_NAME:latest
3030
3131
deploy:

Dockerfile

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
# 베이스 이미지 설정
2-
FROM node:16
1+
# Node.js 18.18.0 이미지를 사용
2+
FROM node:18.18.0
3+
4+
# 빌드 타임 환경 변수 설정
5+
ARG DATABASE_URL
6+
ARG JWT_SECRET
7+
8+
# 런타임 환경 변수 설정
9+
ENV DATABASE_URL=$DATABASE_URL
10+
ENV JWT_SECRET=$JWT_SECRET
311

412
# 작업 디렉토리 설정
513
WORKDIR /usr/src/app
@@ -8,11 +16,21 @@ WORKDIR /usr/src/app
816
COPY package*.json ./
917
RUN npm install
1018

11-
# 소스 코드 복사
19+
# Prisma CLI 설치 (글로벌 또는 프로젝트 내 설치에 따라 조정)
20+
RUN npx prisma --version
21+
22+
# Prisma schema 파일 복사 (Prisma CLI 실행 전에 필요)
23+
COPY prisma ./prisma
24+
25+
# Prisma 명령어 실행 (예: generate와 migrate)
26+
RUN npx prisma generate
27+
RUN npx prisma migrate deploy
28+
29+
# 애플리케이션 소스 코드 복사
1230
COPY . .
1331

14-
# 포트 설정
32+
# 포트 노출
1533
EXPOSE 3000
1634

17-
# 앱 실행 명령어
35+
# 애플리케이션 시작
1836
CMD ["npm", "start"]

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
"license": "ISC",
88
"description": "",
99
"dependencies": {
10+
"@prisma/client": "^6.1.0",
11+
"bcrypt": "^5.1.1",
1012
"cors": "^2.8.5",
11-
"dotenv": "^16.4.5",
13+
"dotenv": "^16.4.7",
1214
"express": "^4.21.1",
15+
"jsonwebtoken": "^9.0.2",
1316
"morgan": "^1.10.0",
17+
"prisma": "^6.1.0",
18+
"superstruct": "^2.0.2",
1419
"swagger-jsdoc": "^6.2.8",
1520
"swagger-ui-express": "^5.0.1"
1621
},
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
-- CreateEnum
2+
CREATE TYPE "Role" AS ENUM ('TRAINER', 'MEMBER');
3+
4+
-- CreateEnum
5+
CREATE TYPE "Status" AS ENUM ('SCHEDULED', 'COMPLETED', 'CANCELED');
6+
7+
-- CreateTable
8+
CREATE TABLE "User" (
9+
"id" SERIAL NOT NULL,
10+
"email" TEXT NOT NULL,
11+
"password" TEXT NOT NULL,
12+
"name" TEXT NOT NULL,
13+
"role" "Role" NOT NULL DEFAULT 'MEMBER',
14+
"profileImage" TEXT,
15+
"phoneNumber" TEXT,
16+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
17+
18+
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
19+
);
20+
21+
-- CreateTable
22+
CREATE TABLE "Member" (
23+
"id" SERIAL NOT NULL,
24+
"userId" INTEGER NOT NULL,
25+
26+
CONSTRAINT "Member_pkey" PRIMARY KEY ("id")
27+
);
28+
29+
-- CreateTable
30+
CREATE TABLE "Trainer" (
31+
"id" SERIAL NOT NULL,
32+
"userId" INTEGER NOT NULL,
33+
34+
CONSTRAINT "Trainer_pkey" PRIMARY KEY ("id")
35+
);
36+
37+
-- CreateTable
38+
CREATE TABLE "Schedule" (
39+
"id" SERIAL NOT NULL,
40+
"date" TIMESTAMP(3) NOT NULL,
41+
"location" TEXT,
42+
"status" "Status" NOT NULL DEFAULT 'SCHEDULED',
43+
"memberId" INTEGER NOT NULL,
44+
"trainerId" INTEGER NOT NULL,
45+
46+
CONSTRAINT "Schedule_pkey" PRIMARY KEY ("id")
47+
);
48+
49+
-- CreateTable
50+
CREATE TABLE "_MemberToTrainer" (
51+
"A" INTEGER NOT NULL,
52+
"B" INTEGER NOT NULL,
53+
54+
CONSTRAINT "_MemberToTrainer_AB_pkey" PRIMARY KEY ("A","B")
55+
);
56+
57+
-- CreateIndex
58+
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
59+
60+
-- CreateIndex
61+
CREATE UNIQUE INDEX "Member_userId_key" ON "Member"("userId");
62+
63+
-- CreateIndex
64+
CREATE UNIQUE INDEX "Trainer_userId_key" ON "Trainer"("userId");
65+
66+
-- CreateIndex
67+
CREATE INDEX "_MemberToTrainer_B_index" ON "_MemberToTrainer"("B");
68+
69+
-- AddForeignKey
70+
ALTER TABLE "Member" ADD CONSTRAINT "Member_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
71+
72+
-- AddForeignKey
73+
ALTER TABLE "Trainer" ADD CONSTRAINT "Trainer_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
74+
75+
-- AddForeignKey
76+
ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_memberId_fkey" FOREIGN KEY ("memberId") REFERENCES "Member"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
77+
78+
-- AddForeignKey
79+
ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_trainerId_fkey" FOREIGN KEY ("trainerId") REFERENCES "Trainer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
80+
81+
-- AddForeignKey
82+
ALTER TABLE "_MemberToTrainer" ADD CONSTRAINT "_MemberToTrainer_A_fkey" FOREIGN KEY ("A") REFERENCES "Member"("id") ON DELETE CASCADE ON UPDATE CASCADE;
83+
84+
-- AddForeignKey
85+
ALTER TABLE "_MemberToTrainer" ADD CONSTRAINT "_MemberToTrainer_B_fkey" FOREIGN KEY ("B") REFERENCES "Trainer"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[username]` on the table `User` will be added. If there are existing duplicate values, this will fail.
5+
- Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty.
6+
7+
*/
8+
-- AlterTable
9+
ALTER TABLE "User" ADD COLUMN "username" TEXT NOT NULL;
10+
11+
-- CreateIndex
12+
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- AlterEnum
2+
-- This migration adds more than one value to an enum.
3+
-- With PostgreSQL versions 11 and earlier, this is not possible
4+
-- in a single migration. This can be worked around by creating
5+
-- multiple migrations, each migration adding only one value to
6+
-- the enum.
7+
8+
9+
ALTER TYPE "Status" ADD VALUE 'MEMBER_PROPOSED';
10+
ALTER TYPE "Status" ADD VALUE 'TRAINER_PROPOSED';
11+
ALTER TYPE "Status" ADD VALUE 'REJECTED';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Warnings:
3+
4+
- You are about to drop the `_MemberToTrainer` table. If the table is not empty, all the data it contains will be lost.
5+
6+
*/
7+
-- DropForeignKey
8+
ALTER TABLE "_MemberToTrainer" DROP CONSTRAINT "_MemberToTrainer_A_fkey";
9+
10+
-- DropForeignKey
11+
ALTER TABLE "_MemberToTrainer" DROP CONSTRAINT "_MemberToTrainer_B_fkey";
12+
13+
-- DropTable
14+
DROP TABLE "_MemberToTrainer";
15+
16+
-- CreateTable
17+
CREATE TABLE "TrainerMember" (
18+
"id" SERIAL NOT NULL,
19+
"memberId" INTEGER NOT NULL,
20+
"trainerId" INTEGER NOT NULL,
21+
"ptStartDate" TIMESTAMP(3) NOT NULL,
22+
23+
CONSTRAINT "TrainerMember_pkey" PRIMARY KEY ("id")
24+
);
25+
26+
-- CreateIndex
27+
CREATE UNIQUE INDEX "TrainerMember_memberId_trainerId_key" ON "TrainerMember"("memberId", "trainerId");
28+
29+
-- AddForeignKey
30+
ALTER TABLE "TrainerMember" ADD CONSTRAINT "TrainerMember_memberId_fkey" FOREIGN KEY ("memberId") REFERENCES "Member"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
31+
32+
-- AddForeignKey
33+
ALTER TABLE "TrainerMember" ADD CONSTRAINT "TrainerMember_trainerId_fkey" FOREIGN KEY ("trainerId") REFERENCES "Trainer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Please do not edit this file manually
2+
# It should be added in your version-control system (e.g., Git)
3+
provider = "postgresql"

prisma/schema.prisma

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// This is your Prisma schema file,
2+
// learn more about it in the docs: https://pris.ly/d/prisma-schema
3+
4+
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
5+
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
6+
7+
generator client {
8+
provider = "prisma-client-js"
9+
}
10+
11+
datasource db {
12+
provider = "postgresql"
13+
url = env("DATABASE_URL")
14+
}
15+
16+
model User {
17+
id Int @id @default(autoincrement())
18+
email String @unique
19+
username String @unique // 사용자 고유 아이디
20+
password String
21+
name String
22+
role Role @default(MEMBER) // 역할 구분
23+
profileImage String? // 프로필 이미지 (선택적)
24+
phoneNumber String? // 연락처 (선택적)
25+
createdAt DateTime @default(now())
26+
27+
// 관계
28+
member Member?
29+
trainer Trainer?
30+
}
31+
32+
model Member {
33+
id Int @id @default(autoincrement())
34+
userId Int @unique
35+
user User @relation(fields: [userId], references: [id])
36+
trainers TrainerMember[] // 연결된 트레이너 목록
37+
schedules Schedule[] // 관련된 스케줄 목록
38+
}
39+
40+
model Trainer {
41+
id Int @id @default(autoincrement())
42+
userId Int @unique
43+
user User @relation(fields: [userId], references: [id])
44+
members TrainerMember[] // 관리하는 회원 목록
45+
schedules Schedule[] // PT 스케줄
46+
}
47+
48+
model TrainerMember {
49+
id Int @id @default(autoincrement())
50+
memberId Int
51+
trainerId Int
52+
member Member @relation(fields: [memberId], references: [id])
53+
trainer Trainer @relation(fields: [trainerId], references: [id])
54+
55+
// 추가 정보
56+
ptStartDate DateTime // PT 시작일
57+
58+
// 고유 제약조건
59+
@@unique([memberId, trainerId]) // 한 회원-트레이너 조합은 중복될 수 없음
60+
}
61+
62+
model Schedule {
63+
id Int @id @default(autoincrement())
64+
date DateTime // PT 날짜 및 시간
65+
location String? // PT 장소 (선택적)
66+
status Status @default(SCHEDULED) // 일정 상태
67+
trainingTarget String
68+
comment String?
69+
exerciseDetails ExerciseDetail[]
70+
memberId Int
71+
trainerId Int
72+
member Member @relation(fields: [memberId], references: [id])
73+
trainer Trainer @relation(fields: [trainerId], references: [id])
74+
}
75+
76+
model ExerciseDetail {
77+
id Int @id @default(autoincrement())
78+
scheduleId Int // FitnessGoal과 연결
79+
schedule Schedule @relation(fields: [scheduleId], references: [id])
80+
exerciseName String // 운동 이름 (예: 스쿼트, 데드리프트)
81+
reps Int // 반복 횟수
82+
sets Int // 세트 수
83+
weight Float? // 무게 (선택적, 예: kg)
84+
duration Int? // 운동 시간 (선택적, 예: 분)
85+
}
86+
87+
enum Role {
88+
TRAINER
89+
MEMBER
90+
}
91+
92+
enum Status {
93+
MEMBER_PROPOSED // 멤버가 제안한 상태
94+
TRAINER_PROPOSED // 트레이너가 제안한 상태
95+
REJECTED // 거절 상태
96+
SCHEDULED // PT가 확정된 상태
97+
COMPLETED // 완료된 상태
98+
CANCELED // 취소된 상태
99+
}

src/config/swagger.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ const options = {
55
definition: {
66
openapi: '3.0.0',
77
info: {
8-
title: 'Project Setup Template API',
8+
title: 'Project PTLink API',
99
version: '1.0.0',
10-
description: 'API documentation for Project Setup Template',
10+
description: 'API documentation for PTLink',
1111
},
1212
servers: [
1313
{

0 commit comments

Comments
 (0)