@synet/patterns
Version:
Robust, battle-tested collection of stable patterns used in Synet packages
107 lines (106 loc) • 3.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResultCombinators = exports.ResultExtensions = void 0;
const result_1 = require("../patterns/result");
/**
* Extensions for the Result pattern following the Open/Closed Principle.
* These add functionality without modifying the core Result class.
*/
exports.ResultExtensions = {
/**
* Maps error from one Result type to another, preserving error details
*
* @example
* const emailResult = Email.create(input);
* if (emailResult.isFailure) {
* return ResultExtensions.mapError<Email, User>(emailResult);
* }
*/
mapError(result) {
if (result.isSuccess) {
throw new Error("Cannot map error from a successful result");
}
return result_1.Result.fail(result.errorMessage ?? "Unknown error occurred", result.errorCause);
},
/**
* Maps a successful result value to a different type
*
* @example
* const userResult = User.create({ name: "John" });
* const userDtoResult = ResultExtensions.mapSuccess(userResult, user => UserDto.fromUser(user));
*/
mapSuccess(result, mapper) {
if (result.isFailure) {
return exports.ResultExtensions.mapError(result);
}
try {
const mappedValue = mapper(result.value);
return result_1.Result.success(mappedValue);
}
catch (error) {
return result_1.Result.fail(`Error mapping result: ${error instanceof Error ? error.message : String(error)}`);
}
},
/**
* Chains multiple results together, short-circuiting on first failure
*
* @example
* const finalResult = ResultExtensions.chain(
* () => validateInput(input),
* (validInput) => processInput(validInput),
* (processedData) => saveToDatabase(processedData)
* );
*/
chain(result, fn) {
if (result.isFailure) {
return exports.ResultExtensions.mapError(result);
}
try {
return fn(result.value);
}
catch (error) {
return result_1.Result.fail(`Error in result chain: ${error instanceof Error ? error.message : String(error)}`);
}
},
};
/**
* Additional useful Result transformations and combinations
*/
exports.ResultCombinators = {
/**
* Returns first success result or combines all error messages
*
* @example
* const result = ResultCombinators.any([
* primaryValidator(input),
* fallbackValidator(input)
* ]);
*/
any(results) {
const successes = results.filter((r) => r.isSuccess);
if (successes.length > 0) {
return successes[0];
}
const errorMessage = results
.filter((r) => r.isFailure && r.errorMessage)
.map((r) => r.errorMessage)
.join("; ");
return result_1.Result.fail(errorMessage || "All operations failed");
},
/**
* Collects all successful results or returns first failure
*
* @example
* const usersResult = ResultCombinators.all(
* userIds.map(id => userRepository.getById(id))
* );
*/
all(results) {
const failures = results.filter((r) => r.isFailure);
if (failures.length > 0) {
return exports.ResultExtensions.mapError(failures[0]);
}
const values = results.map((r) => r.value);
return result_1.Result.success(values);
},
};