Metarhia utilities
npm install metautil





- Install: npm install metautil
- Require: const metautil = require('metautil')
- toBool = [() => true, () => false]
- Example: const created = await mkdir(path).then(...toBool);
- timeout(msec: number, signal?: AbortSignal): Promise
- delay(msec: number, signal?: AbortSignal): Promise
- timeoutify(promise: Promise
- collect(keys: Array
- options.exact?: boolean
- options.timeout?: number
- options.reassign?: boolean
CollectorAsync collection is an utility to collect needed keys and signalize on done.
- constructor(keys: Array
- options.exact?: boolean
- options.timeout?: number
- options.reassign?: boolean
- options.defaults?: object
- options.validate?: (data: Record
- set(key: string, value: unknown): void
- wait(key: string, fn: AsyncFunction | Promise
- take(key: string, fn: Function, ...args?: Array
- collect(sources: Record
- fail(error: Error): void
- abort(): void
- then(onFulfilled: Function, onRejected?: Function): Promise
- done: boolean
- data: Dictionary
- keys: Array
- count: number
- exact: boolean
- timeout: number
- defaults: object
- reassign: boolean
- validate?: (data: Record
- signal: AbortSignal
Collect keys with .set method:
``js
const ac = collect(['userName', 'fileName']);
setTimeout(() => ac.set('fileName', 'marcus.txt'), 100);
setTimeout(() => ac.set('userName', 'Marcus'), 200);
const result = await ac;
console.log(result);
`
Collect keys with .wait method from async or promise-returning function:
`js
const ac = collect(['user', 'file']);
ac.wait('file', getFilePromisified, 'marcus.txt');
ac.wait('user', getUserPromisified, 'Marcus');
try {
const result = await ac;
console.log(result);
} catch (error) {
console.error(error);
}
`
Collect keys with .take method from callback-last-error-first function:
`js
const ac = collect(['user', 'file'], { timeout: 2000, exact: false });
ac.take('file', getFileCallback, 'marcus.txt');
ac.take('user', getUserCallback, 'Marcus');
const result = await ac;
`
Set default values โโfor unset keys using the options.defaults argument:
`js
const defaults = { key1: 'sub1', key2: 'sub1' };
const dc = collect(['key1', 'key2'], { defaults, timeout: 2000 });
dc.set('key2', 'sub2');
const result = await dc;
`
Compose collectors (collect subkeys from multiple sources):
`js`
const dc = collect(['key1', 'key2', 'key3']);
const key1 = collect(['sub1']);
const key3 = collect(['sub3']);
dc.collect({ key1, key3 });
const result = await dc;
Complex example: compare Promise.allSettled + Promise.race vs Collector in next two examples:
`js
// Collect 4 keys from different contracts with Promise.allSettled + Promise.race
const promise1 = new Promise((resolve, reject) => {
fs.readFile('README.md', (err, data) => {
if (err) return void reject(err);
resolve(data);
});
});
const promise2 = fs.promises.readFile('README.md');
const url = 'http://worldtimeapi.org/api/timezone/Europe';
const promise3 = fetch(url).then((data) => data.json());
const promise4 = new Promise((resolve) => {
setTimeout(() => resolve('value4'), 50);
});
const timeout = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Timed out')), 1000);
});
const data = Promise.allSettled([promise1, promise2, promise3, promise4]);
try {
const keys = await Promise.race([data, timeout]);
const [key1, key2, key3, key4] = keys.map(({ value }) => value);
const result = { key1, key2, key3, key4 };
console.log(result);
} catch (err) {
console.log(err);
}
`
Compare with:
`js
// Collect 4 keys from different contracts with Collector
const dc = collect(['key1', 'key2', 'key3', 'key4'], { timeout: 1000 });
dc.take('key1', fs.readFile, 'README.md');
dc.wait('key2', fs.promises.readFile, 'README.md');
const url = 'http://worldtimeapi.org/api/timezone/Europe';
dc.wait(
'key3',
fetch(url).then((data) => data.json()),
);
setTimeout(() => dc.set('key4', 'value4'), 50);
try {
const result = await dc;
console.log(result);
} catch (err) {
console.log(err);
}
`
- cryptoRandom(min?: number, max?: number): numberrandom(min?: number, max?: number): number
- generateUUID(): string
- generateKey(possible: string, length: number): string
- crcToken(secret: string, key: string): string
- generateToken(secret: string, characters: string, length: number): string
- validateToken(secret: string, token: string): boolean
- serializeHash(hash: Buffer, salt: Buffer): string
- deserializeHash(phcString: string): HashInfo
- hashPassword(password: string): Promise
- validatePassword(password: string, serHash: string): Promise
- md5(fileName: string): Promise
- getX509(cert: X509Certificate): Strings
-
`js`
const x509 = new crypto.X509Certificate(cert);
const domains = metautil.getX509names(x509);
- duration(s: string | number): numbernowDate(date?: Date): string
- nowDateTimeUTC(date?: Date, timeSep?: string): string
- parseMonth(s: string): number
- parseDay(s: string): number
- parseEvery(s: string): Every
- nextEvent(every: Every, date?: Date): number
-
- Class Errorconstructor(message: string, options?: number | string | ErrorOptions)
- options.code?: number | string
- options.cause?: Error
- message: string
- stack: string
- code?: number | string
- cause?: Error
- DomainError
- Class constructor(code?: string, options?: number | string | ErrorOptions)
- options.code?: number | string
- options.cause?: Error
- message: string
- stack: string
- code?: number | string
- cause?: Error
- toError(errors: Errors): Error
- isError(instance: object): boolean
-
- exists(path: string): PromisedirectoryExists(path: string): Promise
- fileExists(path: string): Promise
- ensureDirectory(path: string): Promise
- parsePath(relPath: string): Strings
-
- parseHost(host?: string): stringparseParams(params: string): Cookies
- parseCookies(cookie: string): Headers
- parseRange(range: string): StreamRange
-
- Deprecated in 4.x: fetch(url: string, options?: FetchOptions): PromisereceiveBody(stream: IncomingMessage): Promise
- ipToInt(ip?: string): number
- intToIp(int: number): string
- httpApiCall(url: string, options: ApiOptions): Promise
-
- makePrivate(instance: object): objectprotect(allowMixins: Strings, ...namespaces: Namespaces): void
- jsonParse(buffer: Buffer): Dictionary | null
- isHashObject(o: string | number | boolean | object): boolean
- flatObject(source: Dictionary, fields: Strings): Dictionary
- unflatObject(source: Dictionary, fields: Strings): Dictionary
- getSignature(method: Function): Strings
- namespaceByPath(namespace: Dictionary, path: string): Dictionary | null
- serializeArguments(fields: Strings, args: Dictionary): string
- firstKey(obj: Dictionary): string | undefined
- isInstanceOf(obj: unknown, constrName: string): boolean
-
- constructor(options: PoolOptions)options.timeout?: number
- items: Array
- free: Array
- queue: Array
- current: number
- size: number
- available: number
- timeout: number
- next(): Promise
- add(item: unknown): void
- capture(): Promise
- release(item: unknown): void
- isFree(item: unknown): boolean
-
`js
const pool = new metautil.Pool();
pool.add({ a: 1 });
pool.add({ a: 2 });
pool.add({ a: 3 });
if (pool.isFree(obj1)) console.log('1 is free');
const item = await pool.capture();
if (pool.isFree(obj1)) console.log('1 is captured');
const obj = await pool.next();
// obj is { a: 2 }
pool.release(item);
`
`js`
const cards = ['๐ก', '๐', '๐ฎ', '๐ท', '๐'];
const card = sample(cards);
`js`
const players = [{ id: 10 }, { id: 12 }, { id: 15 }];
const places = shuffle(players);
`js`
const player = { name: 'Marcus', score: 1500, socket };
const playerState = projection(player, ['name', 'score']);
- constructor(options: SemaphoreOptions)options.concurrency: number
- options.size?: number
- options.timeout?: number
- concurrency: number
- counter: number
- timeout: number
- size: number
- empty: boolean
- queue: Array
- enter(): Promise
- leave(): void
-
`js`
const options = { concurrency: 3, size: 4, timeout: 1500 };
const semaphore = new Semaphore(options);
await semaphore.enter();
// Do something
semaphore.leave();
- replace(str: string, substr: string, newstr: string): stringbetween(s: string, prefix: string, suffix: string): string
- split(s: string, separator: string): [string, string]
- isFirstUpper(s: string): boolean
- isFirstLower(s: string): boolean
- isFirstLetter(s: string): boolean
- toLowerCamel(s: string): string
- toUpperCamel(s: string): string
- toLower(s: string): string
- toCamel(separator: string): (s: string) => string
- spinalToCamel(s: string): string
- snakeToCamel(s: string): string
- isConstant(s: string): boolean
- fileExt(fileName: string): string
- parsePath(relPath: string): Strings
- trimLines(s: string): string
-
- bytesToSize(bytes: number): stringsizeToBytes(size: string): number
-
`js`
const size = bytesToSize(100000000);
const bytes = sizeToBytes(size);
console.log({ size, bytes });
// { size: '100 MB', bytes: 100000000 }
| Symbol | zeros | Unit |
| -----: | ----: | --------- |
| yb | 24 | yottabyte |
| zb | 21 | zettabyte |
| eb | 18 | exabyte |
| pb | 15 | petabyte |
| tb | 12 | terabyte |
| gb | 9 | gigabyte |
| mb | 6 | megabyte |
| kb | 3 | kilobyte |
- Events:
- constructor(options?: { maxListeners?: number })emit(eventName: EventName, data: unknown): Promise
- on(eventName: EventName, listener: Listener): void
- once(eventName: EventName, listener: Listener): void
- off(eventName: EventName, listener?: Listener): void
- toPromise(eventName: EventName): Promise
- Adapters:
- toAsyncIterable(eventName: EventName): AsyncIterable
- clear(eventName?: EventName): void
- Utilities:
- listeners(eventName?: EventName): Listener[]
- listenerCount(eventName?: EventName): number
- eventNames(): EventName[]
-
Examples:
`js`
const ee = new Emitter();
ee.on('eventA', (data) => {
console.log({ data });
// Prints: { data: 'value' }
});
ee.emit('eventA', 'value');
`js`
const ee = new Emitter();
setTimeout(() => {
ee.emit('eventA', 'value');
}, 100);
const result = await ee.toPromise('eventA');
`js``
const ee = new Emitter();
passReferenceSomewhere(ee);
const iterable = ee.toAsyncIterable('eventB');
for await (const eventData of iterable) {
console.log({ eventData });
}
Copyright (c) 2017-2025 Metarhia contributors.
Metautil is MIT licensed.\
Metautil is a part of Metarhia technology stack.