diff --git a/.docker-compose.dev.yml b/.docker-compose.dev.yml deleted file mode 100644 index 0ff31ec..0000000 --- a/.docker-compose.dev.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: '3.9' - -services: - - db: - image: postgres - restart: always - shm_size: 128mb - env_file: - - .env - ports: - - 5432:${DB_PORT} - volumes: - - budgeteer-db:/var/lib/postgresql/data - adminer: - image: adminer - restart: always - ports: - - 8080:${ADMINER_PORT} - -volumes: - budgeteer-db: \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..38ec7e6 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +POSTGRES_PASSWORD=example +POSTGRES_USER=postgres +POSTGRES_DB=postgres +DB_PORT=5432 +ADMINER_PORT=8080 +JWT_SECRET=secret \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push index 62b8bf4..e360988 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1 +1 @@ -bun run test --run +bun run test diff --git a/Dockerfile.client b/Dockerfile.client new file mode 100644 index 0000000..303322d --- /dev/null +++ b/Dockerfile.client @@ -0,0 +1,17 @@ +FROM oven/bun:alpine AS base + +FROM base AS builder +WORKDIR /app +RUN apk add --no-cache git +COPY . . + +RUN bun install +RUN bun run client:build + +FROM builder AS runner +WORKDIR /app +ENV NODE_ENV=production + +USER bun +EXPOSE 5173 +CMD ["bun", "run", "client:start"] \ No newline at end of file diff --git a/Dockerfile.server b/Dockerfile.server new file mode 100644 index 0000000..540bd72 --- /dev/null +++ b/Dockerfile.server @@ -0,0 +1,16 @@ +FROM oven/bun:alpine AS base + +FROM base AS builder +WORKDIR /app +RUN apk add --no-cache git +COPY . . + +RUN bun install + +FROM builder AS runner +WORKDIR /app +ENV NODE_ENV=production + +USER bun +EXPOSE 3000 +CMD ["bun", "run", "server:start"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ba8059 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Budgeteer + +## Prerequisites + +To get started with Budgeteer, ensure that you have the following tools installed and properly configured on your system: + +1. **Docker**: A platform to develop, ship, and run applications using containers. + - Installation guide: [Get Docker](https://docs.docker.com/get-docker/) +2. **Docker Compose**: A tool for defining and running multi-container Docker applications. + - Installation guide: [Install Docker Compose](https://docs.docker.com/compose/install/) + +## Usage + +Run the following command to initialize the required services using Docker Compose: + +```bash +# Executes the Docker Compose configuration for development +npm run all:up +``` + +## Setting Up Environment Variables + +> [!TIP] +> By default, the environment variables are set to placeholder fallbacks to ensure the app works without any configuration. + +If you want to setup your own environment variables in the Docker Compose files, make a copy of the `.env.example` first. + +```bash +# creates a .env to read from when executing the Docker Compose file +cp .env.example .env + +# start editing it +nano .env +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b56eca0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,54 @@ +services: + client: + depends_on: + - server + build: + context: . + dockerfile: Dockerfile.client + restart: always + ports: + - ${CLIENT_PORT:-5173}:${CLIENT_PORT:-5173} + environment: + - NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL:-http://server:${SERVER_PORT:-3000}/api} + + server: + depends_on: + - db + build: + context: . + dockerfile: Dockerfile.server + restart: always + ports: + - ${SERVER_PORT:-3000}:${SERVER_PORT:-3000} + environment: + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-example} + - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_DB=${POSTGRES_DB:-postgres} + - POSTGRES_HOST=${POSTGRES_HOST:-db} + - JWT_SECRET=${JWT_SECRET:-secret} + + db: + image: postgres + restart: always + ports: + - ${DB_PORT:-5432}:${DB_PORT:-5432} + shm_size: 128mb + environment: + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-example} + - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_DB=${POSTGRES_DB:-postgres} + volumes: + - budgeteer-db:/var/lib/postgresql/data + # run this script on first DB initialization + - ./packages/server/src/infrastructure/drizzle-data-service/migrations/0000_furry_sheva_callister.sql:/docker-entrypoint-initdb.d/init.sql + + adminer: + depends_on: + - db + image: adminer + restart: always + ports: + - ${ADMINER_PORT:-8080}:${ADMINER_PORT:-8080} + +volumes: + budgeteer-db: diff --git a/package.json b/package.json index a2f69a5..ac692ec 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "private": true, "scripts": { "prepare": "husky", - "test": "vitest", + "test": "docker-compose -f docker-compose.yml up -d db server && vitest --run && docker-compose -f docker-compose.yml down db server", "server:test": "bun run --cwd=\"packages/server\" test", "server:lint": "bun run --cwd=\"packages/server\" lint", "server:format": "bun run --cwd=\"packages/server\" format", @@ -36,16 +36,19 @@ "types:format": "bun run --cwd=\"packages/types\" format", "workspace:lint": "bun run server:lint && bun run client:lint && bun run types:lint", "workspace:format": "bun run server:format && bun run client:format && bun run types:format", - "db:up": "docker-compose -f .docker-compose.dev.yml up -d", - "db:down": "docker-compose -f .docker-compose.dev.yml down", + "db:up": "docker-compose -f docker-compose.yml up -d db adminer", + "db:down": "docker-compose -f docker-compose.yml down db adminer", "db:migration-generate": "bun run --cwd=\"packages/server\" drizzle:generate", "db:migration-migrate": "bun run --cwd=\"packages/server\" drizzle:migrate", "db:migration-push": "bun run --cwd=\"packages/server\" drizzle:push", "db:seed": "bun run --cwd=\"packages/server\" drizzle:seed", "client:dev": "bun run --cwd=\"packages/client\" dev", + "client:build": "bun run --cwd=\"packages/client\" build", "client:start": "bun run --cwd=\"packages/client\" start", "server:dev": "bun run --cwd=\"packages/server\" dev", - "server:start": "bun run --cwd=\"packages/server\" start" + "server:start": "bun run --cwd=\"packages/server\" start", + "all:up": "docker-compose -f docker-compose.yml up", + "all:down": "docker-compose -f docker-compose.yml down" }, "workspaces": [ "packages/*" diff --git a/packages/client/package.json b/packages/client/package.json index d050bd3..5534366 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -33,7 +33,7 @@ "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^3.1.0", - "zod": "^3.23.7" + "zod": "3.23.7" }, "devDependencies": { "@types/node": "^20", diff --git a/packages/client/src/features/dashboard/transaction.tsx b/packages/client/src/features/dashboard/transaction.tsx index cfc9745..af6108c 100644 --- a/packages/client/src/features/dashboard/transaction.tsx +++ b/packages/client/src/features/dashboard/transaction.tsx @@ -3,7 +3,7 @@ import { TransactionTypeEnum } from "@budgeteer/types" import { convertToTitleCase } from "~/lib/convertToTitleCase" interface TransactionProps { - type: TransactionTypeEnum + type: string description: string } diff --git a/packages/client/src/hooks/use-toast.ts b/packages/client/src/hooks/use-toast.ts index 83b19af..3b40a47 100644 --- a/packages/client/src/hooks/use-toast.ts +++ b/packages/client/src/hooks/use-toast.ts @@ -15,6 +15,7 @@ type ToasterToast = ToastProps & { action?: ToastActionElement } +// eslint-disable-next-line const actionTypes = { ADD_TOAST: "ADD_TOAST", UPDATE_TOAST: "UPDATE_TOAST", diff --git a/packages/server/package.json b/packages/server/package.json index aee6e36..e1108c8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -31,7 +31,7 @@ "drizzle-orm": "^0.36.0", "hono": "^4.6.9", "pg": "^8.13.1", - "zod": "^3.23.7" + "zod": "3.23.7" }, "type": "module" } diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 9159723..df8429a 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -12,6 +12,8 @@ app.use(logger()) app.use(cors()) app.onError((err, c) => { + console.error(err) + const response: ResponseDto = { status: HttpStatusEnum.INTERNAL_SERVER_ERROR, data: null, diff --git a/packages/server/src/services/config-service/index.ts b/packages/server/src/services/config-service/index.ts index a195223..ab260b8 100644 --- a/packages/server/src/services/config-service/index.ts +++ b/packages/server/src/services/config-service/index.ts @@ -13,7 +13,7 @@ function loadEnvConfig() { DB_USER: process.env["POSTGRES_USER"] ?? "postgres", DB_DB: process.env["POSTGRES_DB"] ?? "postgres", DB_HOST: process.env["POSTGRES_HOST"] ?? "localhost", - DB_PORT: Number(process.env["DB_PORT"]) ?? 5432, + DB_PORT: process.env["DB_PORT"] ?? 5432, JWT_SECRET: process.env["JWT_SECRET"] ?? "secret", } diff --git a/packages/server/src/use-cases/auth/auth.use-cases.ts b/packages/server/src/use-cases/auth/auth.use-cases.ts index e615779..ea0fc2c 100644 --- a/packages/server/src/use-cases/auth/auth.use-cases.ts +++ b/packages/server/src/use-cases/auth/auth.use-cases.ts @@ -53,6 +53,7 @@ export const AuthUseCases: IAuthUseCases = { return response } catch (e) { if (e instanceof Error) { + throw new HTTPException(HttpStatusEnum.INTERNAL_SERVER_ERROR, { message: e.message }) } diff --git a/packages/types/src/abstracts/repositories/user-repository.abstract.ts b/packages/types/src/abstracts/repositories/user-repository.abstract.ts index 24c1296..a087cac 100644 --- a/packages/types/src/abstracts/repositories/user-repository.abstract.ts +++ b/packages/types/src/abstracts/repositories/user-repository.abstract.ts @@ -1,6 +1,6 @@ import type { UserCreateDto } from "../../entities/users/user-create.dto" import type { UserUpdateDto } from "../../entities/users/user-update.dto" -import type { UserUpdateProfilePictureDto } from "src/entities/users/user-update-profile-picture.dto" +import type { UserUpdateProfilePictureDto } from "../../entities/users/user-update-profile-picture.dto" import type { UserDto, UserPublicDto } from "../../entities/users/user.dto" export type IUserRepository = { diff --git a/packages/types/src/abstracts/use-cases/auth-use-cases.abstract.ts b/packages/types/src/abstracts/use-cases/auth-use-cases.abstract.ts index 40b4f95..b803f05 100644 --- a/packages/types/src/abstracts/use-cases/auth-use-cases.abstract.ts +++ b/packages/types/src/abstracts/use-cases/auth-use-cases.abstract.ts @@ -2,6 +2,6 @@ import type { ResponseDto } from "../../entities/response/response.dto" import type { UserCreateDto } from "../../entities/users/user-create.dto" export type IAuthUseCases = { - register: (dto: UserCreateDto) => Promise> - login: (dto: UserCreateDto) => Promise> + register: (dto: UserCreateDto) => Promise> + login: (dto: UserCreateDto) => Promise> } diff --git a/packages/types/src/abstracts/use-cases/users-use-cases.abstract.ts b/packages/types/src/abstracts/use-cases/users-use-cases.abstract.ts index a6507e6..8151c44 100644 --- a/packages/types/src/abstracts/use-cases/users-use-cases.abstract.ts +++ b/packages/types/src/abstracts/use-cases/users-use-cases.abstract.ts @@ -1,7 +1,7 @@ import type { ResponseDto } from "../../entities/response/response.dto" import type { UserCreateDto } from "../../entities/users/user-create.dto" -import type { UserUpdateProfilePictureDto } from "src/entities/users/user-update-profile-picture.dto" -import type { UserUpdateDto } from "src/entities/users/user-update.dto" +import type { UserUpdateProfilePictureDto } from "../../entities/users/user-update-profile-picture.dto" +import type { UserUpdateDto } from "../../entities/users/user-update.dto" import type { UserDto, UserPublicDto } from "../../entities/users/user.dto" export type IUserUseCases = {