// @ts-check
///
///
///
///
///
///
"use strict";
/**
* @name Celestra
* @version 6.4.0 node
* @author Ferenc Czigler
* @see https://github.com/Serrin/Celestra/
* @license MIT https://opensource.org/licenses/MIT
*/
const VERSION = "Celestra v6.4.0 node";
/** TS types */
/**
* @description Map-like object with string or number or symbol keys.
*
* @internal
* */
type MapLike = {[key: string]: any; [key: number]: any; [key: symbol]: any; };
/**
* @description Array-like object.
*
* @internal
* */
type ArrayLike = { length: number; [n: number]: any; };
/* interface ArrayLike { length: number; [n: number]: T; }; */
/**
* @description Set-like object.
*
* @internal
* */
/*
type SetLike ={
readonly size: number;
has(value: T): boolean;
};
*/
/**
* @description Number-like object.
*
* @internal
* */
type NumberLike = number | bigint;
/**
* @description Iterable and Iterator types.
*
* @internal
*/
type IterableAndIterator =
Iterable | Iterator | IterableIterator;
/**
* @description Iterable and Iterator and Array-like types.
*
* @internal
*/
type IterableAndIteratorAndArrayLike =
Iterable | Iterator | IterableIterator | ArrayLike;
/**
* @description Iterable and Iterator and Generator types.
*
* @internal
*/
type IteratorReturn =
Iterable | IteratorResult | Generator;
/**
* @description Type for undefined and null values.
*
* @internal
*/
type Nullish = undefined | null;
/*
built-in type:
type NonNullable = number | boolean | string | symbol | object | Function;
*/
/**
* @description Not null or undefined or object or function.
*
* @internal
*/
type NonNullablePrimitive = number | bigint | boolean | string | symbol;
/**
* @description Not object or function.
*
* @internal
*/
type Primitive = null | undefined | number | bigint | boolean | string | symbol;
/**
* Generic comparable types.
*
* @internal
*/
type Comparable = number | bigint | string | boolean;
/**
* @description Object key type.
*
* @internal
*/
type PropertyKey = string | symbol;
/**
* @description Primitive types.
*
* @internal
*/
type TypeOfTag =
| "null" | "undefined"
| "number" | "bigint" | "boolean" | "string" | "symbol"
| "object" | "function";
/**
* @description TypedArray types.
*
* @internal
*/
type TypedArray =
| Int8Array | Uint8Array | Uint8ClampedArray
| Int16Array | Uint16Array
| Int32Array | Uint32Array
| Float32Array | Float64Array
| BigInt64Array | BigUint64Array
| (typeof globalThis extends { Float16Array: infer F } ? F : never);
/** polyfills **/
/* globalThis; */
(function (global) {
if (!global.globalThis) {
if (Object.defineProperty) {
Object.defineProperty(global, "globalThis", {
configurable: true, enumerable: false, value: global, writable: true
});
} else {
global.globalThis = global;
}
}
})(typeof this === "object" ? this : Function("return this")());
/* Math.sumPrecise(); */
if (!("sumPrecise" in Math)) {
// @ts-ignore
Math.sumPrecise = function sumPrecise ([...array]): number {
/* empty iterator */
if (array.length === 0) { return -0; }
/* iterator with items */
if (array.every((value: unknown): boolean => typeof value === "number")) {
/* return NaN + Infinity + -Infinity */
let inf = array.indexOf(Infinity) >- 1;
let negInf = array.indexOf(-Infinity) > -1;
if (array.some((value: unknown): boolean => value !== value)
|| (inf && negInf)) { return NaN; }
if (inf) { return Infinity; }
if (negInf) { return -Infinity; }
/* sum hi */
let hi = array.filter((value: unknown): boolean =>
(value === 1e20 || value === -1e20))
.reduce((acc, value): number => acc + value, 0);
/* sum lo - Kahan sum */
let lo: number = 0.0;
let c: number = 0.0;
for (let item of array.filter((value: unknown): boolean =>
(value !== 1e20 && value !== -1e20))) {
let y = item - c; let t = lo + y; c = (t - lo) - y; lo = t;
}
/* return sum values */
/*
if (lo === 0 && hi !== 0) { return hi; }
if (lo > 0 && hi > 0) { return hi; }
if (lo < 0 && hi < 0) { return hi; }
if (lo > 0 && hi < 0) { return lo + hi; }
if (lo < 0 && hi > 0) { return lo + hi; }
if (lo === 0 && hi === 0) { return lo; }
if (lo !== 0 && hi === 0) { return lo; }
*/
if ((lo === 0 && hi !== 0) || (lo > 0 && hi > 0) || (lo < 0 && hi < 0)) {
return hi;
}
if ((lo > 0 && hi < 0) || (lo < 0 && hi > 0)) { return lo + hi; }
return lo;
}
/* not number items -> TypeError */
throw new TypeError("values passed to Math.sumPrecise must be numbers");
};
}
/* Error.isError(); */
if (!("isError" in Error)) {
// @ts-ignore
Error.isError = function isError (value: unknown) {
let className =
Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
return (className === "error" || className === "domexception");
};
}
/* Object.groupBy(); */
if (!("groupBy" in Object)) {
// @ts-ignore
Object.defineProperty(Object, "groupBy", {
"configurable": true, "writable": true, "enumerable": true,
"value": function (items: IterableAndIterator, callbackFn: Function) {
if (!(typeof callbackFn === "function")) { throw new TypeError(); }
let result = Object.create(null);
let index: number = 0;
for (let item of items as Iterable) {
let key = callbackFn(item, index++);
if (!(Object.prototype.hasOwnProperty.call(result, key))) {
result[key] = [];
}
result[key].push(item);
}
return result;
}
});
}
/* Map.groupBy(); */
if (!("groupBy" in Map)) {
Object.defineProperty(Map, "groupBy", {
"configurable": true, "writable": true, "enumerable": true,
"value": function (items: IterableAndIterator, callbackFn: Function) {
if (!(typeof callbackFn === "function")) { throw new TypeError(); }
let result = new Map();
let index: number = 0;
for (let item of items as Iterable) {
let key = callbackFn(item, index++);
if (!(result.has(key))) { result.set(key, []); }
result.get(key).push(item);
}
return result;
}
});
}
/* Array.fromAsync(); */
if (!Array.fromAsync) {
// @ts-ignore
Array.fromAsync = async function fromAsync (arrayLike, mapfn, thisArg) {
const isConstructor = (value: unknown): boolean =>
(typeof value === "function" && typeof value.prototype === "object");
const errorMsg = "Input length exceed the Number.MAX_SAFE_INTEGER.";
if (Symbol.asyncIterator in arrayLike || Symbol.iterator in arrayLike) {
let result: any[] = isConstructor(this) ? new this : Array(0);
let index: number = 0;
for await (const item of arrayLike) {
if (index > Number.MAX_SAFE_INTEGER) {
throw TypeError(errorMsg);
} else {
if (!mapfn) {
result[index] = item;
} else {
result[index] = await mapfn.call(thisArg,item,index);
}
}
index++;
}
result.length = index;
return result;
} else {
let length: number = arrayLike.length;
let result: any[] = isConstructor(this) ? new this(length) : Array(length);
let index: number = 0;
while (index < length) {
if (index > Number.MAX_SAFE_INTEGER) { throw TypeError(errorMsg); }
let item: any = await arrayLike[index];
if (!mapfn) {
result[index] = item;
} else {
result[index] = await mapfn.call(thisArg,item,index);
}
index++;
}
result.length = index;
return result;
}
};
}
/* crypto.randomUUID(); */
if (("crypto" in globalThis) && !("randomUUID" in globalThis.crypto)) {
// @ts-ignore
globalThis.crypto.randomUUID = function randomUUID () {
// @ts-ignore
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,
(c: any): any =>
(c^crypto.getRandomValues(new Uint8Array(1))[0]&15 >> c/4).toString(16)
);
};
}
/* Object.hasOwn(); */
if (!Object.hasOwn) {
Object.defineProperty(Object, "hasOwn", {
configurable: true, enumerable: false, writable: true,
value: function (object: object, property: string): boolean {
if (object == null) {
throw new TypeError("Cannot convert undefined or null to object");
}
return Object.prototype.hasOwnProperty.call(Object(object), property);
}
});
}
/* Array.prototype.toReversed(); */
if (!("toReversed" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toReversed", {
"configurable": true, "writable": true, "enumerable": false,
"value": function () { return this.slice().reverse(); }
});
}
/* Array.prototype.toSorted(); */
if (!("toSorted" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toSorted", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (fn: Function) { return this.slice().sort(fn); }
});
}
/* Array.prototype.toSpliced(); */
if (!("toSpliced" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toSpliced", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (
start: number,
deleteCount: number,
...items: any[]): any[] {
let result: any[] = this.slice();
result.splice(start, deleteCount, ...items);
return result;
}
});
}
/* Array.prototype.with(); */
if (!("with" in Array.prototype)) {
Object.defineProperty(Array.prototype, "with", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (index: string | number, value: unknown): any[] {
let result = this.slice();
result[index] = value;
return result;
}
});
}
/* TypedArray.prototype.toReversed(); */
if (!("toReversed" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "toReversed", {
"configurable": true, "writable": true, "enumerable": false,
"value": function () { return this.slice().reverse(); }
});
}
/* TypedArray.prototype.toSorted(); */
if (!("toSorted" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "toSorted", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (fn: Function) { return this.slice().sort(fn); }
});
}
/* TypedArray.prototype.with(); */
if (!("with" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "with", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (index: string | number, value: unknown) {
let result = this.slice();
result[index] = value;
return result;
}
});
}
/* globalThis.GeneratorFunction; */
// @ts-ignore
if (!globalThis.GeneratorFunction) {
// @ts-ignore
globalThis.GeneratorFunction =
Object.getPrototypeOf(function*(){}).constructor;
}
/* globalThis.AsyncFunction; */
// @ts-ignore
if (!globalThis.AsyncFunction) {
// @ts-ignore
globalThis.AsyncFunction =
Object.getPrototypeOf(async function(){}).constructor;
}
/* globalThis.AsyncGeneratorFunction; */
// @ts-ignore
if (!globalThis.AsyncGeneratorFunction) {
// @ts-ignore
globalThis.AsyncGeneratorFunction =
Object.getPrototypeOf(async function* () {}).constructor;
}
/** Core API **/
/* Alphabet constans */
const BASE16 = "0123456789ABCDEF";
const BASE32 = "234567ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const WORDSAFEALPHABET = "23456789CFGHJMPQRVWXcfghjmpqvwx"; /* 31 */
/* assert(value: unknown [, message | error]): thrown error */
/**
* @description Ensures that `condition` is truthy. Throws an `Error` if falsy.
*
* @param {unknown} condition The value to check.
* @param {unknown} [message] - Optional message or Error to throw.
* @throws {Error} If assertion is failed.
*/
function assert (condition: unknown, message?: unknown): asserts condition {
if (!condition) {
// @ts-ignore
if (Error.isError(message)) { throw message; }
let errorMessage =
`[assert] Assertion failed: ${condition} should be truly${message ? " - " + message : ""}`;
throw new Error(errorMessage, {cause: errorMessage});
}
}
/* isNonNullable (value: unknown): boolean */
/**
* @description Checks if the given value is NonNullable (not null or undefined).
*
* @param {unknown} value - The value to check.
* @returns True if the value is a NonNullable, false otherwise.
*/
const isNonNullable = (value: unknown): value is NonNullable =>
value != null;
/* isNonNullablePrimitive (value: unknown): boolean */
/**
* @description Checks if the given value is NonNullablePrimitive.
*
* @param {unknown} value - The value to check.
* @returns True if the value is a NonNullable, false otherwise.
*/
const isNonNullablePrimitive =
(value: unknown): value is NonNullablePrimitive =>
value != null && typeof value !== "object" && typeof value !== "function";
/* eq (value1: any, value2: any): boolean */
/**
* @description SameValueZero equality (like `Object.is`, but +0 === -0).
*
* @param {unknown} value1
* @param {unknown} value2
* @returns {boolean}
*/
const eq = (value1: unknown, value2: unknown): boolean =>
value1 === value2 || (value1 !== value1 && value2 !== value2);
/* gt (value1: any, value2: any): boolean */
/**
* @description Greater than.
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function gt (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2) && value1 > value2;
}
/* gte (value1: any, value2: any): boolean */
/**
* @description Greater than or equal (SameValueZero).
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function gte (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2)
&& (value1 > value2
|| value1 === value2
|| (value1 !== value1 && value2 !== value2));
}
/* lt (value1: any, value2: any): boolean */
/**
* @description Less than.
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function lt (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2) && value1 < value2;
}
/* lte (value1: any, value2: any): boolean */
/**
* @description Less than or equal (SameValueZero).
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function lte (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2)
&& (value1 < value2
|| value1 === value2
|| (value1 !== value1 && value2 !== value2));
}
/* tap(function: function): function(v) */
function tap (fn: Function): any {
return function (value: unknown): any { fn(value); return value; };
}
/* once(function: function): function */
function once (fn: Function): Function {
let called: boolean = false;
let result: any;
return function (...args: any[]): any {
if (!called) {
called = true;
result = fn(...args);
}
return result;
};
}
/* curry (function: function): function */
function curry (fn: Function): Function {
const curried = (...args: any[]): any =>
args.length >= fn.length
? fn(...args)
: (...rest: any[]): any => curried(...args, ...rest);
return curried;
}
/* pipe (function1:function [, functionN: function]): function */
const pipe = (...functions: Function[]): Function =>
(first: any): any =>
functions.reduce((value: unknown, fn: Function): any => fn(value), first);
/* compose (function1: function [, functionN: function]): function */
const compose = (...functions: Function[]): Function =>
(first: any): any => functions.reduceRight((value, fn): any => fn(value), first);
/* pick (object: object, keys: array): object */
const pick = (obj: MapLike, keys: string[]): MapLike =>
keys.reduce(function (acc: MapLike, key: string) {
if (key in obj) { acc[key] = obj[key]; }
return acc;
}, {});
/* omit (object: object, keys: array): object */
const omit = (obj: MapLike, keys: string[]): MapLike =>
Object.keys(obj).reduce(function (acc: MapLike, key: string) {
// @ts-ignore
if (!keys.includes(key)) { acc[key] = obj[key]; }
return acc;
}, {});
/* assoc (object: object, key: string, value: unknown): object */
const assoc = (obj: MapLike, key: string, value: unknown): MapLike =>
({...obj, [key]: value});
/* asyncNoop (): Promise - do nothing */
// @ts-ignore
function asyncNoop (): Promise {
return new Promise(function (resolve: Function) { resolve(); });
}
/* asyncT (): Promise - return true */
async function asyncT (): Promise { return true; }
/* asyncF (): Promise - return false */
async function asyncF (): Promise { return false; }
/* asyncConstant (value): async function */
function asyncConstant (value: unknown): Function {
return async function() { return value; };
}
/* asyncIdentity (value): Promise - return value */
async function asyncIdentity (value: unknown): Promise { return value; }
/* deleteOwnProperty(object, property [,Throw = false]): number | thrown error*/
function deleteOwnProperty (
obj: Object,
property: string,
Throw: boolean = false): number {
if (Object.hasOwn(obj, property)) {
// @ts-ignore
delete obj[property];
let result = Object.hasOwn(obj, property);
if (result && Throw) { throw new Error("[deleteOwnProperty] error"); }
return +!result;
}
return -1;
}
/* createPolyfillMethod(object, property, function: any): boolean */
function createPolyfillMethod (
obj: Object,
property: string,
value: Function): boolean {
if (!(Object.hasOwn(obj, property))) {
Object.defineProperty(obj, property, {
writable: true, enumerable: false, configurable: true, value: value
});
}
// @ts-ignore
return (obj[property] === value);
}
/* createPolyfillProperty(object, property, value: unknown): boolean */
function createPolyfillProperty (
obj: object,
property: string,
value: unknown): boolean {
if (!(Object.hasOwn(obj, property))) {
Object.defineProperty(obj, property, {
writable: true, enumerable: true, configurable: true, value: value
});
}
// @ts-ignore
return (obj[property] === value);
}
/* randomUUIDv7(v4: boolean = false): string */
function randomUUIDv7 (v4: boolean = false): string {
let ts = Date.now().toString(16).padStart(12,"0") + (v4 ? "4" : "7");
// @ts-ignore
let uuid = Array.from(([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, (c): any =>
(c^crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
));
let index: number = 0;
let pos: number = 0;
while (index < 13) {
if (pos === 8 || pos === 13) { pos++; }
uuid[pos] = ts[index];
pos++;
index++;
}
return uuid.join("");
}
/* delay(ms: integer).then(callback: function): promise */
const delay = (milisec: number): Promise =>
new Promise(resolve => setTimeout(resolve, milisec));
/* randomBoolean(): boolean */
const randomBoolean = (): boolean => !Math.round(Math.random());
/* getUrlVars([str = location.search]): Object */
const getUrlVars = (str: string = location.search): Object =>
[...new URLSearchParams(str).entries()]
// @ts-ignore
.reduce(function (obj, item) { obj[item[0]] = item[1]; return obj; }, {});
/* obj2string(object): string */
const obj2string = (obj: object): string => Object.keys(obj).reduce(
(str, key: string): string => str
// @ts-ignore
+= encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]) + "&",
"").slice(0, -1);
/* extend([deep: boolean,] target: object, source1: object[, sourceN]): object*/
/**
* @description Deep assign of an object (Object, Array, etc.)
*
* @returns any
*/
function extend (target: T, source: U): T & U;
function extend (target: T, s1: U, s2: V): T & U & V;
function extend (deep: true, target: T, ...sources: any[]): T;
function extend (deep: false, target: T, ...sources: any[]): T;
function extend (target: object, ...sources: any[]): object;
function extend (...args: any[]): any {
/* Arguments checking */
let deep: boolean = false;
let target: any;
let i = 0;
if (args[0] === true) {
deep = true;
target = args[1] || {};
i = 2;
} else {
target = args[0] || {};
i = 1;
}
/* Helper functions */
const _isPlainObject = (obj: any): obj is Record =>
obj != null
&& typeof obj === "object"
&& (obj.constructor === Object || obj.constructor == null);
const _isDate = (value: any): value is Date => value instanceof Date;
const _isRegExp = (value: any): value is RegExp => value instanceof RegExp;
const _isMap = (value: any): value is Map => value instanceof Map;
const _isSet = (value: any): value is Set => value instanceof Set;
/* */
function merge(target: any, source: any): any {
/* Identical or non-object -> direct assign */
if (Object.is(source, target) || source == null || typeof source !== "object") {
return source;
}
/* Date -> clone */
if (_isDate(source)) { return new Date(source.getTime()); }
/* RegExp -> clone */
if (_isRegExp(source)) { return new RegExp(source); }
/* Map -> deep merge entries */
if (_isMap(source)) {
if (!_isMap(target)) { target = new Map(); }
for (let [key, value] of source) {
const tv = target.get(key);
target.set(key, deep ? merge(tv, value) : value);
}
return target;
}
/* Set -> deep union */
if (_isSet(source)) {
if (!_isSet(target)) { target = new Set(); }
for (let item of source) {
if (deep) {
if (target.has(item)) { continue; }
}
target.add(item);
}
return target;
}
/* Array -> deep merge by index */
if (Array.isArray(source)) {
if (!Array.isArray(target)) { target = []; }
const srcLength = source.length;
for (let i = 0; i < srcLength; i++) {
let sv = source[i];
let tv = target[i];
target[i] = deep ? merge(tv, sv) : sv;
}
return target;
}
/* Plain object -> deep merge keys */
if (_isPlainObject(source)) {
if (!_isPlainObject(target)) { target = {}; }
for (let key in source) {
let sv = source[key];
let tv = target[key];
target[key] = deep ? merge(tv, sv) : sv;
}
return target;
}
/* Fallback: copy by reference */
return source;
}
/* Clone all sources */
const length = args.length;
for (; i < length; i++) { merge(target, args[i]); }
return target;
}
/* sizeIn(object): integer */
const sizeIn = (obj: object): number =>
Object.getOwnPropertyNames(obj).length
+ Object.getOwnPropertySymbols(obj).length;
/* unBind(function): function */
const unBind = (fn: Function): Function => Function.prototype.call.bind(fn);
/* bind(function, context: any): function */
/** @return {Function} */
const bind = Function.prototype.call.bind(Function.prototype.bind);
/* constant(value: unknown): unknown */
/**
* @description Returns a function that always returns the same value.
*
* @param {unknown} value
* @returns {unknown}
*/
const constant = (value: T): (() => T) => () => value;
/* identity(value: unknown): any */
/**
* @description Returns value unchanged.
*
* @param {unknown} value
* @returns {unknown}
*/
const identity = (value: T): T => value;
/* noop(): undefined */
/**
* @description A function that does nothing.
*
* @returns {void}
*/
function noop (): void {}
/* T(): true */
/**
* @description Always returns true.
*
* @returns {true}
*/
const T = (): boolean => true;
/* F(): false */
/**
* @description Always returns false.
*
* @returns {false}
*/
const F = (): boolean => false;
/* nanoid([size = 21 [,
alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"]])
: string */
function nanoid (
size = 21,
alphabet: string =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
): string {
let result: string = "";
let dl: number = alphabet.length;
let pos: number;
let index: number = size;
while (index--) {
do { pos = crypto.getRandomValues(new Uint8Array(1))[0]; } while
(pos >= dl);
result += alphabet[pos];
}
return result;
}
/* timestampID([size = 21
[, alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"]])
: string */
function timestampID (
size: number = 21,
alphabet: string =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
): string {
let result: string = Date.now().toString(36).padStart(10, "0") + "-";
let dl: number = alphabet.length;
let pos: number;
let index: number = ((size > 11) ? size : 12) - 11;
while (index--) {
do { pos = crypto.getRandomValues(new Uint8Array(1))[0]; } while
(pos >= dl);
result += alphabet[pos];
}
return result;
}
/** String API **/
/* b64Encode(s: any): string */
function b64Encode (str: any): string {
return btoa(encodeURIComponent(String(str)).replace(/%([0-9A-F]{2})/g,
function toSolidBytes (_match, p1): string {
// @ts-ignore
return String.fromCharCode("0x" + p1);
}
));
}
/* b64Decode(s: string): string */
function b64Decode (str: any): string {
return decodeURIComponent(atob(String(str)).split("").map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
}).join(""));
}
/* strTruncate(string: string, newLength: integer [, omission: string = ""]):
string */
function strTruncate (
str: any,
newLength: number,
omission: string = ""): string {
str = String(str);
omission = String(omission);
let strUC = Array.from(str);
if (newLength >= strUC.length) { return str; }
return strUC.slice(0, newLength-Array.from(omission).length).join("")
+ omission;
}
/* strPropercase(s: any): string */
const strPropercase = (str: any): string =>
String(str).trim().split(" ").map(function (value: string) {
let chars = Array.from(value).map( (c: string): string => c.toLowerCase() );
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}).join(" ");
/* strTitlecase(s: any): string */
const strTitlecase = (str: any): string =>
String(str).trim().split(" ").map(function (value: string) {
let chars = Array.from(value).map( (c: string): string => c.toLowerCase() );
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}).join(" ");
/* strCapitalize(s: any): string */
function strCapitalize (str: any): string {
let chars = [...String(str).trim().toLowerCase()];
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}
/* strUpFirst(s: any): string */
function strUpFirst (str: any): string {
let chars = [...String(str).trim()];
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}
/* strDownFirst(s: any): string */
function strDownFirst (str: any): string {
let chars = [...String(str).trim()];
if (chars.length) { chars[0] = chars[0].toLowerCase(); }
return chars.join("");
}
/* strReverse(s: any): string */
const strReverse = (str: any): string =>
Array.from(String(str)).reverse().join("");
/* strCodePoints(s: any): array of strings */
const strCodePoints = (str: any): any[] =>
Array.from(String(str), (value: string): number | undefined =>
value.codePointAt(0));
/* strFromCodePoints(iterator: iterator): string */
const strFromCodePoints = ([...array]): string =>
String.fromCodePoint(...array);
/* strAt(string: string, index: number [, newChar: string]): string */
function strAt (str: string, index: number, newChar?: string): string {
let chars: string[] = Array.from(String(str));
if (newChar == null) { return chars.at(index) || ""; }
index = index < 0 ? chars.length + index : index;
if (index > chars.length) { return chars.join(""); }
chars[index] = newChar;
return chars.join("");
}
/* strSplice(string: string, index: number, count: integer [, add: string]):
string */
const strSplice = (str: string, index: number,count: number, ...add: any[]): string =>
Array.from(str).toSpliced(index, count, add.join("")).join("");
/* strHTMLRemoveTags(s: any): string */
const strHTMLRemoveTags = (str: any): string =>
String(str).trim().replace(/<[^>]*>/g, " ").replace(/\s{2,}/g, " ").trim();
/* strHTMLEscape(str: any): string */
const strHTMLEscape = (str: any): string =>
String(str).trim()
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
/* strHTMLUnEscape(s: any): string */
const strHTMLUnEscape = (str: string): string =>
String(str).trim()
.replace(/&/g, "&").replace(/&/g, "&")
.replace(/</g, "<").replace(/</g, "<")
.replace(/>/g, ">").replace(/>/g, ">")
.replace(/"/g, '"').replace(/"/g, '"')
.replace(/'/g, "'").replace(/'/g, "'");
/** Type API **/
/* isTypedCollection (
iter: iterable,
expectedType: string | Function | Array,
Throw: boolean = false
): boolean | throw TypeError */
function isTypedCollection (
iter: IterableAndIterator,
expectedType: string | Function | Array,
Throw: boolean = false): boolean {
/* helper functions */
const _typeOf = (value: any): string =>
value === null ? "null" : typeof value;
const _isIterator = (value: any): boolean =>
value != null && typeof value === "object"
&& typeof value.next === "function";
const _isIterable = (value: any): boolean =>
value != null && typeof value[Symbol.iterator] === "function";
/* Validate `iter` */
if (!_isIterator(iter) && !_isIterable(iter)) {
throw new TypeError(
`[isTypedCollection] TypeError: iter must be iterable or iterator. Got ${_typeOf(iter)}`
);
}
/* Validate `expected` */
if (!(["string", "function"].includes(typeof expectedType))
&& !Array.isArray(expectedType)) {
throw new TypeError(
`[isTypedCollection] TypeError: expectedType must be string, function, array. Got ${_typeOf(expectedType)}`
);
}
/* Validate `Throw` */
if (typeof Throw !== "boolean") {
throw new TypeError(
`[isTypedCollection] TypeError: Throw has to be a boolean. Got ${typeof Throw}`
);
}
/* Normalize expected to an array */
let expectedArray: any[] =
Array.isArray(expectedType) ? expectedType : [expectedType];
/* Check values of iter against expected types or constructors */
let matched: boolean = true;
for (let value of iter as Iterable) {
const valueType: string = _typeOf(value);
matched = expectedArray.some(
function (item: string | Function): boolean {
if (typeof item === "string") { return valueType === item; }
if (typeof item === "function") {
return value != null && value instanceof item;
}
/* validate expected array elements */
throw new TypeError(
`[isTypedCollection] TypeError: expectedType array elements have to be a string or function. Got ${typeof item}`
);
}
);
if (!matched) { break; }
}
/* Throw error if mismatch and `Throw` is true */
if (Throw && !matched) {
let eNames: string = expectedArray.map((item: any): string =>
(typeof item === "string" ? item.toString() : item.name ?? "anonymous")
).join(", ");
throw new TypeError(
`[isTypedCollection] TypeError: one or more items are not ${eNames}`
);
}
return matched;
}
/* is (
value: unknown,
expectedType: string | Function | Array | undefined,
Throw: boolean = false
): string | Function | boolean | throw TypeError */
function is (
value: any,
expectedType?: string | Function | Array | undefined,
Throw: boolean = false): string | Function | boolean {
/* Validate `expected` */
if (!(["string", "function", "undefined"].includes(typeof expectedType))
&& !Array.isArray(expectedType)) {
throw new TypeError(
`[is] TypeError: expectedType must be string, function, array or undefined. Got ${typeof expectedType}`
);
}
/* Validate `Throw` */
if (typeof Throw !== "boolean") {
throw new TypeError(
`[is] TypeError: Throw has to be a boolean. Got ${typeof Throw}`
);
}
/* Determine the type of `value` */
const vType: string = (value === null ? "null" : typeof value);
/* If no expected type provided, return type or constructor */
if (expectedType == null) {
return vType === "object"
? Object.getPrototypeOf(value)?.constructor ?? "object"
: vType;
}
/* Normalize expected to an array */
let expectedArray: Array =
Array.isArray(expectedType) ? expectedType : [expectedType];
/* Check against expected types or constructors */
let matched: boolean = expectedArray.some(
function (item: string | Function) {
if (typeof item === "string") { return vType === item; }
if (typeof item === "function") {
return value != null && value instanceof item;
}
/* validate expected array elements */
throw new TypeError(
`[is] TypeError: expectedType array elements have to be a string or function. Got ${typeof item}`
);
}
);
/* Throw error if mismatch and `Throw` is true */
if (Throw && !matched) {
let vName: string =
value.toString ? value.toString() : Object.prototype.toString.call(value);
let eNames: string = expectedArray.map((item: any): string =>
(typeof item === "string" ? item.toString() : item.name ?? "anonymous")
).join(", ");
throw new TypeError(`[is] TypeError: ${vName} is not a ${eNames}`);
}
return matched;
}
/* toObject(value: unknown): object | symbol | Function | thrown error */
function toObject (value: unknown): Object | symbol | Function {
if (value == null) {
throw new TypeError("[toObject] error: " + value);
}
return (["object", "function"].includes(typeof value))
? value
: Object(value);
}
/* toPrimitiveValue(value: unknown): primitive | object | symbol | Function */
function toPrimitiveValue (value: unknown): any {
if (value == null || typeof value !== "object") { return value; }
const vType = Object.prototype.toString.call(value).slice(8, -1);
if (["Boolean", "BigInt", "Number", "String", "Symbol"].includes(vType)) {
return value.valueOf();
}
return value;
}
/**
* @description This function is a general purpose, type safe, predictable stringifier. Converts a value into a human-readable string for error messages Handles symbols, functions, nullish, circular references, etc.
*
* @param {unknown} value The value to inspect.
* @returns {string}
*/
function toSafeString (value: unknown): string {
const seen = new WeakSet