mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 12:41:04 +00:00
add readme
This commit is contained in:
260
README.md
260
README.md
@@ -1 +1,259 @@
|
||||
# edr-platform
|
||||
# EDR Platform
|
||||
|
||||
Monorepo for the **Ethio-Djibouti Railway** digital platform. Hosts two product lines — **Freight Management** and **Passenger Management** — each with a NestJS API plus React portal and back-office web apps, sharing TypeScript types, NestJS utilities, and a React component library.
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Backend
|
||||
|
||||
| Layer | Tech |
|
||||
| ---------------- | ----------------------------------------------- |
|
||||
| Runtime | Node.js ≥ 20 |
|
||||
| Framework | NestJS 11 (modular architecture) |
|
||||
| Language | TypeScript 5 (strict mode, project-wide) |
|
||||
| ORM | TypeORM 0.3 (UUID PKs, soft deletes, `snake_case` columns) |
|
||||
| Database | PostgreSQL 16 (one DB per domain) |
|
||||
| Validation | class-validator + class-transformer |
|
||||
| API docs | Swagger via `@nestjs/swagger` |
|
||||
| Messaging | `@nestjs/microservices` (inter-service ready) |
|
||||
| Testing | Jest + Supertest |
|
||||
|
||||
### Frontend
|
||||
|
||||
| Layer | Tech |
|
||||
| ---------------- | ----------------------------------------------- |
|
||||
| Framework | React 18 + Vite 5 |
|
||||
| Language | TypeScript 5 (strict) |
|
||||
| Routing | React Router v6 |
|
||||
| Styling | Tailwind CSS v4 (`@tailwindcss/vite`) + `tailwind-merge` + `class-variance-authority` |
|
||||
| UI primitives | Radix UI (meta `radix-ui` package, shadcn-style components) |
|
||||
| Icons | lucide-react |
|
||||
| State / Data | Zustand (client state) · TanStack Query (server state) |
|
||||
| HTTP | Axios |
|
||||
| Auth UI | `@tria-plc/iamui-common` (external IAM) |
|
||||
|
||||
### Shared Packages
|
||||
|
||||
| Package | Purpose |
|
||||
| ---------------------- | -------------------------------------------------------------------- |
|
||||
| `@edr/types` | Shared TypeScript interfaces and enums |
|
||||
| `@edr/api-common` | NestJS decorators, filters, interceptors, pipes, `BaseEntity`, `BaseRepository` |
|
||||
| `@edr/ui-common` | Shared React components (`DashboardLayout`, `Sidebar`, `Button`, `Modal`, etc.) and theme tokens |
|
||||
| `@edr/eslint-config` | Shared ESLint configs (base / nestjs / react) |
|
||||
| `@edr/tsconfig` | Shared TypeScript configs |
|
||||
| `@edr/prettier-config` | Shared Prettier configuration |
|
||||
|
||||
### Tooling
|
||||
|
||||
- **pnpm 9** — workspace package manager (sole supported PM)
|
||||
- **Turborepo 2** — task orchestrator with caching
|
||||
- **Husky + lint-staged + commitlint** — pre-commit ESLint/Prettier and conventional-commit enforcement
|
||||
- **Docker Compose** — local Postgres instances + production stack (see `infrastructure/`)
|
||||
- **Nginx** — reverse proxy / static asset server in production
|
||||
|
||||
### Planned Integrations
|
||||
|
||||
- **MinIO** — S3-compatible object storage for documents (object keys already shaped under `edr-freight/{linkedType}/{ref}/{filename}`)
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### High-level layout
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ EDR Platform (monorepo) │
|
||||
├──────────────────────┬───────────────────────────────────────────┤
|
||||
│ Freight domain │ Passenger domain │
|
||||
│ ┌────────────────┐ │ ┌────────────────┐ │
|
||||
│ │ freight-portal │ │ │ passenger- │ │
|
||||
│ │ (React) │ │ │ portal (React)│ │
|
||||
│ ├────────────────┤ │ ├────────────────┤ │
|
||||
│ │ freight- │ │ │ passenger- │ │
|
||||
│ │ backoffice │ │ │ backoffice │ │
|
||||
│ └───────┬────────┘ │ └───────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ ┌────────────────┐ │ ┌────────────────┐ │
|
||||
│ │ freight-api │ │ │ passenger-api │ │
|
||||
│ │ (NestJS) │ │ │ (NestJS) │ │
|
||||
│ └───────┬────────┘ │ └───────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ ┌────────────────┐ │ ┌────────────────┐ │
|
||||
│ │ postgres- │ │ │ postgres- │ │
|
||||
│ │ freight │ │ │ passenger │ │
|
||||
│ └────────────────┘ │ └────────────────┘ │
|
||||
└──────────────────────┴───────────────────────────────────────────┘
|
||||
Shared (workspace) packages
|
||||
@edr/types · @edr/api-common · @edr/ui-common · @edr/{eslint,tsconfig,prettier}-config
|
||||
```
|
||||
|
||||
### Domain isolation
|
||||
|
||||
- **One database per domain.** `postgres-freight` (port 5433, db `edr_freight`) and `postgres-passenger` (port 5434, db `edr_passenger`). No cross-database joins. Cross-domain data flows only through API calls or message queues.
|
||||
- **Each domain owns its data model.** Freight bookings/consignments/shipments/trains/invoices/documents live only in the freight DB; passenger journeys/tickets live only in the passenger DB.
|
||||
|
||||
### NestJS module pattern (per feature)
|
||||
|
||||
```
|
||||
modules/<feature>/
|
||||
entities/<feature>.entity.ts // extends BaseEntity (UUID, timestamps, soft delete)
|
||||
dto/<verb>-<feature>.dto.ts // class-validator DTOs
|
||||
<feature>.module.ts // wires controller + service + repository
|
||||
<feature>.controller.ts // HTTP layer only — no business logic
|
||||
<feature>.service.ts // business logic
|
||||
<feature>.repository.ts // extends BaseRepository<Entity>; services inject this, NEVER `Repository<T>` directly
|
||||
```
|
||||
|
||||
Conventions enforced across the codebase:
|
||||
|
||||
- All entities have UUID primary keys (`@PrimaryGeneratedColumn('uuid')`).
|
||||
- All entities inherit `createdAt` / `updatedAt` / `deletedAt` from `BaseEntity` (soft delete).
|
||||
- DB columns use `snake_case` via `@Column({ name: '...' })`; TS properties stay `camelCase`.
|
||||
- **No `synchronize: true`** in production — schema changes go through TypeORM migrations.
|
||||
- ESLint + Prettier run on pre-commit via Husky + lint-staged.
|
||||
- Conventional-commits enforced via commitlint.
|
||||
|
||||
### Frontend application structure
|
||||
|
||||
```
|
||||
apps/edr-freight-web/portal/src/
|
||||
App.tsx // routes + sidebar definition
|
||||
main.tsx // React Router + QueryClient providers
|
||||
components/
|
||||
Breadcrumbs.tsx // shared local UI
|
||||
ui/ // shadcn-style primitives (Button, Input, Dialog, Label, Textarea)
|
||||
pages/
|
||||
customers/ // CustomersPage + CustomerDetailPage + NewCustomerPage (dialog)
|
||||
bookings/ // ... + multimodal Transport Legs editor
|
||||
consignments/
|
||||
tracking/ // Shipment grid + table view toggle
|
||||
trains/ // Fleet roster
|
||||
billing/ // Invoices
|
||||
documents/ // MinIO-shaped document library
|
||||
hooks/ // TanStack Query hooks (per feature)
|
||||
services/ // Axios clients (per feature)
|
||||
store/ // Zustand stores
|
||||
lib/ // utilities (`cn` helper, formatters)
|
||||
```
|
||||
|
||||
Each feature folder typically contains: `*Page.tsx` (list), `*DetailPage.tsx`, `New*Page.tsx` (create/edit dialog with `mode: "create" | "edit"`), `Delete*Dialog.tsx`, and a `*.mock.ts` seed file used by the current mock UI.
|
||||
|
||||
### Shared layout (`@edr/ui-common`)
|
||||
|
||||
`DashboardLayout` provides the sidebar + header shell shared across all freight and passenger web apps:
|
||||
|
||||
- **Sidebar** — brand-tinted, icon-led navigation; the brand color (`#33578D`) marks the active item.
|
||||
- **Header** — language picker, notifications, user dropdown (click-driven, click-outside / Escape close); host apps opt into a light/dark theme toggle via `enableThemeToggle` (Tailwind class-based, persisted in `localStorage`).
|
||||
|
||||
### Auth integration (planned)
|
||||
|
||||
Authentication is provided by an external `@edr/iamui-common` / `@tria-plc/iamapi-common` package. **Do not** implement login/JWT/password logic in this repo. Use placeholder TODO comments next to controllers and `@CurrentUser` decorators (in `@edr/api-common`) until the integration ships.
|
||||
|
||||
---
|
||||
|
||||
## Apps & Ports
|
||||
|
||||
| App | Package name | Purpose | Port |
|
||||
| ------------------------------ | --------------------------- | ---------------------------------------- | ---- |
|
||||
| `edr-freight-api` | `@edr/freight-api` | NestJS API for freight | 3001 |
|
||||
| `edr-freight-web/portal` | `@edr/freight-portal` | React frontend for freight customers | 5173 |
|
||||
| `edr-freight-web/backoffice` | `@edr/freight-backoffice` | React frontend for freight employees | 5183 |
|
||||
| `edr-passenger-api` | `@edr/passenger-api` | NestJS API for passengers | 3002 |
|
||||
| `edr-passenger-web/portal` | `@edr/passenger-portal` | React frontend for passenger customers | 5174 |
|
||||
| `edr-passenger-web/backoffice` | `@edr/passenger-backoffice` | React frontend for passenger employees | 5184 |
|
||||
|
||||
`edr-freight-web` and `edr-passenger-web` are grouping folders, not workspace packages. Each holds independent `portal/` and `backoffice/` workspace packages declared in `pnpm-workspace.yaml`.
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js ≥ 20
|
||||
- pnpm 9 (`corepack enable && corepack prepare pnpm@9.12.0 --activate`)
|
||||
- Docker (for local Postgres)
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Start local databases
|
||||
|
||||
```bash
|
||||
docker compose -f infrastructure/docker/docker-compose.db.dev.yml up -d
|
||||
```
|
||||
|
||||
### Run apps
|
||||
|
||||
```bash
|
||||
pnpm dev # every app
|
||||
pnpm dev:freight # freight API + portal + backoffice
|
||||
pnpm dev:passenger # passenger API + portal + backoffice
|
||||
```
|
||||
|
||||
### Common scripts
|
||||
|
||||
| Script | Description |
|
||||
| ------------------- | ------------------------------------ |
|
||||
| `pnpm install` | Install workspace dependencies |
|
||||
| `pnpm dev` | Run every app in watch mode |
|
||||
| `pnpm build` | Build every package and app |
|
||||
| `pnpm test` | Run all tests |
|
||||
| `pnpm lint` | Lint everything |
|
||||
| `pnpm type-check` | Type-check every package |
|
||||
| `pnpm format` | Format with Prettier |
|
||||
|
||||
---
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
.
|
||||
├── apps/
|
||||
│ ├── edr-freight-api/ NestJS — freight backend
|
||||
│ ├── edr-freight-web/
|
||||
│ │ ├── portal/ React — freight customer portal
|
||||
│ │ └── backoffice/ React — freight back-office
|
||||
│ ├── edr-passenger-api/ NestJS — passenger backend
|
||||
│ └── edr-passenger-web/
|
||||
│ ├── portal/ React — passenger customer portal
|
||||
│ └── backoffice/ React — passenger back-office
|
||||
├── packages/
|
||||
│ ├── api-common/ Shared NestJS utilities + BaseEntity/Repository
|
||||
│ ├── types/ Shared TS types/enums
|
||||
│ ├── ui-common/ Shared React components + theme
|
||||
│ └── config/
|
||||
│ ├── eslint/ @edr/eslint-config
|
||||
│ ├── tsconfig/ @edr/tsconfig
|
||||
│ └── prettier/ @edr/prettier-config
|
||||
├── infrastructure/
|
||||
│ ├── docker/ docker-compose files (db.dev / dev / prod)
|
||||
│ └── nginx/ Production nginx config
|
||||
├── CLAUDE.md Developer guide for AI-assisted work
|
||||
├── turbo.json Turborepo task pipeline
|
||||
├── pnpm-workspace.yaml Workspace manifest
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Standards (recap)
|
||||
|
||||
- **TypeScript strict mode** is enabled in every package.
|
||||
- **pnpm only** — never run `npm install` or `yarn`.
|
||||
- **Conventional commits** — enforced via commitlint on every commit.
|
||||
- **NestJS 4-layer pattern** — `module → controller → service → repository`.
|
||||
- **Repository injection** — services inject the custom `*Repository` class, not `Repository<T>`.
|
||||
- **Controllers are thin** — no business logic; delegate to services.
|
||||
- **Migrations only** — never enable TypeORM `synchronize` in production.
|
||||
- **One DB per domain** — no cross-database joins.
|
||||
|
||||
See [`CLAUDE.md`](./CLAUDE.md) for the deeper developer guide used during AI-assisted contributions.
|
||||
|
||||
Reference in New Issue
Block a user