Skip to content

AI Prompt: Forma3D.Connect — Phase 5s: Prisma Decoupling from Domain

Purpose: This prompt instructs an AI to remove Prisma imports from domain contracts
Estimated Effort: 4-6 hours
Prerequisites: Phase 5r completed (Metadata Types)
Output: Domain layer fully decoupled from Prisma/database types
Status: 🟡 PENDING


🎯 Mission

You are implementing Phase 5s: Prisma Decoupling — addressing TD-017 (Direct Prisma Import in Domain Contracts) from the technical debt register.

Why This Matters:

Domain contracts importing from @prisma/client causes:

  1. Tight Database Coupling: Domain layer depends on database implementation
  2. Testing Difficulty: Tests need Prisma types even for pure domain logic
  3. Refactoring Risk: Database changes ripple through domain
  4. Architecture Violation: Domain should be infrastructure-agnostic

Phase 5s delivers:

  • Domain-owned enum definitions
  • Mapping layer between Prisma and domain types
  • Clean separation of concerns

📋 Context: Technical Debt Item

TD-017: Direct Prisma Import in Domain Contracts

Attribute Value
Type Architecture Debt
Priority Medium
Location libs/domain-contracts/src/lib/types.ts
Interest Rate Medium
Principal (Effort) 4-6 hours

Current Problem

// libs/domain-contracts/src/lib/types.ts
import { OrderStatus, PrintJobStatus, ShipmentStatus } from '@prisma/client';

🛠️ Implementation

Phase 1: Create Domain Enums (1 hour)

Create libs/domain/src/enums/:

// order-status.enum.ts
export enum OrderStatus {
  PENDING = 'PENDING',
  PROCESSING = 'PROCESSING',
  PRINTING = 'PRINTING',
  PRINTED = 'PRINTED',
  SHIPPING = 'SHIPPING',
  SHIPPED = 'SHIPPED',
  DELIVERED = 'DELIVERED',
  CANCELLED = 'CANCELLED',
}

// print-job-status.enum.ts
export enum PrintJobStatus {
  PENDING = 'PENDING',
  QUEUED = 'QUEUED',
  PRINTING = 'PRINTING',
  COMPLETED = 'COMPLETED',
  FAILED = 'FAILED',
  CANCELLED = 'CANCELLED',
}

// shipment-status.enum.ts
export enum ShipmentStatus {
  PENDING = 'PENDING',
  LABEL_CREATED = 'LABEL_CREATED',
  SHIPPED = 'SHIPPED',
  IN_TRANSIT = 'IN_TRANSIT',
  DELIVERED = 'DELIVERED',
  FAILED = 'FAILED',
}

Phase 2: Create Type Mappers (1.5 hours)

Create apps/api/src/database/mappers/:

// status-mapper.ts
import { OrderStatus as PrismaOrderStatus } from '@prisma/client';
import { OrderStatus as DomainOrderStatus } from '@forma3d/domain';

export function toDomainOrderStatus(prisma: PrismaOrderStatus): DomainOrderStatus {
  return prisma as DomainOrderStatus;
}

export function toPrismaOrderStatus(domain: DomainOrderStatus): PrismaOrderStatus {
  return domain as PrismaOrderStatus;
}

Phase 3: Update Domain Contracts (1.5 hours)

Replace Prisma imports:

// Before
import { OrderStatus } from '@prisma/client';

// After
import { OrderStatus } from '@forma3d/domain';

Phase 4: Update Repositories (2 hours)

Add mapping at repository boundaries:

async findById(id: string): Promise<Order | null> {
  const prismaOrder = await this.prisma.order.findUnique({ where: { id } });
  return prismaOrder ? this.toDomain(prismaOrder) : null;
}

private toDomain(prisma: PrismaOrder): Order {
  return {
    ...prisma,
    status: toDomainOrderStatus(prisma.status),
  };
}

📁 Files to Create/Modify

New Files

libs/domain/src/enums/order-status.enum.ts
libs/domain/src/enums/print-job-status.enum.ts
libs/domain/src/enums/shipment-status.enum.ts
libs/domain/src/enums/index.ts
apps/api/src/database/mappers/status-mapper.ts

Modified Files

libs/domain-contracts/src/lib/types.ts
All repository files

✅ Validation Checklist

  • Domain enums created
  • Prisma imports removed from domain-contracts
  • Mappers implemented
  • Repositories use mappers
  • pnpm nx build passes
  • pnpm nx test passes

END OF PROMPT


This prompt resolves TD-017 from the technical debt register.