# 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` 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//` with `entities/`, `dto/`, and the four `.{module,controller,service,repository}.ts` files. 2. The entity extends `BaseEntity` from `@edr/api-common`. 3. The repository extends `BaseRepository` from `@edr/api-common`. 4. The service injects the repository class (not `Repository` 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//.tsx` and `src/components//index.ts`. 2. Export from `src/index.ts`. 3. Component is a functional component with a `ComponentNameProps` interface (named-exported alongside the default).