Skip to content

Commit d8bd784

Browse files
authored
Merge pull request #1 from frckbrice/feat/align_project
Feat/align project
2 parents 543f2aa + 46e43b3 commit d8bd784

103 files changed

Lines changed: 13711 additions & 4467 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Dependencies and build output
2+
node_modules
3+
dist
4+
.pnpm-store
5+
6+
# Git and IDE
7+
.git
8+
.gitignore
9+
.cursor
10+
.vscode
11+
*.code-workspace
12+
13+
# Env and secrets (use runtime env or secrets)
14+
.env
15+
.env.*
16+
!.env.example
17+
18+
# Tests and coverage
19+
coverage
20+
**/__tests__
21+
**/*.test.ts
22+
**/*.spec.ts
23+
jest.config.js
24+
jest.setup.js
25+
26+
# Docs and misc
27+
docs
28+
*.md
29+
!README.md
30+
31+
# CI
32+
.github
33+
34+
# Local and OS
35+
.DS_Store
36+
Thumbs.db
37+
*.log

.editorconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# EditorConfig: keep indentation consistent so format-on-save doesn't break spec.ts
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf

.env.example

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
1-
DATABASE_URL=""
2-
SESSION_SECRET=""
3-
REPL_ID=""
4-
API_PROD_URL=""
1+
# Required: at least one of DATABASE_URL (dev) or DATABASE_URL_PROD (prod)
2+
DATABASE_URL="postgresql://user:password@localhost:5432/museum"
3+
# DATABASE_URL_PROD="postgresql://..."
4+
5+
# Required: min 32 characters
6+
SESSION_SECRET="your-super-secret-session-key-at-least-32-chars"
7+
8+
# Server
9+
PORT=5001
10+
NODE_ENV=development
11+
12+
# CORS: allowed origin for browser requests (default http://localhost:3000)
13+
FRONTEND_URL="http://localhost:3000"
14+
# Optional: comma-separated extra origins
15+
# CORS_ORIGINS="https://app.example.com,https://admin.example.com"
16+
17+
# Production: set when NODE_ENV=production
18+
# API_PROD_URL="https://api.example.com"
19+
20+
# Optional: Cloudinary (for gallery uploads)
21+
# CLOUDINARY_CLOUD_NAME=
22+
# CLOUDINARY_API_KEY=
23+
# CLOUDINARY_API_SECRET=

.eslintrc.cjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* ESLint config for TypeScript and Node.js (ESLint 8 compatible).
3+
* Ensures consistent style and catches common issues before push/CI.
4+
*/
5+
module.exports = {
6+
root: true,
7+
env: { node: true, es2022: true },
8+
parser: "@typescript-eslint/parser",
9+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
10+
plugins: ["@typescript-eslint"],
11+
extends: [
12+
"eslint:recommended",
13+
"plugin:@typescript-eslint/recommended",
14+
"prettier",
15+
],
16+
ignorePatterns: ["node_modules", "dist", "*.js", "drizzle", "config/openapi"],
17+
rules: {
18+
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
19+
"@typescript-eslint/no-explicit-any": "warn",
20+
"@typescript-eslint/explicit-function-return-type": "off",
21+
"@typescript-eslint/no-require-imports": "off",
22+
"no-console": ["warn", { allow: ["warn", "error"] }],
23+
},
24+
};

.github/workflows/ci.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, master, develop]
6+
pull_request:
7+
branches: [main, master, develop]
8+
9+
jobs:
10+
test:
11+
name: Test and Lint
12+
runs-on: ubuntu-latest
13+
14+
strategy:
15+
matrix:
16+
node-version: [20.x]
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Install pnpm
23+
uses: pnpm/action-setup@v4
24+
with:
25+
version: 8
26+
27+
- name: Setup Node.js ${{ matrix.node-version }}
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: ${{ matrix.node-version }}
31+
cache: "pnpm"
32+
33+
- name: Get pnpm store directory
34+
shell: bash
35+
run: |
36+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
37+
38+
- name: Setup pnpm cache
39+
uses: actions/cache@v4
40+
with:
41+
path: ${{ env.STORE_PATH }}
42+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
43+
restore-keys: |
44+
${{ runner.os }}-pnpm-store-
45+
46+
- name: Install dependencies
47+
run: pnpm install --frozen-lockfile
48+
49+
- name: Check formatting
50+
run: pnpm run format:check
51+
52+
- name: Run linter
53+
run: pnpm run lint
54+
55+
- name: Type check
56+
run: pnpm run check
57+
58+
- name: Run tests
59+
run: pnpm run test
60+
env:
61+
NODE_ENV: test
62+
63+
- name: Build project
64+
run: pnpm run build
65+
66+
build:
67+
name: Build
68+
runs-on: ubuntu-latest
69+
needs: test
70+
71+
steps:
72+
- name: Checkout code
73+
uses: actions/checkout@v4
74+
75+
- name: Install pnpm
76+
uses: pnpm/action-setup@v4
77+
with:
78+
version: 8
79+
80+
- name: Setup Node.js
81+
uses: actions/setup-node@v4
82+
with:
83+
node-version: 20.x
84+
cache: "pnpm"
85+
86+
- name: Get pnpm store directory
87+
shell: bash
88+
run: |
89+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
90+
91+
- name: Setup pnpm cache
92+
uses: actions/cache@v4
93+
with:
94+
path: ${{ env.STORE_PATH }}
95+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
96+
restore-keys: |
97+
${{ runner.os }}-pnpm-store-
98+
99+
- name: Install dependencies
100+
run: pnpm install --frozen-lockfile
101+
102+
- name: Prepare for build
103+
run: pnpm run prebuild
104+
105+
- name: Build for production
106+
run: pnpm run build:prod
107+
108+
- name: Upload build artifacts
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: dist
112+
path: dist/
113+
retention-days: 7
114+
115+
docker:
116+
name: Docker build
117+
runs-on: ubuntu-latest
118+
needs: test
119+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
120+
steps:
121+
- name: Checkout code
122+
uses: actions/checkout@v4
123+
124+
- name: Set up Docker Buildx
125+
uses: docker/setup-buildx-action@v3
126+
127+
- name: Build Docker image
128+
uses: docker/build-push-action@v6
129+
with:
130+
context: .
131+
push: false
132+
load: true
133+
tags: museum-management-rest-api:latest
134+
cache-from: type=gha
135+
cache-to: type=gha,mode=max

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ logs
88
config/database/reset-db.ts
99
todo-tasks.md
1010
config/database/seed.ts
11-
config/database/badagry_backend.code-workspace.json
11+
config/database/museum-management.code-workspace*
1212
.DS_Store
1313
*.swp
1414
*.swo

.prettierignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Dependencies and build
2+
node_modules
3+
dist
4+
build
5+
*.min.js
6+
7+
# Lockfiles and generated
8+
pnpm-lock.yaml
9+
package-lock.json
10+
*.config.js
11+
12+
# Drizzle and migrations (generated)
13+
drizzle/**/*.sql
14+
15+
# Env (secrets)
16+
.env
17+
.env.*
18+
!.env.example
19+
20+
# OpenAPI spec (manual formatting; do not strip curly braces or reformat)
21+
config/openapi/
22+
config/openapi/spec.ts
23+
**/config/openapi/**

.prettierrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 100
7+
}

.vscode/settings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"editor.formatOnSave": true,
3+
"[typescript]": {
4+
"editor.defaultFormatter": "esbenp.prettier-vscode"
5+
},
6+
"editor.detectIndentation": false,
7+
"editor.tabSize": 2,
8+
"editor.insertSpaces": true,
9+
"prettier.ignorePath": ".prettierignore"
10+
}

Dockerfile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Museum Management REST API — multi-stage build (smallest image)
2+
# =============================================================
3+
# Stage 1: Dependencies and build
4+
FROM node:20-alpine AS builder
5+
6+
RUN corepack enable && corepack prepare pnpm@latest --activate
7+
WORKDIR /app
8+
9+
COPY package.json pnpm-lock.yaml* ./
10+
RUN pnpm install --frozen-lockfile
11+
12+
COPY tsconfig.json ./
13+
COPY index.ts app.ts ./
14+
COPY config config/
15+
COPY middlewares middlewares/
16+
COPY server server/
17+
COPY drizzle.config.ts ./
18+
COPY drizzle drizzle/
19+
20+
RUN pnpm run build
21+
22+
# Prune dev dependencies so runner only gets production node_modules
23+
RUN pnpm prune --prod
24+
25+
# Stage 2: Production runner (minimal: no pnpm, no dev deps)
26+
FROM node:20-alpine AS runner
27+
28+
WORKDIR /app
29+
30+
ENV NODE_ENV=production
31+
ENV PORT=5001
32+
33+
# Copy only runtime artifacts from builder (no source, no devDependencies)
34+
COPY --from=builder /app/package.json ./
35+
COPY --from=builder /app/node_modules ./node_modules
36+
COPY --from=builder /app/dist ./dist
37+
COPY --from=builder /app/drizzle ./drizzle
38+
COPY --from=builder /app/drizzle.config.ts ./
39+
40+
# Non-root user for security
41+
RUN addgroup -g 1001 -S app && adduser -u 1001 -S app -G app
42+
USER app
43+
44+
EXPOSE ${PORT}
45+
46+
CMD ["node", "dist/index.js"]

0 commit comments

Comments
 (0)