From bce557cc2dc767628bed6aac87301a1be7c5431b Mon Sep 17 00:00:00 2001 From: rxliuli Date: Tue, 4 Nov 2025 05:03:50 +0800 Subject: init commit --- .../tmp/src/foundation/util/promise-util.js | 215 +++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js (limited to 'node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js') diff --git a/node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js b/node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js new file mode 100644 index 0000000..d661559 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js @@ -0,0 +1,215 @@ +/** + * This module provides enhanced promise handling capabilities beyond native JavaScript Promises. + * It focuses on distinguishing between required and optional promises, standardizing results, + * and simplifying error handling for complex async operations. + */ +/** + * Symbol used to uniquely identify PromiseResult objects. + * This allows for reliable type checking. + */ +export const PROMISE_RESULT_SYMBOL = Symbol("PromiseResult"); +/** + * Type guard to check if a value is a PromiseResult. + * + * @param value - The value to check + * @returns True if the value is a PromiseResult, false otherwise + */ +function isPromiseResult(value) { + return value !== null && typeof value === "object" && PROMISE_RESULT_SYMBOL in value; +} +/** + * Custom error class that aggregates multiple promise failures. + * Provides access to all underlying errors while presenting a combined error message. + */ +export class MultiPromiseError extends Error { + constructor(reasons) { + super(errorMessageForReasons(reasons)); + this.reasons = reasons; + this.reasons = reasons; + } +} +/** + * Helper function to create a standardized fulfilled result object. + * Ensures the result has the PROMISE_RESULT_SYMBOL for type checking. + * + * @param value - The value to wrap in a fulfilled result + * @returns A standardized fulfilled result object + */ +export function makeFulfilledResult(value) { + return { + success: true, + value, + error: null, + [PROMISE_RESULT_SYMBOL]: true, + }; +} +/** + * Helper function to create a standardized rejected result object. + * Ensures the result has the PROMISE_RESULT_SYMBOL for type checking. + * + * @param error - The error to wrap in a rejected result + * @returns A standardized rejected result object + */ +export function makeRejectedResult(error) { + const normalizedError = error instanceof Error ? error : new Error(String(error)); + return { + success: false, + value: null, + error: normalizedError, + [PROMISE_RESULT_SYMBOL]: true, + }; +} +/** + * Custom error class that indicates that a required promise failed. + */ +export class RequiredPromiseError extends Error { + constructor(reason) { + super(reason.message); + this.reason = reason; + this.reason = reason; + } +} +/** + * Transforms a promise into one that never throws, instead returning a standardized result. + * Use this for optional operations that shouldn't cause the overall process to fail. + * This is a convenience alias for tryAwait with a more semantic name. + * + * @param promise - The promise to make optional + * @returns A promise that resolves to a PromiseResult instead of throwing + */ +export async function optional(promise) { + return await tryAwait(promise); +} +/** + * Marks a promise as required (will throw on rejection). + * This is mainly for code clarity as regular promises are already required by default. + * + * @param promise - The promise to mark as required + * @returns The original promise (identity function) + */ +export async function required(promise) { + return await promise; +} +/** + * Executes a mix of required and optional promises, returning standardized results. + * Regular promises are treated as required and will cause this function to throw if they fail. + * Promises wrapped with optional() will never cause this function to throw. + * + * This implementation handles both regular promises and promises that resolve to PromiseResult. + * + * @param promises - Array of promises (both required and optional) + * @returns Promise resolving to an array of standardized results + * @throws Original error if a single required promise fails + * @throws MultiPromiseError if multiple required promises fail + * @note For homogeneous promise arrays, prefer using more specific functions: + * - Use allRequired() when all promises should be treated as required + * - Use allOptional() when all promises should be treated as optional + * - Only use allMixed() when you need to combine both required and optional promises + */ +export async function allMixed(promises) { + // Process each promise + const results = await Promise.all(promises.map(async (promise) => { + try { + const value = await promise; + // If it's a PromiseResult (from optional()/tryAwait), use it directly + if (isPromiseResult(value)) { + // Handle the case where T is already a PromiseResult + // This fixes the double-wrapping issue when all promises are optional + return value; + } + else { + // It's a regular promise that succeeded + return makeFulfilledResult(value); + } + } + catch (error) { + // This was a required promise that failed + return makeRejectedResult(error instanceof Error ? error : new Error(String(error))); + } + })); + const requiredFailures = []; + results.forEach((result) => { + if (!result.success) { + requiredFailures.push(result.error); + } + }); + // If any required promises failed, throw an error + if (requiredFailures.length > 0) { + if (requiredFailures.length === 1) { + throw requiredFailures[0]; + } + else { + throw new MultiPromiseError(requiredFailures); + } + } + return results; +} +/** + * Executes all promises and returns their values. + * All promises are treated as required and will cause this function to throw if any fail. + * + * @param promises - Array of promises + * @returns Promise resolving to an array of values + * @throws Original error if a single promise fails + * @throws MultiPromiseError if multiple promises fail + */ +export async function allRequired(promises) { + return await Promise.all(promises); +} +/** + * Makes all promises optional and then executes them, returning standardized results. + * This function is specifically designed for cases where you want all promises to be treated as optional. + * It avoids the double-wrapping issue that can occur when using allMixed with arrays of optional promises. + * + * @param promises - Array of promises to make optional + * @returns Promise resolving to an array of standardized results + * @example + * ``` + * const promises = urls.map(fetchData); + * const results = await allOptional(promises); + * // Each result is a PromiseResult that won't cause the overall operation to fail + * ``` + */ +export async function allOptional(promises) { + // Use Promise.all with optional() for each promise + return await Promise.all(promises.map(optional)); +} +/** + * Creates an error message from multiple rejection reasons. + * Formats multiple error reasons into a single error message string, + * handling both Error objects and other rejection values. + * + * @param reasons - Array of error reasons that caused promise rejections + * @returns Concatenated error message string + */ +function errorMessageForReasons(reasons) { + return reasons + .map((reason) => { + if (reason instanceof Error) { + return reason.message; + } + else { + return JSON.stringify(reason); + } + }) + .join(""); +} +/** + * Safely awaits a promise and returns a standardized result object. + * Eliminates the need for repetitive try/catch blocks throughout the codebase. + * + * @param promiseOrFn - Either a promise or a function that returns a promise + * @returns A standardized PromiseResult object indicating success or failure + */ +export async function tryAwait(promiseOrFn) { + try { + // Handle both promise and function that returns a promise + const promise = typeof promiseOrFn === "function" ? promiseOrFn() : promiseOrFn; + const value = await promise; + return makeFulfilledResult(value); + } + catch (error) { + return makeRejectedResult(error); + } +} +//# sourceMappingURL=promise-util.js.map \ No newline at end of file -- cgit v1.2.3