@tldraw/utils 4.2.0-next.f100cedfc45b → 4.3.0-canary.d8da2a99f394
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/object.js.map +2 -2
- package/dist-cjs/lib/retry.js +1 -1
- package/dist-cjs/lib/retry.js.map +2 -2
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/object.mjs.map +2 -2
- package/dist-esm/lib/retry.mjs +1 -1
- package/dist-esm/lib/retry.mjs.map +2 -2
- package/package.json +1 -1
- package/src/lib/object.ts +4 -4
- package/src/lib/retry.ts +2 -2
package/dist-cjs/index.js
CHANGED
|
@@ -168,7 +168,7 @@ var import_version2 = require("./lib/version");
|
|
|
168
168
|
var import_warn = require("./lib/warn");
|
|
169
169
|
(0, import_version.registerTldrawLibraryVersion)(
|
|
170
170
|
"@tldraw/utils",
|
|
171
|
-
"4.
|
|
171
|
+
"4.3.0-canary.d8da2a99f394",
|
|
172
172
|
"cjs"
|
|
173
173
|
);
|
|
174
174
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/object.ts"],
|
|
4
|
-
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<[Key, Value]> {\n\treturn Object.entries(object) as [Key, Value][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,
|
|
4
|
+
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["isEqualWith"]
|
|
7
7
|
}
|
package/dist-cjs/lib/retry.js
CHANGED
|
@@ -32,7 +32,7 @@ async function retry(fn, {
|
|
|
32
32
|
for (let i = 0; i < attempts; i++) {
|
|
33
33
|
if (abortSignal?.aborted) throw new Error("aborted");
|
|
34
34
|
try {
|
|
35
|
-
return await fn();
|
|
35
|
+
return await fn({ attempt: i, remaining: attempts - i, total: attempts });
|
|
36
36
|
} catch (e) {
|
|
37
37
|
if (matchError && !matchError(e)) throw e;
|
|
38
38
|
error = e;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/retry.ts"],
|
|
4
|
-
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: () => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn()\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAsB;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG;AAAA,
|
|
4
|
+
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAsB;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,gBAAM,sBAAM,YAAY;AAAA,IACzB;AAAA,EACD;AACA,QAAM;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/index.mjs
CHANGED
|
@@ -101,7 +101,7 @@ import { registerTldrawLibraryVersion as registerTldrawLibraryVersion2 } from ".
|
|
|
101
101
|
import { warnDeprecatedGetter, warnOnce } from "./lib/warn.mjs";
|
|
102
102
|
registerTldrawLibraryVersion(
|
|
103
103
|
"@tldraw/utils",
|
|
104
|
-
"4.
|
|
104
|
+
"4.3.0-canary.d8da2a99f394",
|
|
105
105
|
"esm"
|
|
106
106
|
);
|
|
107
107
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/object.ts"],
|
|
4
|
-
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<[Key, Value]> {\n\treturn Object.entries(object) as [Key, Value][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,iBAAiB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,
|
|
4
|
+
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/lib/retry.mjs
CHANGED
|
@@ -9,7 +9,7 @@ async function retry(fn, {
|
|
|
9
9
|
for (let i = 0; i < attempts; i++) {
|
|
10
10
|
if (abortSignal?.aborted) throw new Error("aborted");
|
|
11
11
|
try {
|
|
12
|
-
return await fn();
|
|
12
|
+
return await fn({ attempt: i, remaining: attempts - i, total: attempts });
|
|
13
13
|
} catch (e) {
|
|
14
14
|
if (matchError && !matchError(e)) throw e;
|
|
15
15
|
error = e;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/retry.ts"],
|
|
4
|
-
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: () => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn()\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,aAAa;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG;AAAA,
|
|
4
|
+
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,aAAa;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,YAAM,MAAM,YAAY;AAAA,IACzB;AAAA,EACD;AACA,QAAM;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
package/src/lib/object.ts
CHANGED
|
@@ -108,10 +108,10 @@ export function objectMapValues<Key extends string, Value>(object: {
|
|
|
108
108
|
* ```
|
|
109
109
|
* @internal
|
|
110
110
|
*/
|
|
111
|
-
export function objectMapEntries<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return Object.entries(object) as [
|
|
111
|
+
export function objectMapEntries<Obj extends object>(
|
|
112
|
+
object: Obj
|
|
113
|
+
): Array<[keyof Obj, Obj[keyof Obj]]> {
|
|
114
|
+
return Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
/**
|
package/src/lib/retry.ts
CHANGED
|
@@ -48,7 +48,7 @@ import { sleep } from './control'
|
|
|
48
48
|
* @internal
|
|
49
49
|
*/
|
|
50
50
|
export async function retry<T>(
|
|
51
|
-
fn: () => Promise<T>,
|
|
51
|
+
fn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,
|
|
52
52
|
{
|
|
53
53
|
attempts = 3,
|
|
54
54
|
waitDuration = 1000,
|
|
@@ -65,7 +65,7 @@ export async function retry<T>(
|
|
|
65
65
|
for (let i = 0; i < attempts; i++) {
|
|
66
66
|
if (abortSignal?.aborted) throw new Error('aborted')
|
|
67
67
|
try {
|
|
68
|
-
return await fn()
|
|
68
|
+
return await fn({ attempt: i, remaining: attempts - i, total: attempts })
|
|
69
69
|
} catch (e) {
|
|
70
70
|
if (matchError && !matchError(e)) throw e
|
|
71
71
|
error = e
|