moderndash
Advanced tools
Comparing version 0.6.0 to 0.6.1
@@ -502,2 +502,54 @@ /** | ||
/** | ||
* Similar to [Promise.race](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race?retiredLocale=de) | ||
* but allows to specify how many promises to wait for. | ||
* | ||
* @example | ||
* const promise1 = Promise.resolve(1); | ||
* const promise2 = Promise.resolve(2); | ||
* const promise2 = Promise.resolve(3); | ||
* | ||
* const firstThree = await races(3, promise1, promise2, promise3); | ||
* // => [1, 2, 3] | ||
* @template TRes - The type of the result of the promises. | ||
* @param waitFor - The number of promises to wait for. | ||
* @param promises - The promises to wait for. | ||
* @returns A promise that resolves an array of the results of the first n promises. | ||
*/ | ||
declare function races<TRes>(waitFor: number, ...promises: Promise<TRes>[]): Promise<TRes[]>; | ||
/** | ||
* Retry a function until it succeeds or the maximum number of retries is reached. | ||
* | ||
* Default maxRetries: `5`. | ||
* Default backoff: `2^retries * 100ms` (100, 200, 400, 800, 1600, 3200, ...) | ||
* | ||
* @example | ||
* await retry(() => fetch('https://example.com')); | ||
* | ||
* // ---- Advanced example ---- | ||
* const fetchSite = async (url: string) => { | ||
* const response = await fetch(url); | ||
* response.ok || throw new Error('Failed to fetch'); | ||
* } | ||
* | ||
* const logger = (error: unknown, retry?: number) => console.log("Retrying", retry, error); | ||
* | ||
* await retry(() => fetchSite('https://example.com'), { maxRetries: 3, backoff: retries => retries * 1000, onRetry: logger })); | ||
* // => Will retry 3 times with a 1 second delay between each retry. Will log the error and retry number. | ||
* | ||
* @param func The function to retry. | ||
* @param options The options for the retry. | ||
* @param options.maxRetries The maximum number of retries. Defaults to `5`. | ||
* @param options.backoff The backoff function to use. Defaults to `2^retries * 100`. | ||
* @param options.onRetry The function to call when a retry is attempted. | ||
* @template TRes The type of the result of the function. | ||
* @returns A promise that resolves when the function succeeds. | ||
*/ | ||
declare function retry<TRes>(func: () => Promise<TRes>, options?: { | ||
maxRetries?: number; | ||
backoff?: ((retries: number) => number); | ||
onRetry: (error?: unknown, retry?: number) => void; | ||
}): Promise<TRes>; | ||
/** | ||
* Sleeps for the given amount of time. | ||
@@ -686,3 +738,3 @@ * | ||
* @example | ||
* stripSpecialChars('Héllo! World #$%&*!') | ||
* stripSpecial('Héllo! World #$%&*!') | ||
* // => 'Hello World' | ||
@@ -709,77 +761,2 @@ * @category String | ||
/** | ||
* A `number` that is an integer. | ||
* You can't pass a `bigint` as they are already guaranteed to be integers. | ||
* | ||
* Use-case: Validating and documenting parameters. Other usage is limited. | ||
* | ||
* *Note: Check this [writeup](https://github.com/sindresorhus/type-fest/issues/334#issuecomment-987787840) for more details.* | ||
* @example | ||
* function setYear<T extends number>(x: Integer<T>){}; | ||
* | ||
* setYear(1); // OK | ||
* setYear(1.1); // Error | ||
* @category type | ||
*/ | ||
type Int<T extends number> = `${T}` extends `${bigint}` ? T : never; | ||
/** | ||
* A `number` that is not an integer. | ||
* You can't pass a `bigint` as they are already guaranteed to be integers. | ||
* | ||
* Use-case: Validating and documenting parameters. Other usage is limited. | ||
* | ||
* *Note: Check this [writeup](https://github.com/sindresorhus/type-fest/issues/334#issuecomment-987787840) for more details.* | ||
* @example | ||
* function setPercentage<T extends number>(x: Float<T>) {}; | ||
* | ||
* setPercentage(1.1); // OK | ||
* setPercentage(1); // Error | ||
* @category type | ||
*/ | ||
type Float<T extends number> = T extends Int<T> ? never : T; | ||
/** | ||
* A negative `number`/`bigint` (`-∞ < x < 0`) | ||
* | ||
* Use-case: Validating and documenting parameters. Other usage is limited. | ||
* | ||
* *Note: Check this [writeup](https://github.com/sindresorhus/type-fest/issues/334#issuecomment-987787840) for more details.* | ||
* @example | ||
* function setNegative<T extends number>(x: Negative<T>) {}; | ||
* | ||
* setNegative(-1.2); // OK | ||
* setNegative(1); // Error | ||
* | ||
* function setNegInt<T extends number>(x: Negative<Int<T>>) {}; | ||
* | ||
* setNegInt(-1); // OK | ||
* setNegInt(1); // Error | ||
* setNegInt(-1.1); // Error | ||
* @category type | ||
*/ | ||
type Negative<T extends number | bigint> = T extends 0 | 0n ? never : `${T}` extends `-${string}` ? T : never; | ||
/** | ||
* A positive `number`/`bigint` (`0 < x < ∞`). | ||
* | ||
* Use-case: Validating and documenting parameters. Other usage is limited. | ||
* | ||
* *Note: Check this [writeup](https://github.com/sindresorhus/type-fest/issues/334#issuecomment-987787840) for more details.* | ||
* @example | ||
* function setPositive<T extends number>(x: Positive<T>) {}; | ||
* | ||
* setPositive(1.2); // OK | ||
* setPositive(-1); // Error | ||
* | ||
* function setPosInt<T extends number>(x: Positive<Int<T>>) {}; | ||
* | ||
* setPosInt(1); // OK | ||
* setPosInt(-1); // Error | ||
* setPosInt(1.1); // Error | ||
* | ||
* @category type | ||
*/ | ||
type Positive<T extends number | bigint> = T extends 0 | 0n ? never : Negative<T> extends never ? T : never; | ||
/** | ||
* Checks if `value` is an empty object, collection, map, or set. | ||
@@ -837,7 +814,7 @@ * | ||
* @category Validate | ||
* @param value1 - The value to compare. | ||
* @param value2 - The other value to compare. | ||
* @param a - The value to compare. | ||
* @param b - The other value to compare. | ||
* @returns Returns `true` if the values are equivalent, else `false`. | ||
*/ | ||
declare function isEqual(value1: unknown, value2: unknown): boolean; | ||
declare function isEqual(a: unknown, b: unknown): boolean; | ||
@@ -859,2 +836,2 @@ declare function isPlainObject(value: unknown): value is object; | ||
export { Float, Int, Negative, Positive, Queue, after, before, camelCase, capitalize, chunk, count, dashCase, debounce, deburr, difference, dropRightWhile, dropWhile, escapeHtml, escapeRegExp, group, intersection, isEmpty, isEqual, isPlainObject, isUrl, kebabCase, memoize, omit, once, pascalCase, pick, sample, shuffle, sleep, snakeCase, sort, startCase, stripSpecial, takeRightWhile, takeWhile, throttle, timeout, times, unescapeHtml, unique }; | ||
export { Queue, after, before, camelCase, capitalize, chunk, count, dashCase, debounce, deburr, difference, dropRightWhile, dropWhile, escapeHtml, escapeRegExp, group, intersection, isEmpty, isEqual, isPlainObject, isUrl, kebabCase, memoize, omit, once, pascalCase, pick, races, retry, sample, shuffle, sleep, snakeCase, sort, startCase, stripSpecial, takeRightWhile, takeWhile, throttle, timeout, times, unescapeHtml, unique }; |
@@ -31,14 +31,17 @@ // src/array/chunk.ts | ||
// src/validate/isEqual.ts | ||
function isEqual(value1, value2) { | ||
if (value1 === value2) | ||
function isEqual(a, b) { | ||
if (Object.is(a, b)) | ||
return true; | ||
if (Array.isArray(value1) && Array.isArray(value2)) { | ||
return isSameArray(value1, value2); | ||
if (a instanceof Date && b instanceof Date) { | ||
return a.getTime() === b.getTime(); | ||
} | ||
if (value1 instanceof RegExp && value2 instanceof RegExp) { | ||
return value1.toString() === value2.toString(); | ||
if (Array.isArray(a) && Array.isArray(b)) { | ||
return isSameArray(a, b); | ||
} | ||
if (isObject(value1) && isObject(value2)) { | ||
return isSameObject(value1, value2); | ||
if (a instanceof RegExp && b instanceof RegExp) { | ||
return a.toString() === b.toString(); | ||
} | ||
if (isObject(a) && isObject(b)) { | ||
return isSameObject(a, b); | ||
} | ||
return false; | ||
@@ -435,2 +438,23 @@ } | ||
// src/promise/races.ts | ||
function races(waitFor, ...promises) { | ||
return new Promise((resolve, reject) => { | ||
if (promises.length < waitFor) | ||
waitFor = promises.length; | ||
const results = []; | ||
let resolved = 0; | ||
for (const promise of promises) { | ||
promise.then((value) => { | ||
results.push(value); | ||
resolved++; | ||
if (resolved >= waitFor) { | ||
resolve(results); | ||
} | ||
}).catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
}); | ||
} | ||
// src/promise/sleep.ts | ||
@@ -441,2 +465,27 @@ function sleep(ms) { | ||
// src/promise/retry.ts | ||
async function retry(func, options) { | ||
const backOffFn = options?.backoff ?? ((retries2) => 2 ** retries2 * 100); | ||
const maxRetries = options?.maxRetries ?? 5; | ||
const onRetry = options?.onRetry ?? (() => { | ||
}); | ||
let retries = 0; | ||
let lastError; | ||
while (retries <= maxRetries) { | ||
try { | ||
if (retries > 0) | ||
onRetry(lastError, retries); | ||
return await func(); | ||
} catch (error) { | ||
lastError = error; | ||
retries++; | ||
if (retries > maxRetries) { | ||
throw error; | ||
} | ||
await sleep(backOffFn(retries)); | ||
} | ||
} | ||
throw new Error("Retry terminated without success, this should never happen"); | ||
} | ||
// src/promise/timeout.ts | ||
@@ -639,2 +688,4 @@ function timeout(promise, timeout2) { | ||
pick, | ||
races, | ||
retry, | ||
sample, | ||
@@ -641,0 +692,0 @@ shuffle, |
@@ -51,3 +51,3 @@ { | ||
}, | ||
"version": "0.6.0" | ||
"version": "0.6.1" | ||
} |
@@ -36,6 +36,2 @@ ![ModernDash Logo](/website/src/assets/moderndashLogo.svg) | ||
Please check [You-Dont-Need-Lodash](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore) for native replacements. | ||
If you still think a function is missing please open an issue. | ||
## Thank you | ||
- [type-fest](https://github.com/sindresorhus/type-fest) for the numeric types | ||
If you still think a function is missing please open an issue. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
189672
2172
36