6.7 KiB
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/iam-seed |
IAM baseline seeder for the apps sharing the iam schema (freight + passenger) |
@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 installoryarn. - 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'sBaseEntity. - All columns use
snake_casein the database (@Column({ name: 'snake_case' })); TypeScript properties usecamelCase. - Never use
synchronize: truein 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: 3001edr-freight-web/portal: 5173edr-freight-web/backoffice: 5183edr-passenger-api: 3002edr-payment-api: 3003edr-passenger-web/portal: 5174edr-passenger-web/backoffice: 5184
Database Layout
postgres-freight(port 5433): databaseedr_freight— freight API only.postgres-passenger(port 5434): databaseedr_passenger— passenger API only.edr_paymentschema — lives in the same Postgres database as the domain system (whatever the passengerDATABASE_URLpoints at) but is owned exclusively byapps/edr-payment-api. Dedicated DB user, no cross-schema FKs, domain apps have no grants on it (seedocs/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
- Create
modules/<feature>/withentities/,dto/, and the four<feature>.{module,controller,service,repository}.tsfiles. - The entity extends
BaseEntityfrom@edr/api-common. - The repository extends
BaseRepository<Entity>from@edr/api-common. - The service injects the repository class (not
Repository<T>directly). - The controller uses
@ApiTags()+@ApiOperation()for Swagger. - Register the module in the app's
app.module.ts.
Adding a new shared component to @edr/ui-common
- Create
src/components/<Name>/<Name>.tsxandsrc/components/<Name>/index.ts. - Export from
src/index.ts. - Component is a functional component with a
ComponentNamePropsinterface (named-exported alongside the default).