178 lines
4.8 KiB
Markdown
178 lines
4.8 KiB
Markdown
|
|
# Customer Domain - Final Cleanup
|
||
|
|
|
||
|
|
## Problems Identified
|
||
|
|
|
||
|
|
### 1. Unnecessary Infra Mapper (BFF)
|
||
|
|
**Current:**
|
||
|
|
```
|
||
|
|
BFF: @prisma/client User → user.mapper.ts → domain/customer/providers/portal → UserAuth
|
||
|
|
```
|
||
|
|
|
||
|
|
**Problem:** Double mapping! BFF adapter just converts Prisma type to domain raw type, then calls domain mapper.
|
||
|
|
|
||
|
|
**Better:**
|
||
|
|
```
|
||
|
|
BFF: @prisma/client User → directly use domain/customer/providers/portal/mapper → UserAuth
|
||
|
|
```
|
||
|
|
|
||
|
|
The BFF mapper is redundant - we should use the domain mapper directly.
|
||
|
|
|
||
|
|
### 2. Unused Legacy WHMCS Types
|
||
|
|
|
||
|
|
**Never used in BFF:**
|
||
|
|
- ❌ `CustomerEmailPreferences` (0 occurrences)
|
||
|
|
- ❌ `CustomerUser` (sub-users, 0 occurrences)
|
||
|
|
- ❌ `CustomerStats` (billing stats, 0 occurrences)
|
||
|
|
- ❌ `Customer` (full WHMCS schema - only used internally in WHMCS mapper)
|
||
|
|
|
||
|
|
**Schemas for unused types:**
|
||
|
|
- ❌ `customerEmailPreferencesSchema` (~40 lines)
|
||
|
|
- ❌ `customerUserSchema` (~25 lines)
|
||
|
|
- ❌ `customerStatsSchema` (~50 lines)
|
||
|
|
- ❌ `customerSchema` (~35 lines)
|
||
|
|
|
||
|
|
**Total bloat:** ~150 lines of unused code!
|
||
|
|
|
||
|
|
### 3. Not Following Schema-First in Domain Mapper
|
||
|
|
|
||
|
|
**Current:** `packages/domain/customer/providers/portal/mapper.ts`
|
||
|
|
```typescript
|
||
|
|
// Manually constructs object - NO SCHEMA!
|
||
|
|
export function mapPrismaUserToUserAuth(raw: PrismaUserRaw): UserAuth {
|
||
|
|
return {
|
||
|
|
id: raw.id,
|
||
|
|
email: raw.email,
|
||
|
|
// ... manual construction
|
||
|
|
};
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Should be:**
|
||
|
|
```typescript
|
||
|
|
// Use schema for validation!
|
||
|
|
export function mapPrismaUserToUserAuth(raw: PrismaUserRaw): UserAuth {
|
||
|
|
return userAuthSchema.parse({
|
||
|
|
id: raw.id,
|
||
|
|
email: raw.email,
|
||
|
|
// ...
|
||
|
|
});
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Cleanup Plan
|
||
|
|
|
||
|
|
### Step 1: Remove Unused Types
|
||
|
|
|
||
|
|
**File:** `packages/domain/customer/types.ts`
|
||
|
|
|
||
|
|
Remove:
|
||
|
|
- `customerEmailPreferencesSchema` + type
|
||
|
|
- `customerUserSchema` + type
|
||
|
|
- `customerStatsSchema` + type
|
||
|
|
- `customerSchema` + type (full WHMCS schema)
|
||
|
|
- Helper functions for these types
|
||
|
|
|
||
|
|
**Keep only:**
|
||
|
|
- `userAuthSchema` → `UserAuth`
|
||
|
|
- `userSchema` → `User`
|
||
|
|
- `customerDataSchema` → `CustomerData`
|
||
|
|
- `customerAddressSchema` → `CustomerAddress`
|
||
|
|
- `addressFormSchema` → `AddressFormData`
|
||
|
|
|
||
|
|
### Step 2: Update Customer Index Exports
|
||
|
|
|
||
|
|
**File:** `packages/domain/customer/index.ts`
|
||
|
|
|
||
|
|
Remove exports:
|
||
|
|
- `CustomerEmailPreferences`
|
||
|
|
- `CustomerUser`
|
||
|
|
- `CustomerStats`
|
||
|
|
- `Customer`
|
||
|
|
- All related schemas
|
||
|
|
|
||
|
|
### Step 3: Clean WHMCS Mapper (Internal Use Only)
|
||
|
|
|
||
|
|
**File:** `packages/domain/customer/providers/whmcs/mapper.ts`
|
||
|
|
|
||
|
|
Since `Customer` type is removed, the WHMCS mapper can:
|
||
|
|
- Either define types inline (internal to mapper)
|
||
|
|
- Or export minimal `WhmcsCustomer` type just for mapper use
|
||
|
|
|
||
|
|
### Step 4: Use Schema in Portal Mapper
|
||
|
|
|
||
|
|
**File:** `packages/domain/customer/providers/portal/mapper.ts`
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { userAuthSchema } from "../../types";
|
||
|
|
import type { PrismaUserRaw } from "./types";
|
||
|
|
import type { UserAuth } from "../../types";
|
||
|
|
|
||
|
|
export function mapPrismaUserToUserAuth(raw: PrismaUserRaw): UserAuth {
|
||
|
|
return userAuthSchema.parse({
|
||
|
|
id: raw.id,
|
||
|
|
email: raw.email,
|
||
|
|
role: raw.role,
|
||
|
|
mfaEnabled: !!raw.mfaSecret,
|
||
|
|
emailVerified: raw.emailVerified,
|
||
|
|
lastLoginAt: raw.lastLoginAt?.toISOString(),
|
||
|
|
createdAt: raw.createdAt.toISOString(),
|
||
|
|
updatedAt: raw.updatedAt.toISOString(),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 5: Eliminate BFF Infra Mapper
|
||
|
|
|
||
|
|
**Delete:** `apps/bff/src/infra/mappers/user.mapper.ts`
|
||
|
|
|
||
|
|
**Update all 7 usages** to directly import from domain:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// OLD (double mapping - BAD!)
|
||
|
|
import { mapPrismaUserToDomain } from "@bff/infra/mappers";
|
||
|
|
const userAuth = mapPrismaUserToDomain(prismaUser);
|
||
|
|
|
||
|
|
// NEW (direct - GOOD!)
|
||
|
|
import { mapPrismaUserToUserAuth } from "@customer-portal/domain/customer/providers/portal";
|
||
|
|
const userAuth = mapPrismaUserToUserAuth(prismaUser);
|
||
|
|
```
|
||
|
|
|
||
|
|
Files to update (7 total):
|
||
|
|
1. `apps/bff/src/modules/auth/presentation/strategies/jwt.strategy.ts`
|
||
|
|
2. `apps/bff/src/modules/auth/infra/workflows/workflows/whmcs-link-workflow.service.ts`
|
||
|
|
3. `apps/bff/src/modules/auth/infra/workflows/workflows/signup-workflow.service.ts`
|
||
|
|
4. `apps/bff/src/modules/auth/infra/workflows/workflows/password-workflow.service.ts`
|
||
|
|
5. `apps/bff/src/modules/auth/infra/token/token.service.ts`
|
||
|
|
6. `apps/bff/src/modules/auth/application/auth.facade.ts`
|
||
|
|
7. Any other imports of `mapPrismaUserToDomain`
|
||
|
|
|
||
|
|
## Result
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
- 342 lines in types.ts (lots of unused code)
|
||
|
|
- BFF infra mapper (unnecessary layer)
|
||
|
|
- Manual object construction (no schema validation)
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
- ~190 lines in types.ts (lean, only what's used)
|
||
|
|
- Direct domain mapper usage (proper architecture)
|
||
|
|
- Schema-validated mapping (type safe + runtime safe)
|
||
|
|
|
||
|
|
**Types kept:**
|
||
|
|
```typescript
|
||
|
|
// User entity types
|
||
|
|
User // Complete user
|
||
|
|
UserAuth // Auth state
|
||
|
|
UserRole // Role enum
|
||
|
|
|
||
|
|
// Address
|
||
|
|
CustomerAddress // Address structure
|
||
|
|
AddressFormData // Form validation
|
||
|
|
|
||
|
|
// Profile data (internal)
|
||
|
|
CustomerData // WHMCS profile fields
|
||
|
|
```
|
||
|
|
|
||
|
|
**Clean, minimal, schema-first! 🎯**
|
||
|
|
|