# EDR Platform — Developer Guide

## Overview

Monorepo for the Ethio Djibouti Railway (EDR) digital platform. Contains the Freight Management and Passenger Management applications, plus shared types, NestJS utilities, and React component libraries.

## Apps

| App                            | Package name                | Purpose                                            | Port |
| ------------------------------ | --------------------------- | -------------------------------------------------- | ---- |
| `edr-freight-api`              | `@edr/freight-api`          | NestJS API for freight management                  | 3001 |
| `edr-freight-web/portal`       | `@edr/freight-portal`       | React frontend for freight customer/portal users   | 5173 |
| `edr-freight-web/backoffice`   | `@edr/freight-backoffice`   | React frontend for freight backoffice employees    | 5183 |
| `edr-passenger-api`            | `@edr/passenger-api`        | NestJS API for passenger management                | 3002 |
| `edr-payment-api`              | `@edr/payment-api`          | NestJS payment microservice (intents, webhooks)    | 3003 |
| `edr-passenger-web/portal`     | `@edr/passenger-portal`     | React frontend for passenger customer/portal users | 5174 |
| `edr-passenger-web/backoffice` | `@edr/passenger-backoffice` | React frontend for passenger backoffice employees  | 5184 |

`edr-freight-web` and `edr-passenger-web` are grouping folders, not workspace packages. Each holds a `portal/` and `backoffice/` sub-app, both of which are independent pnpm workspace packages (declared in `pnpm-workspace.yaml`). The existing `pnpm dev:freight` / `pnpm dev:passenger` turbo filters (`@edr/freight-*` / `@edr/passenger-*`) cover all four web apps + their APIs.

## Packages

| Package                | Purpose                                                                            |
| ---------------------- | ---------------------------------------------------------------------------------- |
| `@edr/types`           | Shared TypeScript interfaces and enums                                             |
| `@edr/api-common`      | Shared NestJS decorators, filters, interceptors, pipes, BaseEntity, BaseRepository |
| `@edr/ui-common`       | Shared React components and theme                                                  |
| `@edr/eslint-config`   | Shared ESLint configurations (base/nestjs/react)                                   |
| `@edr/tsconfig`        | Shared TypeScript configurations                                                   |
| `@edr/prettier-config` | Shared Prettier configuration                                                      |

## Commands

| Command              | Description                        |
| -------------------- | ---------------------------------- |
| `pnpm install`       | Install all workspace dependencies |
| `pnpm dev`           | Run every app in dev mode          |
| `pnpm dev:freight`   | Run only freight API + web         |
| `pnpm dev:passenger` | Run only passenger API + web       |
| `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 all files with Prettier     |

## Standards

- **TypeScript strict mode** is enabled in every package and app.
- **pnpm** is the only supported package manager — never run `npm install` or `yarn`.
- **Conventional commits** are enforced via commitlint on every commit.
- **NestJS modules** follow the 4-layer pattern: `module → controller → service → repository` (entities and DTOs live alongside).
- **All entities** use UUID primary keys (`@PrimaryGeneratedColumn('uuid')`).
- **All entities** have `createdAt`, `updatedAt`, `deletedAt` (soft delete) via `@edr/api-common`'s `BaseEntity`.
- **All columns** use `snake_case` in the database (`@Column({ name: 'snake_case' })`); TypeScript properties use `camelCase`.
- **Never use `synchronize: true`** in production database config. All schema changes go through TypeORM migrations.
- **ESLint + Prettier** run on pre-commit via Husky + lint-staged.
- **Services** never inject TypeORM `Repository<T>` directly — they inject the custom repository class.
- **Controllers** never contain business logic.

## Auth

Authentication is handled by an external package (`@edr/iamui-common` or equivalent) that will be integrated later. **Do not** implement any auth, login, logout, JWT verification, password hashing, or user management code in this repo.

When auth integration is needed, use placeholder TODO comments:

- `// @UseGuards(JwtAuthGuard) — TODO: integrate @edr/auth`
- `// TODO: integrate @edr/auth — replace stub @CurrentUser with real one`

The `@CurrentUser`, `@Roles`, and `@Public` decorators in `@edr/api-common` are bare metadata setters with no guard wiring — they exist so controllers can be annotated correctly without depending on auth infrastructure yet.

## Port Assignments

- `edr-freight-api`: 3001
- `edr-freight-web/portal`: 5173
- `edr-freight-web/backoffice`: 5183
- `edr-passenger-api`: 3002
- `edr-payment-api`: 3003
- `edr-passenger-web/portal`: 5174
- `edr-passenger-web/backoffice`: 5184

## Database Layout

- `postgres-freight` (port 5433): database `edr_freight` — freight API only.
- `postgres-passenger` (port 5434): database `edr_passenger` — passenger API only.
- `edr_payment` schema — lives in the same Postgres database as the domain system (whatever the passenger `DATABASE_URL` points at) but is owned exclusively by `apps/edr-payment-api`. Dedicated DB user, no cross-schema FKs, domain apps have no grants on it (see `docs/payment-service/`).
- Each app owns its own DB. No cross-database joins; cross-domain data flows through API calls or message queues.

## Adding a new module to a NestJS app

1. Create `modules/<feature>/` with `entities/`, `dto/`, and the four `<feature>.{module,controller,service,repository}.ts` files.
2. The entity extends `BaseEntity` from `@edr/api-common`.
3. The repository extends `BaseRepository<Entity>` from `@edr/api-common`.
4. The service injects the repository class (not `Repository<T>` directly).
5. The controller uses `@ApiTags()` + `@ApiOperation()` for Swagger.
6. Register the module in the app's `app.module.ts`.

## Adding a new shared component to `@edr/ui-common`

1. Create `src/components/<Name>/<Name>.tsx` and `src/components/<Name>/index.ts`.
2. Export from `src/index.ts`.
3. Component is a functional component with a `ComponentNameProps` interface (named-exported alongside the default).
