FlexDelivery24 API

Backend for the FlexDelivery24 delivery platform. This repository is a NestJS + Fastify application that exposes web, mobile, admin, and public APIs on top of a MySQL database, with a large set of migrations, seeders, and domain use cases.

This README is written for new developers joining the project. It focuses on:

What You Are Looking At

The application is organized around a shared business layer and two client-facing API modules:

Core stack:

The app also has integrations for Pusher, Paystack, Twilio, Smile ID, email providers, AWS S3, and OpenAI. Some of those are feature-level, but a few are still wired as boot-time dependencies, so see the environment section carefully.

Repository Walkthrough

Top level

src/

src/
├── app.module.ts                 # Root module
├── main.ts                       # Bootstraps Fastify, Swagger, static assets, filters
├── config/                       # Env validation, app config, TypeORM config
├── database/
│   ├── migrations/               # TypeORM migrations
│   └── utils/                    # Migration helpers
├── modules/
│   ├── shared/
│   │   ├── application/          # DTOs, mappers, use cases
│   │   ├── domain/               # Domain services and contracts
│   │   ├── infrastructure/       # Repositories, entities, external providers, cron jobs
│   │   ├── common/               # Enums, decorators, utils
│   │   ├── errors/               # Custom error types
│   │   └── presentation/         # Guards, filters, interceptors, middleware
│   ├── web/                      # Web/admin/public controllers
│   └── mobile/                   # Mobile controllers
└── types/                        # Shared TS types

How a request usually flows

When you need to trace or change behavior, this is the pattern to follow:

  1. Start in a controller under src/modules/web/controllers or src/modules/mobile/controllers.
  2. Find the injected use case in src/modules/shared/application/use-cases.
  3. Follow repository or service calls into src/modules/shared/infrastructure.
  4. If persistence changed, inspect the matching entity in src/modules/shared/infrastructure/persistence/entities and migration files in src/database/migrations.

In practice:

Important routing note

There is no single central routing file for the API surface.

For that reason, when you are debugging or adding endpoints, trust controller decorators over module README files or route placeholders.

Main Entry Points

Architecture, Flow, and Data Diagrams

The diagrams below are intended to make onboarding faster. They map the current implementation, not just the intended design. For the larger schema reference, also see database-erd.md and database-design.md.

Runtime Architecture

Runtime Architecture Diagram

Feature Assembly Pattern

Feature Assembly Pattern Diagram

Request Flow: Authenticated API Request

Authenticated API Request Flow Diagram

Request Flow: Job Creation and Side Effects

Job Creation and Side Effects Flow Diagram

Entity Relationship Diagram: Identity and Access

Identity and Access ERD

Entity Relationship Diagram: Jobs and Delivery Lifecycle

Jobs and Delivery Lifecycle ERD

Entity Relationship Diagram: Finance, Reviews, and Disputes

Finance, Reviews, and Disputes ERD

Diagram Notes

Local Development Setup

1. Prerequisites

Install these first:

Why Node 24? The CI workflow uses Node 24 and this repo has no .nvmrc, so matching CI is the safest default.

This repo does not include Docker Compose files, so MySQL and Redis are expected to be running outside the repository.

2. Install dependencies

Use the same install style the CI workflow uses:

npm install --legacy-peer-deps

3. Create your environment file

The app loads environment variables from:

  1. .env.local
  2. .env

That means .env.local overrides .env when both exist.

Start with:

cp .env.example .env.local

Then add the values below. This matters because .env.example is not fully sufficient for a local boot today.

Required for local boot

These are required either by env validation or by modules that call getOrThrow(...) during startup:

NODE_ENV=development
PORT=3000
API_PREFIX=/api/v1
CORS_ORIGIN=http://localhost:3000,http://localhost:5173

DB_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=
DB_NAME=flex_delivery

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0

PUSHER_APP_ID=local
PUSHER_KEY=local
PUSHER_SECRET=local
PUSHER_CLUSTER=mt1

SMILE_ID_API_KEY=local
SMILE_ID_PARTNER_ID=local

EMAIL_PROVIDER=nodemailer
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_USER=local
SMTP_PASSWORD=local
SMTP_FROM_EMAIL=dev@flexdelivery24.local
SMTP_FROM_NAME=FlexDelivery24 Dev

JWT_SECRET=dev-jwt-secret
JWT_REFRESH_SECRET=dev-refresh-secret
DEFAULT_OTP=123456

Notes:

Optional for feature testing

Add these when you need the corresponding integrations:

4. Create the database

Create the local database before running migrations:

CREATE DATABASE flex_delivery
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

5. Run migrations

Apply the schema:

npm run migration:run

Useful related commands:

npm run migration:show
npm run migration:revert
npm run migration:run:batch

Use migration:run:batch if your machine or target environment is memory-constrained.

6. Seed local data

For the easiest local setup, use the comprehensive seeder:

npm run seed:all

This populates lookup data, users, jobs, rewards, payments, marketplace data, notifications, disputes, and more.

If you only need admin access, you can run the smaller admin seed after roles exist:

npm run seed:roles
npm run seed:admin-users

Default admin credentials created by seed-admin-users:

The seed script itself warns that these passwords should be changed after first login.

7. Start the API

For local development:

npm run start:dev

Other modes:

npm run start
npm run start:debug
npm run build
npm run start:prod

After boot, check:

Quick Start Checklist

If you want the shortest path from clone to running API:

cp .env.example .env.local
# add Redis, Pusher, Smile ID, and SMTP values to .env.local

npm install --legacy-peer-deps

# create the flex_delivery database first
npm run migration:run
npm run seed:all
npm run start:dev

Testing

Unit and integration-style specs

npm test
npm run test:watch
npm run test:cov

There are repo-level specs under src/ and E2E specs under test/.

E2E flow tests

npm run test:e2e

Important: the more realistic E2E flow in test/job-flow.e2e-spec.ts expects:

The test helpers support overriding credentials and base URL via env vars:

Example:

npm run start:dev

In another terminal:

TEST_API_URL=http://localhost:3000 npm run test:e2e -- --testPathPatterns=job-flow --verbose --forceExit

Note: test/app.e2e-spec.ts still looks like the default Nest scaffold and does not reflect the current root route behavior, so test/job-flow.e2e-spec.ts is the better reference when you want a realistic manual or automated flow.

Common Commands

npm run start:dev
npm run build
npm run lint
npm test
npm run test:e2e
npm run migration:run
npm run migration:show
npm run seed:all

Other useful one-offs:

How To Work In This Repo

When adding a new endpoint

The usual workflow is:

  1. Add or update DTOs in src/modules/shared/application/dto.
  2. Create or modify a use case in src/modules/shared/application/use-cases.
  3. Add repository or infrastructure changes under src/modules/shared/infrastructure.
  4. Expose the use case through a controller in src/modules/web/controllers and/or src/modules/mobile/controllers.
  5. Register new providers in src/modules/shared/shared.module.ts if needed.
  6. Add or update a migration if the schema changed.

When debugging persistence

Look in this order:

  1. TypeORM entity
  2. repository implementation
  3. use case
  4. migration history

When debugging routes

Look in this order:

  1. controller @Controller(...)
  2. controller method decorators like @Get, @Post, @Put
  3. guards/interceptors attached to the controller or method

Do not start with the routes/ folders; they are effectively placeholders today.

Useful Internal Docs

Some of those documents are helpful for architecture context, but the source code should be treated as the final authority where docs and implementation differ.

Known Onboarding Gotchas

First Places To Read In Code

If you are brand new to the repo, start here:

  1. src/main.ts
  2. src/app.module.ts
  3. src/modules/shared/shared.module.ts
  4. one controller you care about in src/modules/web/controllers or src/modules/mobile/controllers
  5. the related use case in src/modules/shared/application/use-cases

That path will give you the fastest mental model of how the app is put together.