mirror of
https://git.meshkee.com/BaloutPastry/backend.git
synced 2026-08-11 22:31:00 +04:30
Add CONTEXT.md with full new-device setup guide.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
f40075fd5e
commit
58380ab81d
+178
@@ -0,0 +1,178 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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/me` → `401` 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 `http://localhost:5173`
|
||||||
|
4. Log in with the super-admin phone/password you created
|
||||||
|
|
||||||
|
## 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 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 |
|
||||||
|
|
||||||
|
Ports are intentional vs Meshkee: API **3100**, Postgres host **5434** (Meshkee uses 3000 / 5432).
|
||||||
|
|
||||||
|
## Auth rules
|
||||||
|
|
||||||
|
- Login: `POST /auth/login` with `{ "cellNumber": "09…", "password": "…" }`
|
||||||
|
- 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/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:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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 |
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- Dashboards setup: clone `BaloutPastry/dashboards` and read `CONTEXT.md`
|
||||||
|
- Short API overview also in `README.md`
|
||||||
Reference in New Issue
Block a user