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:
- Tight Database Coupling: Domain layer depends on database implementation
- Testing Difficulty: Tests need Prisma types even for pure domain logic
- Refactoring Risk: Database changes ripple through domain
- 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 buildpasses -
pnpm nx testpasses
END OF PROMPT
This prompt resolves TD-017 from the technical debt register.