summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/foundation/util/promise-util.js215
1 files changed, 215 insertions, 0 deletions
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<T> 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