Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
a495bc1
refactor: standardize token auth responses using HTTPResponse
iodsky Jun 16, 2025
ddc135f
chore: remove flushDB call from server initialization
iodsky Jun 16, 2025
31a33ca
chore: rename package to brainbytes-api for clarity
iodsky Jun 16, 2025
cef1790
chore(tsconfig): simplify and update compiler options
iodsky Jun 16, 2025
154cb75
chore(docker): rename backend service to expressjs and clean up config
iodsky Jun 16, 2025
15c4333
chore: add .env.template for environment variable guidance
iodsky Jun 16, 2025
fb9a37d
refactor: add named status methods to HTTPResponse for clearer API re…
iodsky Jun 16, 2025
daf09b0
refactor: add named status methods to HTTPResponse for clearer API re…
iodsky Jun 16, 2025
b012763
refactor: use HTTPResponse.badRequest and format validation errors
iodsky Jun 16, 2025
d50d63b
refactor: make message parameter optional in ok and created responses
iodsky Jun 19, 2025
fccd52a
chore: add ESLint configuration to project
iodsky Jun 19, 2025
8bceced
chore: update target to ES2022 and exclude node_modules
iodsky Jun 19, 2025
59e5387
chore: rename project to brainbytes, add ESLint scripts and config, a…
iodsky Jun 19, 2025
3cffc6b
refactor: move Express app setup to app.ts and simplify index.ts star…
iodsky Jun 19, 2025
10f797c
fix: use post hook for cascading delete of messages in chat model
iodsky Jun 19, 2025
9b84264
refactor: use unknown instead of any for error handling in auth contr…
iodsky Jun 19, 2025
3369eb9
refactor: use findOneAndDelete for chat deletion in deleteChat contro…
iodsky Jun 19, 2025
11fd3a4
feat: return 404 if no messages found for given chatId
iodsky Jun 19, 2025
367feec
refactor: improve type safety in token auth middleware by using unkno…
iodsky Jun 19, 2025
a0a09e6
test: add integration tests for registration and login routes using J…
iodsky Jun 20, 2025
0c2a118
chore: add basic Jest config for ts-jest with Node environment
iodsky Jun 20, 2025
b550a9e
chore: rename and add MongoDB URI variables for clarity and testing
iodsky Jun 20, 2025
a13e2c4
chore: add coverage and dist dir to .gitignore
iodsky Jun 20, 2025
a3abc2a
chore: rename project, update scripts, and add testing dependencies
iodsky Jun 20, 2025
9ff02f0
chore: rename project, update scripts, and add testing dependencies
iodsky Jun 20, 2025
ac4b60a
chore: exclude test files from TypeScript build output
iodsky Jun 20, 2025
f15c610
refactor(auth): move password hashing to user model pre-save hook
iodsky Jun 20, 2025
b356b9d
test: add health check endpoint test
iodsky Jun 20, 2025
be8e133
chore: improve MongoDB connection logging and env variable naming
iodsky Jun 20, 2025
db45a05
chore: add mongodb-memory-server to dev dependencies.
iodsky Jun 22, 2025
9b36d6f
chore: remove MONGO_URI_TEST env variable
iodsky Jun 22, 2025
fb6107d
chore: use ESM-style default export in config
iodsky Jun 22, 2025
70f1901
feat: add in-memory MongoDB test-db utility
iodsky Jun 22, 2025
9ae48f9
refactor: migrate to in-memory MongoDB for test setup
iodsky Jun 22, 2025
182620e
refactor: make attachmentUrls optional in ConvoGenParam
iodsky Jun 24, 2025
d564272
refactor: set default empty array for optional attachmentUrls in invo…
iodsky Jun 24, 2025
0df4031
refactor: convert from class-based to functional module
iodsky Jun 24, 2025
4b46a54
refactor: Update import and use updated generateResponse funciton
iodsky Jun 24, 2025
4582cd2
refactor: Update import and use updated generateResponse funciton
iodsky Jun 24, 2025
5bce6c0
feat: Implement integration test for chat endpoints.
iodsky Jun 24, 2025
7607410
test: add integration tests for /messsage endpoints using jest and su…
iodsky Jun 27, 2025
a1f5f9e
chore: rename Dockerfile to Dockerfile.dev
iodsky Jun 27, 2025
4b990ee
feact: Implement logger util using winston
iodsky Jun 29, 2025
5b7cfa8
refactor: Replace standard logging with custom logger.
iodsky Jun 29, 2025
e9f8f34
chore: Add winston and morgan to project dependencies
iodsky Jun 29, 2025
f7b069b
feat: Implement morgan middleware to log http requests
iodsky Jun 29, 2025
ece74fe
refactor: Update systemInstruction for improved title and subject gen…
iodsky Jun 29, 2025
e27c4c3
test: Add unit tests for prompt-service
iodsky Jun 30, 2025
34d585b
refactor: rename response field to json_response for clarity
iodsky Jun 30, 2025
5358fdc
refactor: unify response format and return structured PromptResponse
iodsky Jun 30, 2025
44c2b20
refactor: use structured PromptResponse instead of parsing raw text
iodsky Jun 30, 2025
636f9aa
refactor: rename generate_title response field from name to title
iodsky Jun 30, 2025
c645db7
test: update tests to use typed PromptResponse and json_response field
iodsky Jun 30, 2025
348cd16
chore: rename docker-compose.yml to dev.compose.yml for env-specific …
iodsky Jul 3, 2025
5dcc720
chore: add Docker Compose scripts for development
iodsky Jul 3, 2025
30141c0
chore: remove cors middleware
iodsky Jul 4, 2025
5b62dad
chore: update dependencies
iodsky Jul 4, 2025
4a6e898
chore: relax type checks and refine exclusions
iodsky Jul 4, 2025
7c5810b
chore: update .gitignore and .dockerignore for cleaner workspace
iodsky Jul 4, 2025
394b6bd
chore: update .env.template to remove unused CORS config
iodsky Jul 4, 2025
e65c7b4
chore: rename backend service to expressjs for consistency
iodsky Jul 5, 2025
cf44b8c
chore: Add Dockerfile and docker compose for production environment
iodsky Jul 5, 2025
9aac1d7
ci: setup GitHub Actions workflow with workflow_dispatch for testing
iodsky Jul 5, 2025
863dd74
ci: updated GitHub Actions workflow for testing
iodsky Jul 5, 2025
f9050ee
fix(ci): update GitHub Actions workflow for testing
iodsky Jul 5, 2025
33ce5b3
ci: add code quality check with lint job and improve test job with pn…
iodsky Jul 6, 2025
d140e9d
fix(ci): use pnpm/action-setup to install Node.js and pnpm, removing …
iodsky Jul 6, 2025
e707965
chore(ci): update GitHub Actions workflow
iodsky Jul 6, 2025
375a504
fix(ci): update build job to use Dockerfile.prod
iodsky Jul 6, 2025
8c4724e
fix(ci): correct GHCR image tag format in Docker build step
iodsky Jul 6, 2025
841eb53
fix(ci): use personal access token for GHCR authentication
iodsky Jul 6, 2025
f459ae9
replace console.log with custom logger util
iodsky Jul 7, 2025
a098380
chore: update NODE_ENV from 'prod' to 'production' in expressjs service
iodsky Jul 7, 2025
6e62d81
chore: update start script to run compiled code with Node.js
iodsky Jul 7, 2025
5ae19ba
fix(ci): update GitHub Actions to use 'master' instead of 'main' branch
iodsky Jul 10, 2025
6189d7a
chore(docker): use prebuilt image for expressjs service from GHCR
iodsky Jul 10, 2025
2b41052
ci: Optimize workflow by seperating node.js setup and add build job c…
iodsky Jul 14, 2025
e109610
fix: ci install pnpm globally to resolve executable error
iodsky Jul 14, 2025
c887062
fix(ci): remove cache pnpm to resolve missing executable file error
iodsky Jul 14, 2025
58f0fde
fix(ci): properly configure pnpm setup and caching order in GitHub Ac…
iodsky Jul 14, 2025
8645fd8
fix(ci): Remove redundant pnpm install in test job
iodsky Jul 14, 2025
218c5b7
fix(test): add testTimout config and set to 30 seconds
iodsky Jul 14, 2025
50bca85
feat: add explicit Docker networks for prod services and Traefik inte…
iodsky Jul 15, 2025
0c9ccc9
feat: add Traefik reverse proxy with Docker provider and HTTPS support
iodsky Jul 15, 2025
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
17 changes: 16 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Ignore dependencies and build outputs
node_modules
dist
coverage

# Ignore environment and config files
.env

# Ignore Docker files themselves (optional)
Dockerfile
Dockerfile.dev
docker-compose.yml
dev.compose.yml
.dockerignore
.env

# Ignore local database or test assets
database

# Ignore local API testing/debugging tools like Bruno collections
BrainBytes
8 changes: 8 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
PORT=
NODE_ENV=

JWT_SECRET=
IS_DOCKERIZED=
MONGO_URI_ATLAS=
MONGO_URI_DOCKER=
GEMINI_KEY=
104 changes: 104 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: BrainBytes CI

on:
push:
branches: [master, develop]
paths-ignore:
- "**.md"
- "docs/**"
pull_request:
branches: [master, develop]
paths-ignore:
- "**.md"
- "docs/**"
workflow_dispatch:

jobs:
lint:
name: Check Code Quality
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: "10.10.0"

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: "24.1.0"
cache: "pnpm"

- name: Install dependencies
working-directory: ./src
run: pnpm install --no-frozen-lockfile

- name: Lint source code
working-directory: ./src
run: pnpm lint

test:
name: Run Tests
needs: lint
runs-on: ubuntu-latest
environment: GitHub actions
env:
JWT_SECRET: ${{secrets.JWT_SECRET}}
MONGO_URI_DOCKER: ${{secrets.MONGO_URI_DOCKER}}

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: "10.10.0"

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: "24.1.0"
cache: "pnpm"

- name: Install dependencies
working-directory: ./src
run: pnpm install --no-frozen-lockfile

- name: Run backend tests
working-directory: ./src
run: pnpm test

build:
name: Build Docker Image
needs: ["lint", "test"]
runs-on: ubuntu-latest
environment: GitHub actions
if: github.event_name == 'push' && github.ref == 'refs/heads/master'

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_PAT }}

- name: Build and push Image
uses: docker/build-push-action@v4
with:
file: ./Dockerfile.prod
push: true
tags: ghcr.io/${{ github.repository_owner }}/brainbytes-api:latest
cache-from: type=gha
cache-to: type=gha,mode=max
20 changes: 19 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
# Ignore dependencies and build outputs
node_modules
.env
dist
coverage

# Ignore environment and config files
.env

# Ignore Docker files themselves (optional)
Dockerfile
Dockerfile.dev
docker-compose.yml
dev.compose.yml
.dockerignore

# Ignore local database or test assets
database

# Ignore local API testing/debugging tools like Bruno collections
BrainBytes
File renamed without changes.
31 changes: 31 additions & 0 deletions Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Stage 1: Build
FROM node:24-alpine AS builder

WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy only package files first (to cache install layers)
COPY package.json pnpm-lock.yaml ./

RUN pnpm install

# Then copy rest of the source
COPY . .

RUN pnpm build

# Stage 2: Run only compiled code
FROM node:24-alpine

WORKDIR /app

# Copy only the necessary runtime files from the first stage into the second stage
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist

EXPOSE 8000

CMD ["node", "dist/index.js"]
40 changes: 15 additions & 25 deletions docker-compose.yaml → dev.compose.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# Use docker compose file format version 3.8
version: "3.8"

# Define all services (containers)
services:
# MongoDB service
mongodb:
# Use official mongoDB image
image: mongo:latest
# Always restart unless forcibly stop the process.
restart: unless-stopped
ports:
- "27017:27017"
# Create volume within src directory
volumes:
- ./database/mongodb-data:/data/db
# Backend service
backend:
expressjs:
# Build the docker image from the dockerfile in the current dir
build: .

# Set custom container name
container_name: brainbytes-server
build:
dockerfile: Dockerfile.dev

# Map port 8000 inside the container to port 8000 on the host machine
ports:
Expand All @@ -24,23 +30,7 @@ services:

# Wait for mongo servvice to start
depends_on:
- mongo
- mongodb

# Override the default command and run npm start
command: pnpm start

# MongoDB service
mongo:
# Use official mongoDB image
image: mongo:latest

container_name: brainbytes-db
restart: unless-stopped
ports:
- "27017:27017"

volumes:
- mongo-data:/data/db

volumes:
mongo-data:
11 changes: 11 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";


export default defineConfig([
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], plugins: { js }, extends: ["js/recommended"] },
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], languageOptions: { globals: globals.browser } },
tseslint.configs.recommended,
]);
7 changes: 7 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
preset: "ts-jest",
testEnvironment: "node",
testMatch: ["**/test/**/*test.ts"],
testPathIgnorePatterns: ["/node_modules"],
testTimeout: 30000,
};
49 changes: 34 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,56 @@
{
"name": "brainbytes",
"name": "brainbytes-api",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"scripts": {
"start": "tsx src/index.ts",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"compose": "docker-compose up --build"
"compose": "docker-compose -f dev.compose.yaml up",
"compose:build": "docker-compose -f dev.compose.yaml up --build",
"compose:down": "docker-compose -f dev.compose.yaml down",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"test": "jest",
"test:coverage": "jest --coverage",
"build": "tsc",
"clean": "rmdir /s /q dist"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.10.0",
"dependencies": {
"@google/genai": "^1.0.1",
"@google/genai": "^1.5.1",
"bcryptjs": "^3.0.2",
"body-parser": "^2.2.0",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"express": "^5.1.0",
"express-validator": "^7.2.1",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.16.0",
"mongoose": "^8.15.0"
"mongodb": "^6.17.0",
"mongoose": "^8.16.0",
"morgan": "^1.10.0",
"winston": "^3.17.0"
},
"devDependencies": {
"@types/body-parser": "^1.19.5",
"@types/cookie-parser": "^1.4.8",
"@types/cors": "^2.8.18",
"@types/express": "^5.0.2",
"@types/jsonwebtoken": "^9.0.9",
"@types/node": "^22.15.21",
"@eslint/js": "^9.29.0",
"@types/cookie-parser": "^1.4.9",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.3",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "^9.0.10",
"@types/morgan": "^1.9.10",
"@types/node": "^24.0.3",
"@types/supertest": "^6.0.3",
"dotenv": "^16.5.0",
"tsx": "^4.20.3"
"eslint": "^9.29.0",
"globals": "^16.2.0",
"jest": "^30.0.2",
"mongodb-memory-server": "^10.1.4",
"supertest": "^7.1.1",
"ts-jest": "^29.4.0",
"tsx": "^4.20.3",
"typescript": "^5.8.3",
"typescript-eslint": "^8.34.1"
}
}
Loading