Skip to content
Strata v1.2.6

Backend

The Strata backend follows Hexagonal Architecture (Ports & Adapters) with four strict layers.

ComponentTechnologyPurpose
RuntimeNode.js 24Server runtime
FrameworkNestJS 11HTTP framework, DI container, decorators
LanguageTypeScript 5End-to-end type safety
ORMPrisma 7Schema-first, type-safe DB access + migrations
DatabaseSQLite via better-sqlite3Embedded, zero-server, portable DB file
Validationclass-validator + class-transformerDTO validation at the HTTP boundary
API Docs@nestjs/swaggerAuto-generated OpenAPI / Swagger UI
TestingJest + SupertestUnit (224) + E2E (44) tests
backend/src/
├── domain/ ← Pure TypeScript — no framework imports
│ ├── entities/ ← Business entities (Asset, AssetSnapshot, PortfolioSnapshot, Category, Tag, AssetType)
│ ├── ports/ ← Repository interfaces (abstract classes)
│ └── exceptions/ ← Domain-specific exceptions
├── application/ ← Use cases as @Injectable() services
│ └── services/ ← AssetService, AssetSnapshotService, PortfolioSnapshotService, CategoryService, TagService, AssetTypeService
├── infrastructure/ ← Framework & persistence implementations
│ ├── prisma/ ← PrismaService, PrismaModule
│ └── repositories/ ← Prisma repository implementations
└── presentation/ ← HTTP layer
├── controllers/ ← NestJS @Controller() with Swagger decorators
├── dto/ ← Request DTOs (class-validator)
│ └── responses/ ← Response DTOs (@ApiProperty)
└── filters/ ← Domain exception → HTTP error mapping
LayerCan ImportCannot Import
DomainNothing (pure TypeScript)NestJS, Prisma, any framework
ApplicationDomainInfrastructure, Presentation
InfrastructureDomain, ApplicationPresentation
PresentationDomain, ApplicationInfrastructure (via DI)

NestJS modules wire abstract ports to concrete implementations:

app.module.ts
{
provide: IAssetRepository, // abstract class (port)
useClass: PrismaAssetRepository, // concrete implementation
}

Controllers receive services via constructor injection. Services receive repository ports via constructor injection. The DI container resolves the full dependency graph.

Backend HTTP requests pass through RequestIdMiddleware.

  • If the client sends X-Request-ID, Strata reuses it.
  • Otherwise, Strata generates one (UUID).
  • The ID is attached to the request context and echoed in response headers.
  • Error filters include this ID in JSON error payloads for easier debugging.

This enables end-to-end correlation across browser logs, API logs, and error responses.

flowchart TD
    A[HTTP Request] --> B[Presentation Layer\nController + DTO]
    B --> C[Application Layer\nService / Use Case]
    C --> D[Domain Layer\nEntities + Ports]
    D --> E[Infrastructure Layer\nPrisma Repository]
    E --> F[(SQLite Database)]
Terminal window
cd backend
npm install
npx prisma migrate deploy
npx prisma db seed # Only needed on first run — loads demo data
npm run start:dev # http://localhost:3000
  • API: http://localhost:3000/api/v1
  • Swagger UI: http://localhost:3000/swagger
  • Tests: npm test (unit) · npm run test:e2e (E2E)