@freeword/meta
Version:
Meta package for Freeword: exports all core types, constants, and utilities from the src/ directory.
166 lines • 6.38 kB
JavaScript
import _ /**/ from 'lodash';
import * as NodeUtil from 'node:util';
// import { nextTick } from 'node:process'
import { AtoZlos } from "../lexicon/LexiconConsts.js";
import * as JSPrintf from 'sprintf-js';
//
export * from "./BaseUtils.js";
export * from "../lib/Streaming.js";
export * from "../lib/Random.js";
export * from "../UtilityConsts.js";
export * from "../lib/Rot13.js";
export { badOutcome, throwable } from "./OutcomeUtils.js";
export * from "./CollectionUtils.js";
export * from "./Logging.js";
export * from "./PromiseUtils.js";
export const { sprintf, vsprintf } = JSPrintf;
/** @returns a bag with keys a, b, ... z and values of type VT */
export function alphabetLookupBag(seed) {
if (_.isFunction(seed)) {
return objectify(AtoZlos, (ltr) => seed(ltr));
}
return objectify(AtoZlos, () => (seed));
}
function indentPaddingFor(indent) {
if (!indent) {
return '';
}
if (_.isString(indent)) {
return indent;
}
return _.repeat(' ', indent);
}
/**
* Pretty-print an array of strings in chunks
*
* @param arr - The array to pretty-print
* @param opts - The options for pretty-printing
* @returns The pretty-printed array
*/
export function prettifyStrings(arr, { chunkSize = 20, colwd = 12, key, indent = 2, naked = false } = {}) {
const indentPadding = indentPaddingFor(indent);
const lines = _.chunk(arr, chunkSize).map((chunk) => chunk.map((val) => _.padEnd(val + ',', colwd)).join(' '));
const body = lines.join('\n' + indentPadding);
const bracketed = naked ? body : '[\n ' + body + '\n]';
return (key ? kfy(key) : '') + bracketed;
}
/**
* Pretty-print an array of strings in chunks
*
* @param arr - The array to pretty-print
* @param opts - The options for pretty-printing
* @returns The pretty-printed array
*/
export function prettifyInChunks(arr, { chunkSize = 20, colwd = 12, key, indent = 2, stringify = true } = {}) {
const stringified = stringify ? _.map(arr, (val) => inspectify(val)) : arr;
return prettifyStrings(stringified, { chunkSize, colwd, key, indent });
}
export function prettifyArray(arr, opts = {}) {
const inspected = inspectify(arr);
if ((inspected.length < 180) && (!opts.chunkArrays)) {
return opts.naked ? inspected.slice(1, -1).trim() : inspected;
}
return prettifyInChunks(arr, opts);
}
export function prettifySet(set, { key, ...opts } = {}) {
const elements = prettifyArray(Array.from(set), opts);
return (key ? kfy(key) : '') + 'new Set(' + elements + ')';
}
export function inspectify(val, _opts = {}) {
return NodeUtil.inspect(val, { depth: 10, colors: false, breakLength: Infinity, maxArrayLength: Infinity, maxStringLength: Infinity, compact: true, numericSeparator: true });
}
const FieldnameRE = /^[a-zA-Z_]\w*$/;
export function kfy(key, opts = {}) {
const str = FieldnameRE.test(key) ? key : inspectify(key);
return _.padEnd(str + ':', opts.keywd);
}
export function prettifyField(val, opts = {}) {
if (_.isArray(val)) {
return prettifyArray(val, opts);
}
if (_.isSet(val)) {
return prettifySet(val, opts);
}
return inspectify(val);
}
export function prettify(obj, { key, naked = false, ...opts } = {}) {
const firstkey = _.isNil(key) ? '' : (kfy(key) + ' ');
const startBracket = naked ? '' : '{';
const endBracket = naked ? '' : '}';
const lines = [];
const indentPadding = indentPaddingFor(opts.indent);
_.each(obj, (val, key) => {
const keypart = kfy(key, { keywd: 12, ...opts });
const valpart = prettifyField(val, opts);
lines.push(indentPadding + keypart + ' ' + valpart);
});
return firstkey + startBracket + '\n' + lines.join(',\n') + ',\n' + endBracket;
}
export function rebag(clxn, func) {
let seq = 0;
return Object.fromEntries(_.map(clxn, (val, key) => func(val, key, seq++, clxn)));
}
export function objectify(clxn, func) {
return rebag(clxn, (val, key, seq, ...args) => [val, func(val, key, seq, ...args)]);
}
export function bagslice(bag, start, end) {
const keys = _.keys(bag).slice(start, end);
return _.pick(bag, keys);
}
export function sortOnKeys([key, _val]) { return key; }
export function sortOnNumkeys([key, _val]) { return Number(key); }
/** Sort a bag by a funtion -- by default, its keys.
* @note **by default, keys that parse as positive integers (1, 2, 3, ...) will appear first in retrieval order**.
* This is part of the spec for Object.
* @example { '1': 1, '2': 2, '-1': -1, '0.9': 0.9, '1.1': 1.1 }
* If you use the magic function `sortOnNumkeys`,
* keys that stringify as integers will be reinserted as `x.0`:
* @example { '-1.0': -1, '0.9': 0.9, '1.0': 1, '1.1': 1.1, '2.0': 2 }
*/
export function bagsort(bag, sortfn = sortOnKeys, { mungeNumKeys = true, sortdirs } = {}) {
const result = {};
const sorted = _.orderBy(_.entries(bag), sortfn, sortdirs);
if (!mungeNumKeys) {
return _.fromPairs(sorted);
}
for (const [key, val] of sorted) {
const mungedKey = (Number.isInteger(Number(key))) ? (String(key) + '.0') : key;
result[mungedKey] = val;
}
return result;
}
const nextTicker = globalThis.nextTick ?? ((func) => (func()));
/**
* Sleep for one tick (i.e. let everyone else have a turn)
* @returns true
*/
export async function sleepNextTick() {
return new Promise((yay) => { nextTicker(() => yay(true)); });
}
/**
* Sleep for a given number of milliseconds
* @param ms - The number of milliseconds to sleep
* @param nextTick - Whether to sleep for one tick before starting the sleep
* @note IMPORTANT: if nextTick is true, the sleep will be delayed by
* the duration given PLUS an unknowable amount of time
* @returns true
*/
export async function sleep(ms, awakeNextTick = false) {
if (awakeNextTick) {
await sleepNextTick();
}
return new Promise((resolve) => setTimeout(resolve, ms)).then(() => true);
}
export async function* catiters(...iters) {
for (const iter of iters) {
yield* iter;
}
}
export function isNode() {
return (typeof process !== 'undefined' && process.release && process.release.name === 'node');
}
export function isBrowser() {
// if (isNode()) { return false }
return (!!import.meta.client);
}
//# sourceMappingURL=UF.js.map