@ethanblaisalarms/utils
v1.0.0
Published
Lightweight helpers, primarily focused on array and object manipulation and improved stringification.
Readme
Lightweight helpers, primarily focused on array and object manipulation and improved stringification.
Installation and setup example
npm install @ethanblaisalarms/utils// ESM
import {merge} from "@ethanblaisalarms/utils";
// CommonJS
const {merge} = require("@ethanblaisalarms/utils");TypeScript types
Record shorthand types
type TRecord<T = unknown> = Record<string, T>| TypeScript | Shorthand for string records.
|------------|-
| JavaScript | Equal to object.
type TNumRecord<T = unknown> = Record<number, T>| TypeScript | Shorthand for numeric records.
|------------|-
| JavaScript | Equal to object with numeric keys.
Await until condition
type TCondition = (i?:number)=>boolean;| TypeScript | A function with an optional iteration parameter, which returns a boolean.
|------------|-
| JavaScript | Equal to function.
Object utilities
Merge objects
function merge<T extends object>(target:T, ...sources:object[]):TThis function merges two or more objects together. Merging starts from the first object, and moves down the line. This means that in objects which share properties, the last object has priority.
This function will mutate target and may overwrite properties.
This function will:
- NOT merge any function
- NOT merge any of the following keys:
__proto__,prototype, orconstructor - NOT merge any symbol keys
- NOT recursively merge non-plain objects
- Preserve excluded keys or functions in
target - Concatenate arrays
Arguments:
| Name | Type | Description
|-----------|--------------|------------
| target | object | required, mutated: The object to merge into.
| sources | ...object[] | Array of objects to merge into target. If empty, target is unchanged.
| @returns | object | A reference to target.
Example:
const x = {
A: 1,
B: 2,
C: 3,
};
const y = {
A: 10,
D: 40,
E: 50,
};
const z = {
A: 100,
E: 500,
F: 600,
};
merge(x, y, z);
// Expected value of x:
{
A: 100,
B: 2,
C: 3,
D: 40,
E: 500,
F: 600,
};Common Use Case:
import userConfig from "./Config.js";
const CONFIG = {
debugMode: false,
};
merge(CONFIG, userConfig);De-comment JSON
function decommentJSON(data:string):stringThis function removes comments from JSON strings. This makes it easy to parse JSON files which may contain comments.
Arguments:
| Name | Type | Description
|-----------|--------|------------
| data | string | required: The JSON string to remove comments from.
| @returns | string | data, but with JSON comments removed.
Example:
const x = `{
// "A" holds the number of apples.
"A": 10,
/* "B" holds the number of bananas.
Must be greater than 0. */
"B": 20,
/*
"C" holds the number of carrots.
Must be:
- An even number
- Divisible by 3
- Not divisible by 60
- The digits must no add up to 6
*/
"C": 30,
"D": "//This is not a JSON comment"
}`;
const y = decommentJSON(x);
// Expected value of y:
`{
"A": 10,
"B": 20,
"C": 30,
"D": "//This is not a JSON comment"
}`;Common Use Case:
const rawConfig = fs.readFileSync("config.json");
const CONFIG = JSON.parse(decommentJSON(rawConfig));Check for plain objects
function checkPlain(data:unknown):data is TRecordThis function checks if a passed value is a plain object. If so, TypeScript will recognize the result as a TRecord.
Arguments:
| Name | Type | Description
|----------|---------|------------
| data | unknown | required: The value to check.
| @returns | boolean | Whether data is a plain object.
Example:
const x = new Date();
const y = {};
const z = [
checkPlain(x),
checkPlain(y),
];
// Expected value of z:
[false, true];Array utilities
Pull from array
function pull<T>(target:T[], ...elements:T[]):T[]This function removes the first instance of each of the specified elements from the array.
This function will mutate target and may remove elements.
Arguments:
| Name | Type | Description
|------------|---------------|------------
| target | unknown[] | required, mutated: The array to remove elements from.
| elements | ...unknown[] | Array of elements to remove from target. If no objects are specified, target is unchanged.
| @returns | unknown[] | A reference to target.
Example:
const x = [10, 20, 30, 40, 50, 20];
pull(x, 20, 50);
// Expected value of x:
[10, 30, 40, 20];Pull all
function pullAll<T>(target:T[], ...elements:T[]):T[]This function removes all instances of each of the specified elements from the array.
This function will mutate target and may remove elements.
Arguments:
| Name | Type | Description
|------------|---------------|------------
| target | unknown[] | required, mutated: The array to remove elements from.
| elements | ...unknown[] | Array of elements to remove from target. If no objects are specified, target is unchanged.
| @returns | unknown[] | A reference to target.
Example:
const x = [10, 20, 30, 40, 50, 20];
pullAll(x, 20, 50);
// Expected value of x:
[10, 30, 40];Pull and replace
function replace<T>(target:T[], element:T, ...replace:T[]):T[]This function removes the first instance of a specified element from the array and replaces it with the specified replacements.
This function will mutate target and may add or remove elements.
Arguments:
| Name | Type | Description
|------------|---------------|------------
| target | unknown[] | required, mutated: The array to remove elements from.
| element | unknown | required: The element to remove from target.
| replace | ...unknown[] | The elements to replace removed elements. If none are specified, behavior matches pull().
| @returns | unknown[] | A reference to target.
Example:
const x = [10, 20, 30, 40, 50, 20];
replace(x, 20, 60, 70);
// Expected value of x:
[10, 60, 70, 30, 40, 50, 20];Pull and replace all
function replaceAll<T>(target:T[], element:T, ...replace:T[]):T[]This function removes all instances of a specified element from the array and replaces it with the specified replacements.
This function will mutate target and may add or remove elements.
Arguments:
| Name | Type | Description
|------------|---------------|------------
| target | unknown[] | required, mutated: The array to remove elements from.
| element | unknown | required: The element to remove from target.
| replace | ...unknown[] | The elements to replace removed elements. If none are specified, behavior matches pullAll().
| @returns | unknown[] | A reference to target.
Example:
const x = [10, 20, 30, 40, 50, 20];
replaceAll(x, 20, 60, 70);
// Expected value of x:
[10, 60, 70, 30, 40, 50, 60, 70];Objectify arrays
function objectify<T>(source:T[]):TNumRecord<T>This function converts an array to a plain object with numeric keys. The original array is not mutated.
Arguments:
| Name | Type | Description
|----------|------------|------------
| source | unknown[] | required: The array to convert to a plain object.
| @returns | TNumRecord | The new object created from source.
Example:
const x = ["zero", "one", "two", "three"];
const y = objectify(x);
// Expected value of y:
{
0: "zero",
1: "one",
2: "two",
3: "three",
};Stringify values
General stringify
function stringify(data:unknown):stringThis function converts any value to a readable string.
The process looks like this:
- If the value is a bigint,
return data + "n"; - If the value is not an object,
return String(data); - If the value is null,
return "null"; - If the value is a Map or a Set, convert to an array and
stringify()it - If the value is an array,
return stringifyJSON(data); - If the value has a non-default toString method, call it and return the value
- Otherwise,
return stringifyJSON({...data});
Arguments:
| Name | Type | Description
|----------|---------|------------
| data | unknown | required: The value to convert to a string.
| @returns | string | A string representation of data.
Example:
const x = 500n;
const y = null;
const z = {};
const res = [
stringify(x),
stringify(y),
stringify(z),
];
// Expected value of res:
["500n", "null", "{}"];Stringify JSON
function stringifyJSON(
data:object,
separator:string = " ",
ignore:string[] = [],
):stringThis function converts an object into a string. This function adds additional support to JSON.stringify().
Unlike JSON.stringify() alone, this function can:
- Handle bigint values
- Handle instances of Map and Set
- Handle circular object references
- Optionally ignore specified key paths
Arguments:
| Name | Type | Description
|-------------|----------|------------
| data | object | required: The object to convert to a string.
| separator | string | The separator to pass into JSON.stringify().
| ignore | string[] | An array of dot-notation key paths to ignore.
| @returns | string | A string representation of data.
Example:
const x = {
A: 1,
B: 2,
};
const y = {
A: 1,
B: 2,
C: {
A: 100n,
B: 2,
},
};
const z = {
X: x,
C: x,
};
z.Z = z;
const res = {
x: stringifyJSON(x),
y: stringifyJSON(y, " ", ["A", "C.B"]),
z: stringifyJSON(z),
};
// Expected value of res:
{
x: `{
"A": 1,
"B": 2
}`,
y: `{
"B": 2,
"C": {
"A": "100n"
}
}`,
z: `{
"X": {
"A": 1,
"B": 2
},
"C": "[Circular: X]",
"Z": "[Circular: ~]"
}`,
};Stringify array elements
function stringifyArray(data:unknown[]):string[]Shorthand for data.map(stringify). Converts all elements of an array into strings, and returns the new array without mutating the existing array.
Arguments:
| Name | Type | Description
|----------|------------|------------
| data | unknown[] | required: The array to stringify the elements of.
| @returns | string[] | data, but after all elements are converted to strings.
Example:
const x = [null, 20, {}];
const y = stringifyArray(x);
// Expected value of y:
["null", "20", "{}"];Randomization
Random number
function rand():numberShorthand for Math.random(). Generates a random number between 0 and 1.
Arguments:
| Name | Type | Description
|----------|--------|------------
| @returns | number | The result of Math.random().
Example:
const x = [
rand(),
rand(),
rand(),
rand(),
rand(),
]
// Expected value of x:
[
0.8966649491265986,
0.18814033044643852,
0.6812450432610444,
0.30752727234410016,
0.6411181322989353,
];Random number up to
function rand(base:number):numberGenerates a random integer between 0 and base (inclusive).
Arguments:
| Name | Type | Description
|----------|--------|------------
| base | number | required: The maximum number to generate.
| @returns | number | A random number between 0 and base.
Example:
const x = [
rand(5),
rand(5),
rand(5),
rand(5),
rand(5),
]
// Expected value of x:
[0, 4, 1, 0, 5];Random number between
function rand(base:number, max:number):numberGenerates a random integer between base and max (inclusive).
Arguments:
| Name | Type | Description
|----------|--------|------------
| base | number | required: The minimum number to generate.
| max | number | required: The maximum number to generate.
| @returns | number | A random number between base and max.
Example:
const x = [
rand(-5, 5),
rand(-5, 5),
rand(-5, 5),
rand(-5, 5),
rand(-5, 5),
]
// Expected value of x:
[4, 1, -1, -1, -5];Random array element
function rand<T>(base:T[]):T|nullReturns a random element from the base array.
Arguments:
| Name | Type | Description
|----------|------------|------------
| base | unknown[] | required: The array to search.
| @returns | unknown | A random element from base.
| @returns | null | If the array is empty.
Example:
const x = "ABCDE".split("");
const y = [
rand(x),
rand(x),
rand(x),
rand(x),
rand(x),
];
// Expected value of y:
["C", "B", "B", "A", "E"];Random object key
function rand(base:TRecord):string|nullReturns a random key from the base object.
Arguments:
| Name | Type | Description
|----------|--------|------------
| base | object | required: The object to search.
| @returns | string | A random key from base.
| @returns | null | If the object is empty.
Example:
const x = {
A: 10,
B: 20,
C: 30,
D: 40,
E: 50,
};
const y = [
rand(x),
rand(x),
rand(x),
rand(x),
rand(x),
];
// Expected value of y:
["E", "C", "A", "A", "E"];Random string
function randString(
len:number = 16,
charset:string|string[] = "0123456789ABCDEF",
):stringReturns a randomly generated string of the specified length, using the specified charset.
Arguments:
| Name | Type | Description
|-----------|-----------|------------
| len | number | The length of the string.
| charset | string | The charset to use.
| charset | string[] | The array of strings to use.
| @returns | string | A random string.
| @returns | "" | If charset did not include at least one item.
Example:
const x = [
randString(4),
randString(8, "!@$^"),
randString(4, ["Hey", "Hi", "Hello"]),
];
// Expected value of x:
[
"9D39",
"@$!!^@$$",
"HeyHiHiHello",
];Async Utilities
Sleep
async function sleep(ms:number):Promise<void>When awaited, waits (sleeps) for the specified milliseconds.
Arguments:
| Name | Type | Description
|----------|---------|------------
| ms | number | required: The duration to sleep for.
| @returns | Promise | Resolves after ms milliseconds.
Example:
console.log("Start!");
await sleep(5000);
console.log("Stop!");
// Expected delay between Start and Stop: 5 seconds.Await Until
async function until(
condition:TCondition,
interval:number = 100,
attempts:number|null = null,
):Promise<number>When awaited, waits until the specified condition returns true.
Arguments:
| Name | Type | Description
|-------------|----------|------------
| condition | function | The function condition.
| interval | number | The number of milliseconds between condition calls.
| attempts | number | The maximum number of attempts.
| attempts | null | Disables the maximum number of attempts.
| @returns | Promise | Resolves once condition returns true. Rejects when reaching the maximum attempts.
Example:
const x = {
value: false,
};
async function setTrue() {
await sleep(5000);
x.value = true;
}
console.log("Start!");
setTrue();
await until(() => {
return x.value;
});
console.log("Stop!");
// Expected delay between Start and Stop: 5 seconds.