rich-domain
Version:
This package provide utils file and interfaces to assistant build a complex application with domain driving design
168 lines • 6.39 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Combine = exports.Result = void 0;
const iterator_1 = require("./iterator");
/**
* @description The `Result` class represents the outcome of an operation, encapsulating both the success or failure state.
* A `Result` instance can contain a payload (`data`), an error, and optional metadata for additional context.
* This pattern encourages explicit handling of operation success or failure, making your code more robust and expressive.
*
* @typeParam T - The type of the payload when the result is successful.
* @typeParam D - The type of the error when the result is a failure. Defaults to `string`.
* @typeParam M - The type of the metadata object. Defaults to an empty object `{}`.
*
* @example
* ```typescript
* // Creating a success result with data
* const successResult = Result.Ok({ name: "Alice" });
* if (successResult.isOk()) {
* console.log("Success data:", successResult.value());
* }
*
* // Creating a failure result with a custom error message
* const failResult = Result.fail("An error occurred");
* if (failResult.isFail()) {
* console.error("Error:", failResult.error());
* }
* ```
*/
class Result {
#isOk;
#isFail;
#data;
#error;
#metaData;
constructor(isSuccess, data, error, metaData) {
this.#isOk = isSuccess;
this.#isFail = !isSuccess;
this.#data = data ?? null;
this.#error = error ?? null;
this.#metaData = metaData ?? {};
}
static Ok(data, metaData) {
const _data = typeof data === 'undefined' ? null : data;
const ok = new Result(true, _data, null, metaData);
return Object.freeze(ok);
}
static fail(error, metaData) {
const _error = (typeof error !== 'undefined' && error !== null) ? error : 'void error. no message!';
const fail = new Result(false, null, _error, metaData);
return Object.freeze(fail);
}
/**
* @description Creates an iterator over a collection of `Result` instances. This allows sequential processing of multiple results.
* @param results An array of `Result` instances.
* @returns An iterator over the provided results.
*/
static iterate(results) {
return iterator_1.default.create({ initialData: results, returnCurrentOnReversion: true });
}
/**
* @description Combines multiple `Result` instances into a single `Result`.
* If any of the provided results is a failure, the combined `Result` is a failure.
* If all results are successful, the combined `Result` is considered a success.
*
* @param results An array of `Result` instances to combine.
* @returns A `Result` instance representing the combined outcome.
*/
static combine(results) {
const iterator = Result.iterate(results);
if (iterator.isEmpty())
return Result.fail('No results provided on combine param');
while (iterator.hasNext()) {
const currentResult = iterator.next();
if (currentResult.isFail())
return currentResult;
}
return iterator.first();
}
/**
* @description Executes a command based on the result state. You can specify whether the command executes on success, failure, or both.
* Optionally, you can provide data to the command if required.
*
* @param command An object implementing `ICommand` interface.
* @returns An object with methods to configure command execution based on the `Result` state.
*/
execute(command) {
return {
on: (option) => {
if (option === 'Ok' && this.isOk())
return command.execute();
if (option === 'fail' && this.isFail())
return command.execute();
},
withData: (data) => {
return {
on: (option) => {
if (option === 'Ok' && this.isOk())
return command.execute(data);
if (option === 'fail' && this.isFail())
return command.execute(data);
}
};
}
};
}
/**
* @description Retrieves the payload of the `Result`. If the `Result` is a failure, `value()` returns `null`.
* @returns The payload `T` or `null` if the result is a failure.
*/
value() {
return this.#data;
}
/**
* @description Retrieves the error of the `Result`. If the `Result` is a success, `error()` returns `null`.
* @returns The error `D` or `null` if the result is a success.
*/
error() {
return this.#error;
}
/**
* @description Determines if the `Result` represents a failure state.
* @returns `true` if the result is a failure, `false` if it is a success.
*/
isFail() {
return this.#isFail;
}
/**
* @description Checks if the `Result` payload is `null`.
* This can be useful for confirming the presence or absence of a value before proceeding.
* @returns `true` if the payload is `null`, `false` otherwise.
*/
isNull() {
return this.#data === null || this.#isFail;
}
/**
* @description Determines if the `Result` represents a success state.
* @returns `true` if the result is a success, `false` if it is a failure.
*/
isOk() {
return this.#isOk;
}
/**
* @description Retrieves the metadata associated with the `Result`.
* @returns The metadata object `M`, or `{}` if no metadata was provided.
*/
metaData() {
const metaData = this.#metaData;
return Object.freeze(metaData);
}
/**
* @description Converts the `Result` instance into a plain object for easier logging or serialization.
* @returns An object containing `isOk`, `isFail`, `data`, `error`, and `metaData`.
*/
toObject() {
const metaData = {
isOk: this.#isOk,
isFail: this.#isFail,
data: this.#data,
error: this.#error,
metaData: this.#metaData
};
return Object.freeze(metaData);
}
}
exports.Result = Result;
exports.default = Result;
exports.Combine = Result.combine;
//# sourceMappingURL=result.js.map