import type { SafeParseReturnType } from "zod"; import { ServiceError, type ServiceErrorParams } from "../errors/serviceError"; import { type Either, type Left, type Right } from "./either"; export interface Success { readonly isSuccess: true; readonly value: A; } export interface Failure { readonly isSuccess: false; readonly error: E; } export type SuccessResult = Right & Success; export type FailureResult = Left & Failure; /** * Represents the result of a service operation that may fail. * * The type is also an {@link Either}, allowing functions built for {@link Either}. * * @template A The type of the successful result value * @template E The type of the failed result error */ export type ServiceResult = SuccessResult | FailureResult; /** * Creates a successful ServiceResult. * * Call with no argument for a `ServiceResult`; the value is `undefined`. */ export declare function success(): ServiceResult; export declare function success(value: A): ServiceResult; /** * Creates a failed ServiceResult. */ export declare function failure(error: E): FailureResult; export declare function failure(params: ServiceErrorParams): FailureResult; /** * Type guard for failure results. */ export declare function isFailure(result: ServiceResult): result is FailureResult; /** * Type guard for success results. */ export declare function isSuccess(result: ServiceResult): result is SuccessResult; /** * Alias for {@link mapLeft}. * Note: returns an {@link Either}, not a ServiceResult. */ export declare function mapFailure(f: (left: E) => G): (result: ServiceResult) => Either; /** * Converts a promise returning function into a ServiceResult by handling potential rejections. * If the promise returning function resolves successfully, returns a success ServiceResult. * If the promise rejects, calls the onError function to convert the error into a ServiceError. * * @template A The type of the value the promise resolves to * @param f Function returning a Promise to execute. Passing a function allows catching synchronous throws * @param onError Maps unknown errors to a ServiceError * @returns A promise that resolves to a ServiceResult * * @example * * * ```ts * import { ok, strictEqual } from "node:assert/strict"; * * import { isFailure, isSuccess, ServiceError, tryCatchAsync } from "@clipboard-health/util-ts"; * * async function example() { * const successResult = await tryCatchAsync( * async () => { * const response = await fetch("https://jsonplaceholder.typicode.com/posts/1"); * return (await response.json()) as { id: number }; * }, * (error) => new ServiceError(`Failed to fetch: ${String(error)}`), * ); * * ok(isSuccess(successResult)); * strictEqual(successResult.value.id, 1); * * const failureResult = await tryCatchAsync( * async () => await Promise.reject(new Error("Network error")), * (error) => new ServiceError(`Failed to fetch: ${String(error)}`), * ); * * ok(isFailure(failureResult)); * strictEqual(failureResult.error.issues[0]?.message, "Failed to fetch: Error: Network error"); * } * * // eslint-disable-next-line unicorn/prefer-top-level-await * void example(); * ``` * * */ export declare function tryCatchAsync(f: () => Promise, onError: (error: unknown) => ServiceError): Promise>; /** * Wraps a synchronous function that might throw into a ServiceResult. * If the function executes successfully, returns a success ServiceResult. * If the function throws, calls the onError function to convert the error into a ServiceError. * * @template A The return type of the function * @param f The function to execute safely * @param onError Function to convert unknown errors into ServiceError * @returns A ServiceResult * * @example * * * ```ts * import { ok, strictEqual } from "node:assert/strict"; * * import { isFailure, isSuccess, parseJson, ServiceError, tryCatch } from "@clipboard-health/util-ts"; * * const successResult = tryCatch( * () => parseJson<{ name: string }>('{"name": "John"}'), * (error) => new ServiceError(`Parse error: ${String(error)}`), * ); * * ok(isSuccess(successResult)); * strictEqual(successResult.value.name, "John"); * * const failureResult = tryCatch( * () => parseJson("invalid json"), * (error) => new ServiceError(`Parse error: ${String(error)}`), * ); * * ok(isFailure(failureResult)); * ok(failureResult.error.issues[0]?.message?.includes("Parse error") === true); * ``` * * */ export declare function tryCatch(f: () => A, onError: (error: unknown) => ServiceError): ServiceResult; /** * Converts a Zod SafeParseReturnType into a ServiceResult. * If the parse was successful, returns a success ServiceResult with the parsed data. * If the parse failed, returns a failure ServiceResult with the validation errors. * * @template A The type of the successfully parsed value * @param value The SafeParseReturnType from a Zod schema parse * @returns A ServiceResult * * @example * * * ```ts * import { ok, strictEqual } from "node:assert/strict"; * * import { fromSafeParseReturnType, isFailure, isSuccess } from "@clipboard-health/util-ts"; * import { z } from "zod"; * * const schema = z.object({ name: z.string(), age: z.number() }); * * const validData = { name: "John", age: 30 }; * const successResult = fromSafeParseReturnType(schema.safeParse(validData)); * * ok(isSuccess(successResult)); * strictEqual(successResult.value.name, "John"); * * const invalidData = { name: "John", age: "thirty" }; * const failureResult = fromSafeParseReturnType(schema.safeParse(invalidData)); * * ok(isFailure(failureResult)); * ok(failureResult.error.issues.length > 0); * ``` * * */ export declare function fromSafeParseReturnType(value: SafeParseReturnType): ServiceResult;