
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A collection of lightweight, type-safe utility functions for TypeScript.
bun add iamfns
abbreviateNumberFormats large numbers with K, M, B, T suffixes for better readability.
function abbreviateNumber(n: number): number | string
Parameters:
n - The number to abbreviateReturns: The original number if < 1000, otherwise a string with suffix (K, M, B, T)
Example:
import { abbreviateNumber } from 'iamfns';
// Numbers < 1000 return as-is
abbreviateNumber(500); // => 500
abbreviateNumber(999); // => 999
// Thousands (K)
abbreviateNumber(1000); // => '1k'
abbreviateNumber(1500); // => '1.5k'
abbreviateNumber(50000); // => '50k'
// Millions (M)
abbreviateNumber(1000000); // => '1m'
abbreviateNumber(1500000); // => '1.5m'
// Billions (B)
abbreviateNumber(1000000000); // => '1b'
abbreviateNumber(1500000000); // => '1.5b'
// Trillions (T)
abbreviateNumber(1000000000000); // => '1t'
// Negative numbers
abbreviateNumber(-1500); // => '-1.5k'
abbreviateNumber(-1000000); // => '-1m'
afterDecimalsReturns the number of digits after the decimal point. Handles integers, floats, string inputs, and scientific notation.
function afterDecimals(num: number | string): number
Parameters:
num - A number or string representation of a numberReturns: The count of digits after the decimal point
Example:
import { afterDecimals } from 'iamfns';
// Integers return 0
afterDecimals(5); // => 0
afterDecimals(100); // => 0
// Floats return decimal count
afterDecimals(5.25); // => 2
afterDecimals(3.14159); // => 5
// String inputs
afterDecimals('5.25'); // => 2
afterDecimals('0.00001'); // => 5
// Scientific notation
afterDecimals(1e-5); // => 5
afterDecimals(1.23e-7); // => 7
adjustRounds a value to the nearest step increment. Useful for price/quantity adjustments.
function adjust(value: number, step: number | string): number
Parameters:
value - The number to adjuststep - The step increment (e.g., 0.01 for cents)Returns: The value rounded to the nearest step
Example:
import { adjust } from 'iamfns';
adjust(10.123, 0.1); // => 10.1
adjust(10.123, 0.01); // => 10.12
adjust(10.126, 0.01); // => 10.13
adjust(10.6, 1); // => 11
adjust(10.4, 1); // => 10
// String step values
adjust(10.123, '0.1'); // => 10.1
addAdds two numbers with correct decimal precision, avoiding floating point errors.
function add(a: number, b: number): number
Parameters:
a - First numberb - Second numberReturns: The sum with correct precision
Example:
import { add } from 'iamfns';
// Native JS: 0.1 + 0.2 = 0.30000000000000004
add(0.1, 0.2); // => 0.3
add(0.01, 0.02); // => 0.03
add(0.3, 0.6); // => 0.9
add(1, 0.001); // => 1.001
calcPercentCalculates the percentage change between two values.
function calcPercent({ now, start }: { now: number; start: number }): number
Parameters:
now - The current valuestart - The starting/reference valueReturns: The percentage change (positive for increase, negative for decrease)
Example:
import { calcPercent } from 'iamfns';
// Positive change (50% increase)
calcPercent({ now: 150, start: 100 }); // => 50
// Negative change (50% decrease)
calcPercent({ now: 50, start: 100 }); // => -50
// No change
calcPercent({ now: 100, start: 100 }); // => 0
// Both zero
calcPercent({ now: 0, start: 0 }); // => 0
// Division by zero (start is 0)
calcPercent({ now: 100, start: 0 }); // => Infinity
// Decimal values
calcPercent({ now: 1.5, start: 1 }); // => 50
calcVolatilityCalculates the volatility (standard deviation of percentage changes) for a series of values. Useful for measuring price fluctuations in financial data.
function calcVolatility(values: number[]): number
Parameters:
values - An array of numeric values (e.g., prices over time)Returns: The volatility as standard deviation of percentage changes
Example:
import { calcVolatility } from 'iamfns';
// Varying changes = higher volatility
calcVolatility([100, 110, 100]); // => ~13.49
// Price series with fluctuations
calcVolatility([100, 105, 102, 108, 106, 110]); // => > 0
// Consistent percentage changes = no volatility
calcVolatility([100, 200, 400]); // => 0 (doubling each time)
// Constant values = no volatility
calcVolatility([100, 100, 100]); // => 0
// Need at least 3 values for meaningful result
calcVolatility([100, 110]); // => 0
calcVolatility([100]); // => 0
subtractSubtracts two numbers with correct decimal precision, avoiding floating point errors.
function subtract(a: number, b: number): number
Parameters:
a - Number to subtract fromb - Number to subtractReturns: The difference with correct precision
Example:
import { subtract } from 'iamfns';
// Native JS: 0.3 - 0.1 = 0.19999999999999998
subtract(0.3, 0.1); // => 0.2
subtract(0.03, 0.01); // => 0.02
subtract(2, 0.001); // => 1.999
subtract(0.1, 0.3); // => -0.2
multiplyMultiplies two numbers with correct decimal precision, avoiding floating point errors.
function multiply(a: number, b: number): number
Parameters:
a - First numberb - Second numberReturns: The product with correct precision
Example:
import { multiply } from 'iamfns';
// Native JS: 0.1 * 0.2 = 0.020000000000000004
multiply(0.1, 0.2); // => 0.02
multiply(0.3, 0.3); // => 0.09
multiply(10, 0.123); // => 1.23
multiply(2, 0.5); // => 1
divideDivides two numbers with correct decimal precision, avoiding floating point errors.
function divide(a: number, b: number): number
Parameters:
a - Dividendb - DivisorReturns: The quotient with correct precision
Example:
import { divide } from 'iamfns';
divide(0.3, 0.1); // => 3
divide(0.12, 0.1); // => 1.2
divide(1, 0.5); // => 2
divide(10.123, 10); // => 1.012
genIdGenerates a random 16-character alphanumeric ID using base-36 encoding.
function genId(): string
Returns: A 16-character string containing lowercase letters (a-z) and digits (0-9)
Example:
import { genId } from 'iamfns';
genId(); // => 'k7x2m9p1q4w8e3r6'
genId(); // => 'a1b2c3d4e5f6g7h8'
genId(); // => 'z9y8x7w6v5u4t3s2'
// Use for unique identifiers
const userId = genId();
const sessionId = genId();
genIntIdGenerates a random integer ID between 0 and 999,999.
function genIntId(): number
Returns: A random integer from 0 to 999,999
Example:
import { genIntId } from 'iamfns';
genIntId(); // => 482957
genIntId(); // => 139482
genIntId(); // => 7234
parseEnvNumberParses an environment variable string into a positive integer, with a safe fallback for invalid input.
function parseEnvNumber(value: string | undefined, fallback: number): number
Parameters:
value - The environment value to parsefallback - Value returned when input is missing, invalid, or not a positive integerReturns: A positive integer parsed from value, or fallback
Example:
import { parseEnvNumber } from 'iamfns';
// Valid positive integers
parseEnvNumber('3000', 8080); // => 3000
parseEnvNumber('42', 10); // => 42
// Invalid or non-positive inputs use fallback
parseEnvNumber(undefined, 8080); // => 8080
parseEnvNumber('', 8080); // => 8080
parseEnvNumber('0', 8080); // => 8080
parseEnvNumber('-5', 8080); // => 8080
parseEnvNumber('abc', 8080); // => 8080
pFloatParses a number from a string with support for comma decimal separators (European format). Returns NaN for undefined or invalid input.
function pFloat(value?: number | string): number
Parameters:
value - A number or string to parse (optional)Returns: The parsed number, or NaN if invalid/undefined
Example:
import { pFloat } from 'iamfns';
// Numbers pass through
pFloat(42); // => 42
pFloat(3.14); // => 3.14
// Standard decimal strings
pFloat('42'); // => 42
pFloat('3.14'); // => 3.14
// European format (comma as decimal separator)
pFloat('3,14'); // => 3.14
pFloat('10,50'); // => 10.5
// Handles undefined safely
pFloat(undefined); // => NaN
// Invalid strings
pFloat('invalid'); // => NaN
pFloat(''); // => NaN
// Scientific notation
pFloat('1e6'); // => 1000000
pFloat('2.5e3'); // => 2500
roundDecimalsRounds a number to a specified number of decimal places.
function roundDecimals(num: number, decimals: number = 8): number
Parameters:
num - The number to rounddecimals - The number of decimal places (default: 8)Returns: The rounded number
Example:
import { roundDecimals } from 'iamfns';
// Round to integer
roundDecimals(3.14, 0); // => 3
roundDecimals(3.5, 0); // => 4
// Round to 1 decimal
roundDecimals(3.14, 1); // => 3.1
roundDecimals(3.15, 1); // => 3.2
// Round to 2 decimals
roundDecimals(3.14159, 2); // => 3.14
roundDecimals(3.145, 2); // => 3.15
// Round to many decimals
roundDecimals(3.14159265359, 4); // => 3.1416
// Handles floating point issues
roundDecimals(0.1 + 0.2, 1); // => 0.3
// Negative numbers
roundDecimals(-3.14, 1); // => -3.1
chunkSplits an array into chunks of a specified size.
function chunk<T>(arr: T[], size: number): T[][]
Parameters:
arr - The array to splitsize - The size of each chunkReturns: A new array of chunks
Example:
import { chunk } from 'iamfns';
chunk([1, 2, 3, 4, 5], 2);
// => [[1, 2], [3, 4], [5]]
chunk(['a', 'b', 'c', 'd'], 3);
// => [['a', 'b', 'c'], ['d']]
chunk([1, 2, 3, 4, 5, 6], 2);
// => [[1, 2], [3, 4], [5, 6]]
lastReturns the last element of an array.
function last<T>(array: T[]): T | undefined
Parameters:
array - The source arrayReturns: The last element, or undefined if the array is empty
Example:
import { last } from 'iamfns';
last([1, 2, 3]); // => 3
last(['a', 'b', 'c']); // => 'c'
last([42]); // => 42
last([]); // => undefined
orderBySorts an array by one or more criteria with configurable sort orders. Supports property keys and custom iteratee functions.
function orderBy<T>(
arr: T[],
iteratees?: Array<keyof T | ((item: T) => any)>,
orders?: Array<'asc' | 'desc'>
): T[]
Parameters:
arr - The array to sortiteratees - Array of property keys or functions to sort by (defaults to identity)orders - Array of sort directions: 'asc' or 'desc' (defaults to 'asc')Returns: A new sorted array
Example:
import { orderBy } from 'iamfns';
const users = [
{ name: 'Charlie', age: 30 },
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 35 }
];
// Sort by name ascending
orderBy(users, ['name'], ['asc']);
// => [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 35 }, { name: 'Charlie', age: 30 }]
// Sort by age descending
orderBy(users, ['age'], ['desc']);
// => [{ name: 'Bob', age: 35 }, { name: 'Charlie', age: 30 }, { name: 'Alice', age: 25 }]
// Sort by multiple criteria
orderBy(users, ['age', 'name'], ['desc', 'asc']);
// Sort primitives (uses identity by default)
orderBy([3, 1, 2]);
// => [1, 2, 3]
// Sort with custom iteratee function
const words = ['apple', 'pear', 'banana', 'kiwi'];
orderBy(words, [(w) => w.length], ['desc']);
// => ['banana', 'apple', 'pear', 'kiwi']
// Mix property keys and functions
const items = [
{ name: 'aa', value: 2 },
{ name: 'a', value: 1 },
{ name: 'aaa', value: 1 }
];
orderBy(items, [(u) => u.name.length, 'value'], ['asc', 'desc']);
takeReturns the first n elements from an array.
function take<T>(array: T[], n: number): T[]
Parameters:
array - The source arrayn - The number of elements to takeReturns: A new array with the first n elements
Example:
import { take } from 'iamfns';
take([1, 2, 3, 4, 5], 3);
// => [1, 2, 3]
take(['a', 'b', 'c'], 2);
// => ['a', 'b']
takeRightReturns the last n elements from an array.
function takeRight<T>(array: T[], n: number): T[]
Parameters:
array - The source arrayn - The number of elements to take from the endReturns: A new array with the last n elements
Example:
import { takeRight } from 'iamfns';
takeRight([1, 2, 3, 4, 5], 3);
// => [3, 4, 5]
takeRight(['a', 'b', 'c'], 2);
// => ['b', 'c']
uniqRemoves duplicate values from an array, preserving the first occurrence of each value. Supports arrays of strings, numbers, and booleans.
function uniq<T extends string | number | boolean>(arr: T[]): T[]
Parameters:
arr - The array to deduplicateReturns: A new array with duplicate values removed
Example:
import { uniq } from 'iamfns';
uniq([1, 2, 3, 4, 5]);
// => [1, 2, 3, 4, 5]
uniq(['a', 'b', 'c', 'a', 'd']);
// => ['a', 'b', 'c', 'd']
uniq([true, false, true, false]);
// => [true, false]
uniqByRemoves duplicate values from an array of objects based on a key or iteratee function, preserving the first occurrence of each unique value.
function uniqBy<T, K extends keyof T>(
arr: T[],
key: K | ((item: T) => unknown),
): T[]
Parameters:
arr - The array to deduplicatekey - A property key or a function that returns the value to compare uniqueness byReturns: A new array with duplicate entries removed, keeping the first occurrence
Example:
import { uniqBy } from 'iamfns';
// Deduplicate by object key
uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], 'id');
// => [{ id: 1 }, { id: 2 }]
// Deduplicate using an iteratee function
uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], (item) => item.id);
// => [{ id: 1 }, { id: 2 }]
// Deduplicate by a computed value
const users = [
{ name: 'Alice', role: 'admin' },
{ name: 'Bob', role: 'user' },
{ name: 'Charlie', role: 'admin' },
];
uniqBy(users, 'role');
// => [{ name: 'Alice', role: 'admin' }, { name: 'Bob', role: 'user' }]
deepMergeDeeply merges two objects. Arrays are replaced (not merged). Does not mutate the original target.
function deepMerge<T, S extends object>(target: T, source?: S): T & S
Parameters:
target - The target objectsource - The source object to merge into target (optional)Returns: A new deeply merged object
Example:
import { deepMerge } from 'iamfns';
// Flat objects
deepMerge({ a: 1, b: 2 }, { b: 3, c: 4 });
// => { a: 1, b: 3, c: 4 }
// Nested objects
deepMerge(
{ user: { name: 'John', age: 30 } },
{ user: { age: 31, city: 'NYC' } }
);
// => { user: { name: 'John', age: 31, city: 'NYC' } }
// Arrays are replaced, not merged
deepMerge({ tags: [1, 2, 3] }, { tags: [4, 5] });
// => { tags: [4, 5] }
// Complex nested structures
deepMerge(
{ user: { settings: { theme: 'dark' }, tags: ['admin'] } },
{ user: { settings: { lang: 'en' }, tags: ['user'] } }
);
// => { user: { settings: { theme: 'dark', lang: 'en' }, tags: ['user'] } }
// Original target is not mutated
const target = { a: 1 };
const result = deepMerge(target, { b: 2 });
// target is still { a: 1 }
// result is { a: 1, b: 2 }
getKVGets a value from an object by key with automatic case conversion. Tries the exact key first, then snake_case, then camelCase versions.
function getKV(obj: Record<string, any> | undefined, key: string): any
Parameters:
obj - The source object (or undefined)key - The key to look upReturns: The value if found, otherwise undefined
Example:
import { getKV } from 'iamfns';
// Direct key match
getKV({ testKey: 'value' }, 'testKey');
// => 'value'
// camelCase key finds snake_case property
getKV({ test_key: 'value' }, 'testKey');
// => 'value'
// snake_case key finds camelCase property
getKV({ testKey: 'value' }, 'test_key');
// => 'value'
// Complex key conversion
getKV({ my_complex_key_name: 'value' }, 'myComplexKeyName');
// => 'value'
// Handles undefined objects
getKV(undefined, 'testKey');
// => undefined
// Returns undefined when key not found
getKV({ otherKey: 'value' }, 'testKey');
// => undefined
inverseObjInverts the keys and values of an object.
function inverseObj<K extends PropertyKey, V extends PropertyKey>(
obj: Record<K, V>
): Record<V, K>
Parameters:
obj - An object with keys and values that are valid property keys (string, number, or symbol)Returns: A new object with keys and values swapped
Example:
import { inverseObj } from 'iamfns';
inverseObj({ a: 'x', b: 'y', c: 'z' });
// => { x: 'a', y: 'b', z: 'c' }
inverseObj({ one: 1, two: 2, three: 3 });
// => { 1: 'one', 2: 'two', 3: 'three' }
// Note: duplicate values will be overwritten
inverseObj({ a: 'x', b: 'x', c: 'y' });
// => { x: 'b', y: 'c' }
objDeltaReturns the changed properties between two objects. Only includes keys that exist in the first object and have different values in the second object.
function objDelta<T extends Record<string, any>>(obj1: T, obj2: T): Partial<T>
Parameters:
obj1 - The original object (defines which keys to compare)obj2 - The updated object (source of new values)Returns: An object containing only the properties that changed
Example:
import { objDelta } from 'iamfns';
// Single property changed
objDelta({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 4 });
// => { c: 4 }
// Multiple properties changed
objDelta({ a: 1, b: 2, c: 3 }, { a: 10, b: 2, c: 30 });
// => { a: 10, c: 30 }
// No changes returns empty object
objDelta({ a: 1, b: 2 }, { a: 1, b: 2 });
// => {}
// Only compares keys from first object
objDelta({ a: 1, b: 2 }, { a: 10, b: 2, c: 30 });
// => { a: 10 } (c is ignored since it's not in obj1)
// Excludes undefined values from delta
objDelta({ a: 1, b: 2, c: 3 }, { a: 1, b: undefined, c: 4 });
// => { c: 4 }
omitCreates a new object with the specified keys removed.
function omit<T extends Record<string, any>>(obj: T, keys: (keyof T)[]): Omit<T, keyof T>
Parameters:
obj - The source objectkeys - An array of keys to omit from the objectReturns: A new object without the specified keys
Example:
import { omit } from 'iamfns';
// Omit a single key
omit({ a: 1, b: 2, c: 3 }, ['b']);
// => { a: 1, c: 3 }
// Omit multiple keys
omit({ a: 1, b: 2, c: 3 }, ['a', 'c']);
// => { b: 2 }
// Empty keys array returns a copy of the object
omit({ a: 1, b: 2, c: 3 }, []);
// => { a: 1, b: 2, c: 3 }
// Omit all keys returns an empty object
omit({ a: 1, b: 2, c: 3 }, ['a', 'b', 'c']);
// => {}
omitByFilters an object's entries based on a predicate function. Omits the entries where the filter returns true.
function omitBy<T extends Record<string, any>>(
obj: T,
filter: (key: keyof T, value: T[keyof T]) => boolean
): T
Parameters:
obj - The source objectfilter - A predicate function that receives the key and value, returns true to omit the entryReturns: A new object without the entries that match the filter
Example:
import { omitBy } from 'iamfns';
// Omit entries with value greater than 1
omitBy({ a: 1, b: 2, c: 3 }, (_key, value) => value > 1);
// => { a: 1 }
// Omit a specific key
omitBy({ a: 1, b: 2, c: 3 }, (key) => key === 'b');
// => { a: 1, c: 3 }
// Omit falsy values
omitBy({ a: 0, b: '', c: 'hello', d: 42 }, (_key, value) => !value);
// => { c: 'hello', d: 42 }
// Omit by both key and value
omitBy({ name: 'John', age: 30, active: true }, (key, value) =>
typeof value === 'string' || key === 'active'
);
// => { age: 30 }
omitUndefinedRemoves all properties with undefined values from an object. Preserves null, false, 0, and empty string values.
function omitUndefined<T extends Record<string, any>>(obj: T): OmitUndefined<T>
Parameters:
obj - The source objectReturns: A new object with all undefined values removed
Example:
import { omitUndefined } from 'iamfns';
omitUndefined({ a: 1, b: undefined, c: 'test' });
// => { a: 1, c: 'test' }
omitUndefined({ a: null, b: undefined, c: 0 });
// => { a: null, c: 0 }
omitUndefined({ a: false, b: '', c: 0, d: undefined });
// => { a: false, b: '', c: 0 }
tryParseSafely parses a JSON string, returning undefined instead of throwing on invalid input.
function tryParse<T>(json: any): T | undefined
Parameters:
json - The JSON string to parseReturns: The parsed value typed as T, or undefined if parsing fails
Example:
import { tryParse } from 'iamfns';
tryParse<{ a: number }>('{"a": 1}');
// => { a: 1 }
tryParse<{ a: number }>('invalid json');
// => undefined
tryParse<number[]>('[1, 2, 3]');
// => [1, 2, 3]
stringifyConverts an object to a URL query string. Supports arrays, nested objects, and properly encodes special characters.
function stringify(obj: Record<string, any>): string
Parameters:
obj - The object to convertReturns: A URL-encoded query string
Example:
import { stringify } from 'iamfns';
// Simple object
stringify({ a: 1, b: '2', c: true });
// => 'a=1&b=2&c=true'
// Arrays (repeated keys)
stringify({ tags: ['js', 'ts', 'node'] });
// => 'tags=js&tags=ts&tags=node'
// Nested objects (bracket notation)
stringify({ user: { name: 'John', age: 30 } });
// => 'user[name]=John&user[age]=30'
// Null/undefined values (flags)
stringify({ a: null, b: undefined, c: 'value' });
// => 'a&b&c=value'
// Special characters are encoded
stringify({ q: 'hello world' });
// => 'q=hello%20world'
parseParses a URL query string into an object. Handles arrays, nested objects with bracket notation, and decodes special characters.
function parse(str: string): Record<string, any>
Parameters:
str - The query string to parse (with or without leading ?)Returns: The parsed object
Example:
import { parse } from 'iamfns';
// Simple query string
parse('a=1&b=2&c=true');
// => { a: '1', b: '2', c: 'true' }
// With leading question mark
parse('?name=John&age=30');
// => { name: 'John', age: '30' }
// Repeated keys become arrays
parse('tag=js&tag=ts&tag=node');
// => { tag: ['js', 'ts', 'node'] }
// Bracket notation becomes nested object
parse('user[name]=John&user[age]=30');
// => { user: { name: 'John', age: '30' } }
// Flags (keys without values)
parse('active&verified&role=admin');
// => { active: true, verified: true, role: 'admin' }
// Decodes special characters
parse('q=hello%20world');
// => { q: 'hello world' }
truncateTruncates a string to a maximum length, appending an omission string when the text is cut. Accounts for the omission length so the total result never exceeds length.
function truncate(
text: string,
options: { length: number; omission?: string }
): string
Parameters:
text - The string to truncateoptions.length - The maximum length of the resulting string (including the omission)options.omission - The string appended when truncating (default: "...")Returns: The original string if it fits within length, otherwise the truncated string with the omission appended
Example:
import { truncate } from 'iamfns';
// Text within limit is returned as-is
truncate('hello', { length: 10 }); // => 'hello'
truncate('hello', { length: 5 }); // => 'hello'
// Text exceeding limit is truncated with default omission
truncate('hello world', { length: 8 }); // => 'hello...'
// Custom omission string
truncate('hello world', { length: 8, omission: '…' }); // => 'hello w…'
// Empty omission truncates without any suffix
truncate('hello world', { length: 5, omission: '' }); // => 'hello'
// When length is shorter than the omission itself
truncate('hello world', { length: 2 }); // => '..'
// Empty string is returned as-is
truncate('', { length: 5 }); // => ''
sleepReturns a promise that resolves after the specified number of milliseconds. Useful for adding delays in async functions.
function sleep(ms: number): Promise<void>
Parameters:
ms - The number of milliseconds to waitReturns: A promise that resolves after the delay
Example:
import { sleep } from 'iamfns';
// Wait 1 second
await sleep(1000);
// Use in async function
async function fetchWithRetry(url: string, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i < retries - 1) {
await sleep(1000 * (i + 1)); // Exponential backoff
}
}
}
}
// Delay between operations
for (const item of items) {
await processItem(item);
await sleep(100); // Rate limiting
}
retryRuns an async function and retries it on failure. After each failure, waits before the next attempt using linear backoff: 100ms × attemptIndex (100ms before the second try, 200ms before the third, and so on). When the remaining retry budget reaches zero, the last error is rethrown.
function retry<T>(
fn: () => Promise<T>,
retries?: number,
tryCount?: number,
): Promise<T>
Parameters:
fn - A function that returns a promise (invoked on each attempt)retries - How many times to retry after a failure (default: 3). With the default, you get up to 4 attempts in total (initial try plus 3 retries)tryCount - Internal counter used for backoff timing; you normally omit this and use the default 1. It increments on each recursive retry and multiplies the delay (100 * tryCount ms)Returns: The resolved value of fn on success
Throws: The error from the final failed attempt when retries are exhausted
Example:
import { retry } from 'iamfns';
// Default: up to 4 attempts, 100ms / 200ms / 300ms delays between failures
await retry(() => fetch('/api/data').then((r) => {
if (!r.ok) throw new Error('HTTP error');
return r.json();
}));
// Fewer retries (1 initial + 2 retries = 3 attempts)
await retry(() => unstableCall(), 2);
// Usually you only pass fn and optionally retries; do not pass tryCount unless
// you are extending the helper.
EmitterA lightweight event emitter class for pub/sub patterns.
class Emitter {
on(event: string, listener: (...args: any[]) => void): void
off(event: string, listener?: (...args: any[]) => void): void
emit(event: string, ...args: any[]): void
}
Methods:
on(event, listener) - Registers a listener for an eventoff(event, listener?) - Removes a specific listener (or all listeners for the event)emit(event, ...args) - Emits an event with optional argumentsExample:
import { Emitter } from 'iamfns';
const emitter = new Emitter();
// Register listeners
const onLogin = (user) => {
console.log(`${user.name} logged in`);
};
emitter.on('user:login', onLogin);
emitter.on('user:login', (user) => {
trackAnalytics('login', user.id);
});
// Emit events
emitter.emit('user:login', { id: 1, name: 'John' });
// => "John logged in"
// => tracks analytics
// Remove a specific listener
emitter.off('user:login', onLogin);
// Remove all listeners for an event
emitter.off('user:login');
// Multiple arguments
emitter.on('order:created', (orderId, items, total) => {
console.log(`Order ${orderId}: ${items.length} items, $${total}`);
});
emitter.emit('order:created', 'ORD-123', ['item1', 'item2'], 99.99);
// => "Order ORD-123: 2 items, $99.99"
// Safe to emit events with no listeners
emitter.emit('unknown:event'); // No error
# Install dependencies
bun install
# Run tests
bun test
# Build
bun run build
# Lint
bun run lint
MIT
FAQs
A collection of lightweight, type-safe utility functions for TypeScript.
We found that iamfns demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.