70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
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<void, DomainError>
|
|
* - Mutation maps DomainError → MutationError
|
|
* - Mutation returns Result<void, MutationError>
|
|
* - 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<UpdateUserStatusInput, void> {
|
|
* async execute(input: UpdateUserStatusInput): Promise<Result<void, MutationError>> {
|
|
* 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<TInput = void, TOutput = void, TError = string> {
|
|
/**
|
|
* 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<Result<TOutput, TError>>
|
|
*/
|
|
execute(input: TInput): Promise<Result<TOutput, TError>>;
|
|
} |