- Changed TypeScript target and library settings in tsconfig files to align with ESNext standards. - Updated pnpm version in GitHub workflows for better dependency management. - Modified Dockerfile to reflect the updated pnpm version. - Adjusted import statements across various domain modules to include file extensions for consistency and compatibility. - Cleaned up TypeScript configuration files for improved clarity and organization.
134 lines
3.9 KiB
TypeScript
134 lines
3.9 KiB
TypeScript
/**
|
|
* ID Mapping Domain - Validation
|
|
*
|
|
* Pure business validation functions for ID mappings.
|
|
* These functions contain no infrastructure dependencies (no DB, no HTTP, no logging).
|
|
*/
|
|
|
|
import { z } from "zod";
|
|
import {
|
|
createMappingRequestSchema,
|
|
updateMappingRequestSchema,
|
|
userIdMappingSchema,
|
|
} from "./schema.js";
|
|
import type {
|
|
CreateMappingRequest,
|
|
UpdateMappingRequest,
|
|
UserIdMapping,
|
|
MappingValidationResult,
|
|
} from "./contract.js";
|
|
|
|
/**
|
|
* Check if a mapping request has optional Salesforce account ID
|
|
* This is used for warnings, not validation errors
|
|
*/
|
|
export function checkMappingCompleteness(request: CreateMappingRequest | UserIdMapping): string[] {
|
|
const warnings: string[] = [];
|
|
if (!request.sfAccountId) {
|
|
warnings.push("Salesforce account ID not provided - mapping will be incomplete");
|
|
}
|
|
return warnings;
|
|
}
|
|
|
|
/**
|
|
* Validate no conflicts exist with existing mappings
|
|
* Business rule: Each userId, whmcsClientId should be unique
|
|
*
|
|
* Note: This assumes the request has already been validated by schema.
|
|
* Use createMappingRequestSchema.parse() before calling this function.
|
|
*/
|
|
export function validateNoConflicts(
|
|
request: CreateMappingRequest,
|
|
existingMappings: UserIdMapping[]
|
|
): MappingValidationResult {
|
|
const errors: string[] = [];
|
|
const warnings: string[] = [];
|
|
|
|
// Check for conflicts
|
|
const duplicateUser = existingMappings.find(m => m.userId === request.userId);
|
|
if (duplicateUser) {
|
|
errors.push(`User ${request.userId} already has a mapping`);
|
|
}
|
|
|
|
const duplicateWhmcs = existingMappings.find(m => m.whmcsClientId === request.whmcsClientId);
|
|
if (duplicateWhmcs) {
|
|
errors.push(
|
|
`WHMCS client ${request.whmcsClientId} is already mapped to user ${duplicateWhmcs.userId}`
|
|
);
|
|
}
|
|
|
|
if (request.sfAccountId) {
|
|
const duplicateSf = existingMappings.find(m => m.sfAccountId === request.sfAccountId);
|
|
if (duplicateSf) {
|
|
warnings.push(
|
|
`Salesforce account ${request.sfAccountId} is already mapped to user ${duplicateSf.userId}`
|
|
);
|
|
}
|
|
}
|
|
|
|
return { isValid: errors.length === 0, errors, warnings };
|
|
}
|
|
|
|
/**
|
|
* Validate deletion constraints
|
|
* Business rule: Warn about data access impacts
|
|
*
|
|
* Note: This assumes the mapping has already been validated.
|
|
* This function adds business warnings about the impact of deletion.
|
|
*/
|
|
export function validateDeletion(mapping: UserIdMapping | null | undefined): MappingValidationResult {
|
|
const errors: string[] = [];
|
|
const warnings: string[] = [];
|
|
|
|
if (!mapping) {
|
|
errors.push("Cannot delete non-existent mapping");
|
|
return { isValid: false, errors, warnings };
|
|
}
|
|
|
|
warnings.push(
|
|
"Deleting this mapping will prevent access to WHMCS/Salesforce data for this user"
|
|
);
|
|
if (mapping.sfAccountId) {
|
|
warnings.push(
|
|
"This mapping includes Salesforce integration - deletion will affect case management"
|
|
);
|
|
}
|
|
|
|
return { isValid: true, errors, warnings };
|
|
}
|
|
|
|
/**
|
|
* Sanitize and normalize a create mapping request
|
|
*
|
|
* Note: This performs basic string trimming before validation.
|
|
* The schema handles validation; this is purely for data cleanup.
|
|
*/
|
|
export function sanitizeCreateRequest(request: CreateMappingRequest): CreateMappingRequest {
|
|
return {
|
|
userId: request.userId?.trim(),
|
|
whmcsClientId: request.whmcsClientId,
|
|
sfAccountId: request.sfAccountId?.trim() || undefined,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sanitize and normalize an update mapping request
|
|
*
|
|
* Note: This performs basic string trimming before validation.
|
|
* The schema handles validation; this is purely for data cleanup.
|
|
*/
|
|
export function sanitizeUpdateRequest(request: UpdateMappingRequest): UpdateMappingRequest {
|
|
const sanitized: Partial<UpdateMappingRequest> = {};
|
|
|
|
if (request.whmcsClientId !== undefined) {
|
|
sanitized.whmcsClientId = request.whmcsClientId;
|
|
}
|
|
|
|
if (request.sfAccountId !== undefined) {
|
|
sanitized.sfAccountId = request.sfAccountId?.trim() || undefined;
|
|
}
|
|
|
|
return sanitized;
|
|
}
|
|
|