Files
notification-elements-demo/node_modules/p-retry/index.js
Giuliano Silvestro 5d0c9ec7eb Initial commit: notification-elements-demo app
Interactive Angular 19 demo for @sda/notification-elements-ui with
6 sections: Bell & Feed, Notification Center, Inbox, Comments &
Threads, Mention Input, and Full-Featured layout. Includes mock
data, dark mode toggle, and real-time event log.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 21:49:19 +10:00

93 lines
2.2 KiB
JavaScript

import retry from 'retry';
import isNetworkError from 'is-network-error';
export class AbortError extends Error {
constructor(message) {
super();
if (message instanceof Error) {
this.originalError = message;
({message} = message);
} else {
this.originalError = new Error(message);
this.originalError.stack = this.stack;
}
this.name = 'AbortError';
this.message = message;
}
}
const decorateErrorWithCounts = (error, attemptNumber, options) => {
// Minus 1 from attemptNumber because the first attempt does not count as a retry
const retriesLeft = options.retries - (attemptNumber - 1);
error.attemptNumber = attemptNumber;
error.retriesLeft = retriesLeft;
return error;
};
export default async function pRetry(input, options) {
return new Promise((resolve, reject) => {
options = {...options};
options.onFailedAttempt ??= () => {};
options.shouldRetry ??= () => true;
options.retries ??= 10;
const operation = retry.operation(options);
const abortHandler = () => {
operation.stop();
reject(options.signal?.reason);
};
if (options.signal && !options.signal.aborted) {
options.signal.addEventListener('abort', abortHandler, {once: true});
}
const cleanUp = () => {
options.signal?.removeEventListener('abort', abortHandler);
operation.stop();
};
operation.attempt(async attemptNumber => {
try {
const result = await input(attemptNumber);
cleanUp();
resolve(result);
} catch (error) {
try {
if (!(error instanceof Error)) {
throw new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`);
}
if (error instanceof AbortError) {
throw error.originalError;
}
if (error instanceof TypeError && !isNetworkError(error)) {
throw error;
}
decorateErrorWithCounts(error, attemptNumber, options);
if (!(await options.shouldRetry(error))) {
operation.stop();
reject(error);
}
await options.onFailedAttempt(error);
if (!operation.retry(error)) {
throw operation.mainError();
}
} catch (finalError) {
decorateErrorWithCounts(finalError, attemptNumber, options);
cleanUp();
reject(finalError);
}
}
});
});
}