Files
backend/CONTEXT.md
T

7.4 KiB

Balout Pastry — Backend (setup context)

NestJS API for شیرینی‌فروشی بلوط. Serves the admin Dashboards SPA (and future customer apps).

Repo: https://git.meshkee.com/BaloutPastry/backend.git
Dashboards repo: https://git.meshkee.com/BaloutPastry/dashboards.git

Stack

  • NestJS 11 / TypeScript
  • Prisma 6 + PostgreSQL 16 (Docker Compose)
  • JWT access + refresh tokens (bcrypt password hashes)
  • Parspack S3-compatible object storage (prefix balout/)

Prerequisites

  • Node.js 20+ (LTS recommended)
  • npm
  • Docker + Docker Compose (for local Postgres)
  • S3 credentials if you need media upload (can leave blank for auth/users-only local work)

Setup on a new device

git clone https://git.meshkee.com/BaloutPastry/backend.git
cd backend

cp .env.example .env
# Fill S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY if you need uploads
# Change JWT_* secrets before any shared/staging use

npm install
npm run db:up                 # Postgres on 127.0.0.1:5434
npx prisma migrate deploy     # apply migrations
npx prisma generate           # if client missing after install

npm run create-super-admin -- --phone 09120000000 --password secret123
# optional: --first علی --last رضایی --title "جناب آقای"

npm run start:dev             # http://localhost:3100/api/v1

Health check: GET http://localhost:3100/api/v1/auth/me401 without token is expected (server is up).

Pair with Dashboards

  1. Keep this API on 3100
  2. In dashboards: VITE_API_BASE_URL=http://localhost:3100/api/v1
  3. Backend CORS_ORIGIN must include local dashboard origins, e.g.
    http://baloutpastry.com:5173,http://admin.baloutpastry.com:5173,http://customer.baloutpastry.com:5173,http://localhost:5173
  4. Add local DNS in /etc/hosts for baloutpastry.com, admin.baloutpastry.com, customer.baloutpastry.com127.0.0.1
  5. Log in with the super-admin phone/password you created
    • Admin: http://admin.baloutpastry.com:5173
    • Customer: http://customer.baloutpastry.com:5173

Scripts

Command What it does
npm run start:dev Nest watch mode → http://localhost:3100/api/v1
npm run start:prod Run compiled dist/main
npm run build Compile Nest → dist/
npm run db:up docker compose up -d (Postgres)
npm run db:down Stop Postgres container
npm run prisma:migrate Create/apply migrations in dev
npm run prisma:deploy Apply existing migrations (CI / new device)
npm run prisma:generate Regenerate Prisma Client
npm run create-super-admin Create first superAdmin user
npm run send-sms Send SMS via Meshkee (--to / --message)
npm run lint ESLint

Environment

Copy from .env.example. Do not commit .env.

Variable Notes
DATABASE_URL Prisma connection string (default → local Docker on 5434)
POSTGRES_* Used by Docker Compose
PORT API port, default 3100
CORS_ORIGIN Comma-separated origins; include dashboard URL
JWT_ACCESS_SECRET / JWT_REFRESH_SECRET Change from example values
JWT_ACCESS_EXPIRES_IN / JWT_REFRESH_EXPIRES_IN e.g. 15m / 7d
STORAGE_DISK s3 for Parspack
S3_* Endpoint, bucket, public URL, keys
MEDIA_MAX_FILE_SIZE_MB Upload size cap
MESHKEE_SMS_URL Meshkee public SMS send endpoint
MESHKEE_SMS_API_KEY Partner API key (X-Api-Key) — server only
MESHKEE_SMS_DOMAIN Partner domain, e.g. baloutpastry.com

Inject SmsService from SmsModule to send SMS from the backend (never from the frontend). Limits: 30/partner/min, 5/destination/min.

npm run send-sms -- --to 09127004945 --message "متن پیام"

Ports are intentional vs Meshkee: API 3100, Postgres host 5434 (Meshkee uses 3000 / 5432).

Auth rules

  • Login: POST /auth/login with { "cellNumber": "09…", "password": "…" }
  • Login with SMS: POST /auth/login/send-code then POST /auth/login/verify
  • Forgot password: POST /auth/forgot-password/send-code/verify/reset
  • Register: POST /auth/register/send-code then POST /auth/register/verify (SMS OTP → create customer)
  • Only admin and superAdmin can log in to the admin API/dashboard
  • Only superAdmin can assign admin or superAdmin roles
  • customer users exist for orders / future customer UI
  • Access token in Authorization: Bearer …; refresh via POST /auth/refresh

Main routes (/api/v1)

Area Methods
Auth POST /auth/login, /auth/login/send-code, /auth/login/verify, /auth/forgot-password/send-code, /auth/forgot-password/verify, /auth/forgot-password/reset, /auth/register/send-code, /auth/register/verify, /auth/refresh, /auth/logout, GET /auth/me
Users CRUD + PATCH /users/:id/role, /password + addresses under /users/:id/addresses
Flavors CRUD
Categories tree CRUD + GET|PUT /categories/:id/options
Products CRUD (options must match category templates); list filters q, categoryId, minPrice, maxPrice
Orders GET /orders, GET /orders/:id, POST /orders, PATCH /orders/:id/status
Media POST /media/upload?kind=main|gallery|temp
Settings districts, shipping exceptions, branches

Guards: most routes require JWT + admin/superAdmin. Role changes require superAdmin.

Orders

Create body example:

{
  "customerId": "...",
  "deliveryType": "pickup",
  "branchId": "...",
  "note": "optional",
  "items": [
    { "productId": "...", "quantity": 2, "optionIds": ["..."] }
  ]
}

For shipping: deliveryType: "shipping" + shippingAddressId (from user addresses). Prices/names are snapshotted. Display code: BL-{number}.

Domain notes

  • Prices are integer تومان
  • Phone numbers: 09 + 9 digits (English digits)
  • User titles/categories are fixed Persian enums in src/users/users.constants.ts

Project layout

prisma/                 schema + migrations
scripts/                create-super-admin.ts
src/
  auth/                 JWT login, refresh, guards, roles
  users/                users + addresses
  flavors/
  categories/
  products/
  orders/
  media/                uploads
  settings/             districts, shipping, branches
  storage/              S3 driver
  prisma/               PrismaModule / PrismaService
  main.ts               global prefix api/v1, CORS, ValidationPipe
docker-compose.yml      local Postgres

Production sketch

cp .env.example .env   # real secrets, DB, CORS, S3
npm ci
npx prisma migrate deploy
npm run build
npm run start:prod

Ensure Postgres is reachable via DATABASE_URL and CORS_ORIGIN lists the real dashboard origin(s).

Common issues

Symptom Likely cause
ECONNREFUSED / Prisma errors Postgres not up → npm run db:up, check DATABASE_URL / port 5434
Port already in use Another process on 3100 or 5434
Login rejected for valid user Role is customer, or wrong phone format
CORS errors from dashboard CORS_ORIGIN missing http://localhost:5173
Upload fails Missing/invalid S3_* keys or endpoint
User already exists on create-super-admin That phone is already in DB
  • Dashboards setup: clone BaloutPastry/dashboards and read CONTEXT.md
  • Website (storefront): clone BaloutPastry/website and read CONTEXT.md (dev port 5174)
  • Short API overview also in README.md