import { Result } from "../Result"; /** * Mutation Contract * * Purpose: Framework-agnostic write operations * * Architecture: * - Server Action constructs Mutation * - Mutation constructs Service * - Service creates own dependencies (API Client, Logger, ErrorReporter) * - Service returns Result * - Mutation maps DomainError → MutationError * - Mutation returns Result * - No HTTP/API calls directly * - No 'use client' directive * - No 'use server' directive * - Must be in lib/mutations/ * - Must be named *Mutation * - Can be called from Server Actions * - Single responsibility: ONE operation per mutation * * Pattern: * Server Action → Mutation → Service → API Client * * Example: * ```typescript * export class UpdateUserStatusMutation implements Mutation { * async execute(input: UpdateUserStatusInput): Promise> { * const service = new UserService(); * const result = await service.updateUserStatus(input.userId, input.status); * * if (result.isErr()) { * return Result.err(mapToMutationError(result.error)); * } * * return Result.ok(undefined); * } * } * ``` * * Design Principle: * Each mutation does ONE thing. If you need multiple operations, * create multiple mutation classes (e.g., UpdateUserStatusMutation, DeleteUserMutation). * This follows the same pattern as Page Queries. * * @template TInput - The input type for the mutation * @template TOutput - The output type on success * @template TError - The error type (default: string for backward compatibility) */ export interface Mutation { /** * Execute the mutation * * Manual construction pattern: * ```typescript * const service = new MyService(); * const result = await service.doWrite(input); * if (result.isErr()) { * return Result.err(mapToMutationError(result.error)); * } * return Result.ok(undefined); * ``` * * @param input - Mutation input * @returns Promise> */ execute(input: TInput): Promise>; }