@apoyo/std
Version:
Typescript utility library
1,023 lines (1,004 loc) • 27.1 kB
JavaScript
// src/types.ts
var isNumber = (value) => typeof value === "number";
var isNaN2 = (value) => Number.isNaN(value);
var isNull = (value) => value === null;
var isUndefined = (value) => value === void 0;
var isObject = (input) => typeof input === "object" && input !== null;
var isFunction = (input) => typeof input === "function";
// src/pipe.ts
function pipe(a, ...fns) {
return fns.reduce((value, fn) => fn(value), a);
}
// src/flow.ts
function flow(...fns) {
return (a) => fns.reduce((value, fn) => fn(value), a);
}
// src/function.ts
function fcurry2(fn) {
return function(...args) {
return args.length === 1 ? (x) => fn(x, args[0]) : fn(args[0], args[1]);
};
}
var identity = (a) => a;
var constant = (a) => () => a;
var cast = (a) => a;
function not(predicate) {
return (value, indexOrKey) => !predicate(value, indexOrKey);
}
var tuple = (...t) => t;
var tupled = (f) => (a) => f(...a);
var untupled = (f) => (...a) => f(a);
function throwError(err) {
throw err;
}
var first = (a, _b) => a;
var last = (_a, b) => b;
var add = fcurry2((a, b) => a + b);
function or(...fns) {
return (value, indexOrKey) => fns.some((fn) => fn(value, indexOrKey));
}
function and(...fns) {
return (value, indexOrKey) => fns.every((fn) => fn(value, indexOrKey));
}
var once = (fn) => {
let result;
let done = false;
return (...args) => {
if (!done) {
result = fn(...args);
done = true;
}
return result;
};
};
var run = (fn) => fn();
// src/Option.ts
var isSome = (value) => value !== void 0;
var isNone = (value) => value === void 0;
var fromNullable = (value) => value === null ? void 0 : value;
var fromFalsy = (value) => !value ? void 0 : value;
var fromString = (value) => value === "" ? void 0 : value;
var fromNumber = (value) => isNaN(value) ? void 0 : value;
var fromDate = (value) => isNaN(value.getTime()) ? void 0 : value;
var map = (fn) => (value) => isSome(value) ? fn(value) : void 0;
function filter(fn) {
return (value) => isSome(value) && fn(value) ? value : void 0;
}
function reject(fn) {
return filter(not(fn));
}
function get(valueOrFn) {
return (value) => isSome(value) ? value : typeof valueOrFn === "function" ? valueOrFn() : valueOrFn;
}
function throwError2(errOrFn) {
return (value) => isSome(value) ? value : typeof errOrFn === "function" ? throwError(errOrFn()) : throwError(errOrFn);
}
var Option = {
isSome,
isNone,
map,
filter,
reject,
get,
throwError: throwError2,
fromNullable,
fromFalsy,
fromString,
fromNumber,
fromDate
};
// src/Dict.ts
var isDict = (input) => typeof input === "object" && input !== null;
var isEmpty2 = (dict) => pipe(dict, keys, isEmpty);
var set = (key, value) => (dict) => (dict[key] = value, dict);
var lookup = (key) => (dict) => dict[key];
var get2 = lookup;
var reduce = (fn, initial) => (dict) => {
let result = initial;
const props = Object.keys(dict);
const len = props.length;
for (let i = 0; i < len; ++i) {
const key = props[i];
const value = dict[key];
result = fn(result, value, key);
}
return result;
};
var mapIndexed = (fn) => (dict) => pipe(dict, reduce((acc, value, key) => pipe(acc, set(key, fn(value, key))), {}));
var map2 = (fn) => mapIndexed((v) => fn(v));
function filter2(fn) {
return (arr) => pipe(arr, reduce((acc, value, key) => fn(value, key) ? pipe(acc, set(key, value)) : acc, {}));
}
function reject2(fn) {
return filter2(not(fn));
}
var filterMap = (fn) => (dict) => pipe(dict, reduce((acc, value, key) => pipe(fn(value, key), (value2) => isSome(value2) ? pipe(acc, set(key, value2)) : acc), {}));
var compact = (value) => pipe(value, filterMap(identity));
var collect = (fn) => (dict) => pipe(dict, reduce((acc, value, key) => (acc.push(fn(value, key)), acc), []));
function omit(props) {
const propsSet = new Set(props);
return Dict.reject((_, key) => propsSet.has(key));
}
function pick(props) {
const propsSet = new Set(props);
return Dict.filter((_, key) => propsSet.has(key));
}
var values = (dict) => pipe(dict, collect(identity));
var keys = (dict) => Object.keys(dict);
var fromPairs = (pairs) => {
const dict = {};
for (let i = 0; i < pairs.length; ++i) {
const [key, value] = pairs[i];
dict[key] = value;
}
return dict;
};
var toPairs = (dict) => pipe(dict, collect((value, key) => [key, value]));
var concat = (member) => (dict) => Object.assign({}, dict, member);
var union = (member) => (dict) => Object.assign({}, member, dict);
var intersect = (member) => (dict) => pipe(dict, filterMap((value, key) => isSome(member[key]) ? value : void 0));
var difference = (member) => (dict) => pipe(dict, filterMap((value, key) => isSome(member[key]) ? void 0 : value));
var Dict = {
isEmpty: isEmpty2,
lookup,
get: get2,
set,
map: map2,
mapIndexed,
filter: filter2,
reject: reject2,
filterMap,
compact,
reduce,
collect,
isDict,
keys,
values,
fromPairs,
toPairs,
concat,
union,
intersect,
difference,
omit,
pick
};
// src/Ord.ts
var Ordering = /* @__PURE__ */ ((Ordering2) => {
Ordering2[Ordering2["UP"] = 1] = "UP";
Ordering2[Ordering2["DOWN"] = -1] = "DOWN";
Ordering2[Ordering2["EQ"] = 0] = "EQ";
return Ordering2;
})(Ordering || {});
var string = (a, b) => a > b ? 1 : a === b ? 0 : -1;
var number = (a, b) => a > b ? 1 : a === b ? 0 : -1;
var boolean = (a, b) => a > b ? 1 : a === b ? 0 : -1;
var date = (a, b) => number(a.valueOf(), b.valueOf());
var contramap = (fn) => (ord) => (a, b) => ord(fn(a), fn(b));
var inverse = (ord) => (a, b) => ord(b, a);
var optional = (ord) => (a, b) => a === b ? 0 : isSome(a) ? isSome(b) ? ord(a, b) : -1 : 1;
var nullable = (ord) => (a, b) => a === b ? 0 : a !== null ? b !== null ? ord(a, b) : -1 : 1;
function concat2(...ords) {
return (a, b) => {
for (let i = 0; i < ords.length; ++i) {
const ord = ords[i];
const result = ord(a, b);
if (result !== 0) {
return result;
}
}
return 0;
};
}
function eq(ord) {
return fcurry2((x, y) => ord(x, y) === 0 /* EQ */);
}
function lt(ord) {
return fcurry2((x, y) => ord(x, y) < 0 /* EQ */);
}
function lte(ord) {
return fcurry2((x, y) => ord(x, y) <= 0 /* EQ */);
}
function gt(ord) {
return fcurry2((x, y) => ord(x, y) > 0 /* EQ */);
}
function gte(ord) {
return fcurry2((x, y) => ord(x, y) >= 0 /* EQ */);
}
function min(ord) {
return fcurry2((x, y) => ord(x, y) <= 0 /* EQ */ ? x : y);
}
function max(ord) {
return min(inverse(ord));
}
var Ord = {
string,
number,
boolean,
date,
contramap,
inverse,
optional,
nullable,
concat: concat2,
eq,
lt,
lte,
gt,
gte,
min,
max
};
// src/NonEmptyArray.ts
var of = (value) => [value];
function fromArray(arr) {
return isNonEmpty(arr) ? arr : void 0;
}
var head = (arr) => arr[0];
var last2 = (arr) => arr[arr.length - 1];
var mapIndexed2 = (fn) => (arr) => {
const res = [fn(arr[0], 0)];
for (let i = 1; i < arr.length; ++i) {
res.push(fn(arr[i], i));
}
return res;
};
var map3 = (fn) => (arr) => pipe(arr, mapIndexed2((value) => fn(value)));
var min2 = (ord) => (arr) => arr.reduce(min(ord), arr[0]);
var max2 = (ord) => min2(inverse(ord));
var sort2 = (ord) => sort(ord);
var NonEmptyArray = {
of,
fromArray,
head,
last: last2,
map: map3,
mapIndexed: mapIndexed2,
min: min2,
max: max2,
sort: sort2
};
// src/Result.ts
var ok = (value) => ({
_tag: "Result.Ok" /* Ok */,
ok: value
});
var ko = (value) => ({
_tag: "Result.Ko" /* Ko */,
ko: value
});
var fromOption = (onNone) => (option) => isSome(option) ? ok(option) : ko(onNone());
var isOk = (result) => result._tag === "Result.Ok" /* Ok */;
var isKo = (result) => result._tag === "Result.Ko" /* Ko */;
var isResult = (result) => isObject(result) && (result._tag === "Result.Ok" /* Ok */ || result._tag === "Result.Ko" /* Ko */);
var get3 = (result) => isOk(result) ? result.ok : throwError(result.ko);
var tuple2 = (result) => isOk(result) ? [result.ok, void 0] : [void 0, result.ko];
var map5 = (fn) => (result) => isOk(result) ? ok(fn(result.ok)) : result;
var mapError = (fn) => (result) => isKo(result) ? ko(fn(result.ko)) : result;
var join = (result) => pipe(result, chain(identity));
var chain = (fn) => (result) => isOk(result) ? fn(result.ok) : result;
var catchError = (fn) => (result) => isKo(result) ? fn(result.ko) : result;
var fold = (onOk, onKo) => (result) => {
return isOk(result) ? onOk(result.ok) : onKo(result.ko);
};
var swap = (result) => pipe(result, fold((value) => ko(value), (err) => ok(err)));
var tryCatch = (fn) => {
try {
return ok(fn());
} catch (err) {
return ko(err);
}
};
var tryCatchFn = (fun) => (...args) => tryCatch(() => fun(...args));
var unionBy = (fn) => (members) => {
const errors = [];
for (let i = 0; i < members.length; ++i) {
const result = fn(members[i], i);
if (Result.isOk(result)) {
return result;
}
errors.push(result.ko);
}
return Result.ko(errors);
};
var union2 = (members) => pipe(members, unionBy(identity));
var structBy = (fn) => (props) => {
const [success, errors] = pipe(toPairs(props), map4(([key, prop]) => pipe(fn(prop, key), Result.map((value) => [key, value]))), separate);
return errors.length > 0 ? Result.ko(errors) : Result.ok(fromPairs(success));
};
var struct = structBy(identity);
var Result = {
ok,
ko,
isOk,
isKo,
isResult,
fromOption,
get: get3,
tuple: tuple2,
map: map5,
mapError,
join,
chain,
catchError,
fold,
swap,
tryCatch,
tryCatchFn,
unionBy,
union: union2,
structBy,
struct
};
// src/Array.ts
var isArray = (arr) => Array.isArray(arr);
var isEmpty = (arr) => arr.length === 0;
var length = (arr) => arr.length;
var of2 = (value) => [value];
var from = (value) => Array.from(value);
var head2 = (arr) => arr.length > 0 ? arr[0] : void 0;
var last3 = (arr) => arr.length > 0 ? arr[arr.length - 1] : void 0;
var mapIndexed3 = (fn) => (arr) => arr.map(fn);
var map4 = (fn) => (arr) => arr.map((value) => fn(value));
var filterMap2 = (fn) => (arr) => {
const out = [];
for (let i = 0; i < arr.length; ++i) {
const result = fn(arr[i]);
if (isSome(result)) {
out.push(result);
}
}
return out;
};
var compact2 = (arr) => pipe(arr, filterMap2(identity));
var concat3 = (value) => (arr) => arr.concat(value);
var flatten = (arr) => [].concat.apply([], arr);
var chain2 = (fn) => (arr) => pipe(arr, map4(fn), flatten);
var chainIndexed = (fn) => (arr) => pipe(arr, mapIndexed3(fn), flatten);
var some = (fn) => (arr) => arr.some(fn);
var every = (fn) => (arr) => arr.every(fn);
var join2 = (sep) => (arr) => arr.join(sep);
function filter3(fn) {
return (arr) => arr.filter(fn);
}
function reject3(fn) {
return (arr) => arr.filter(not(fn));
}
var reduce2 = (fn, initial) => (arr) => arr.reduce(fn, initial);
var slice = (start, end) => (arr) => arr.slice(start, end);
var take = (nb) => slice(0, nb);
var skip = (nb) => slice(nb);
var sort = (ord) => (arr) => arr.map(of2).sort(pipe(ord, contramap(head))).map(head);
var reverse = (arr) => arr.slice().reverse();
var toDict = (fn, reducer, initial) => (arr) => {
const res = {};
for (let i = 0; i < arr.length; ++i) {
const value = arr[i];
const key = fn(value, i);
const curr = res[key];
res[key] = isSome(curr) ? reducer(curr, value) : initial(value);
}
return res;
};
var groupBy = (fn) => toDict(fn, (arr, value) => (arr.push(value), arr), of2);
var indexBy = (fn, strategy = last) => toDict(fn, strategy, identity);
var countBy = (fn) => toDict(fn, add(1), constant(1));
var chunksOf = (size) => (arr) => {
const count = Math.ceil(arr.length / size);
const chunks = Array(count);
for (let i = 0; i < count; ++i) {
const start = i * size;
const end = Math.min(start + size, arr.length);
chunks[i] = arr.slice(start, end);
}
return chunks;
};
function uniq(arr) {
return from(new Set(arr));
}
var uniqBy = (fn) => (arr) => pipe(arr, indexBy(fn, first), values);
var union3 = (fn, member) => (arr) => pipe(arr, indexBy(fn, first), union(pipe(member, indexBy(fn, first))), values);
var intersect2 = (fn, member) => (arr) => pipe(arr, indexBy(fn, first), intersect(pipe(member, indexBy(fn, first))), values);
var difference2 = (fn, member) => (arr) => pipe(arr, indexBy(fn, first), difference(pipe(member, indexBy(fn, first))), values);
var pluck = (key) => (arr) => arr.map((v) => v[key]);
function partition(fn) {
return partitionMap((value) => fn(value) ? ok(value) : ko(value));
}
var partitionMap = (fn) => (arr) => {
const ok2 = [];
const ko2 = [];
for (let i = 0; i < arr.length; ++i) {
const value = arr[i];
const res = fn(value);
if (isOk(res)) {
ok2.push(res.ok);
} else {
ko2.push(res.ko);
}
}
return [ok2, ko2];
};
var separate = (arr) => pipe(arr, partitionMap(identity));
var isNonEmpty = (arr) => arr.length > 0;
var min3 = (ord) => (arr) => isNonEmpty(arr) ? pipe(arr, min2(ord)) : void 0;
var max3 = (ord) => min3(inverse(ord));
var find = (fn) => (arr) => arr.find(fn);
var includes = (fn) => (arr) => isSome(arr.find(fn));
var empty = () => [];
var sum = (arr) => arr.reduce(add, 0);
var sumBy = (fn) => (arr) => arr.reduce((a, b) => a + fn(b), 0);
var push = fcurry2((arr, value) => (arr.push(value), arr));
var Arr = {
of: of2,
from,
length,
isArray,
isEmpty,
isNonEmpty,
head: head2,
last: last3,
map: map4,
mapIndexed: mapIndexed3,
chain: chain2,
chainIndexed,
some,
every,
join: join2,
reduce: reduce2,
reject: reject3,
filter: filter3,
filterMap: filterMap2,
compact: compact2,
concat: concat3,
flatten,
slice,
take,
skip,
sort,
chunksOf,
groupBy,
countBy,
indexBy,
uniq,
uniqBy,
union: union3,
intersect: intersect2,
difference: difference2,
pluck,
partition,
partitionMap,
separate,
min: min3,
max: max3,
reverse,
find,
includes,
empty,
sum,
sumBy,
push
};
// src/List.ts
var init = () => ({
length: 0
});
var map6 = (fn) => (list) => {
const lb = init();
let elem = list.head;
while (elem) {
push2(lb, fn(elem.value));
elem = elem.next;
}
return lb;
};
var unshift = (queue, value) => {
const head3 = queue.head;
const item = {
next: head3,
prev: void 0,
value
};
if (head3) {
head3.prev = item;
}
if (!queue.last) {
queue.last = item;
}
queue.head = item;
queue.length++;
};
var push2 = (queue, value) => {
const last4 = queue.last;
const item = {
next: void 0,
prev: last4,
value
};
if (last4) {
last4.next = item;
}
if (!queue.head) {
queue.head = item;
}
queue.last = item;
queue.length++;
};
var shift = (queue) => {
const head3 = queue.head;
if (head3) {
queue.head = head3.next;
queue.length--;
}
if (queue.last === head3) {
queue.last = void 0;
}
return head3 && head3.value;
};
var pop = (queue) => {
const last4 = queue.last;
if (last4) {
queue.last = last4.prev;
queue.length--;
}
if (queue.head === last4) {
queue.head = void 0;
}
return last4 && last4.value;
};
var fromArray2 = (arr) => {
const queue = init();
for (let i = 0; i < arr.length; ++i) {
push2(queue, arr[i]);
}
return queue;
};
var toArray = (list) => {
const arr = [];
let elem = list.head;
while (elem) {
arr.push(elem.value);
elem = elem.next;
}
return arr;
};
var List = {
init,
map: map6,
fromArray: fromArray2,
toArray,
unshift,
shift,
push: push2,
pop
};
// src/Task.ts
var thunk = (fn) => ({
_tag: "Task",
then: (onResolve, onReject) => Promise.resolve().then(fn).then(onResolve, onReject)
});
var from2 = (promise) => thunk(() => promise);
var isTask = (value) => value._tag === "Task";
function of4(value = void 0) {
return thunk(() => of3(value));
}
var resolve = of4;
var reject5 = (value) => thunk(() => reject4(value));
var run2 = (task) => new Promise(task.then);
var map7 = (fn) => (task) => thunk(() => task.then(fn));
var mapError2 = (fn) => (task) => thunk(() => task.then(identity, (err) => reject4(fn(err))));
var chain3 = (fn) => (task) => thunk(() => task.then((v) => fn(v)));
var catchError2 = (fn) => (task) => thunk(() => task.then(identity, (err) => fn(err)));
var tap2 = (fn) => (task) => thunk(() => pipe(task, tap(fn)));
var tapError2 = (fn) => (task) => thunk(() => pipe(task, tapError(fn)));
var sleep2 = (ms) => thunk(() => sleep(ms));
var delay2 = (ms) => (task) => thunk(() => pipe(task, delay(ms)));
var all2 = (tasks) => thunk(() => all(tasks));
var sequence = (tasks) => thunk(async () => {
const res = [];
for (let i = 0; i < tasks.length; ++i) {
const task = tasks[i];
res.push(await task);
}
return res;
});
var concurrent = (concurrency) => (tasks) => thunk(async () => {
if (concurrency < 1) {
throw new Error(`Concurrency should be above 1 or above`);
}
if (concurrency === Number.POSITIVE_INFINITY || concurrency > tasks.length) {
concurrency = tasks.length;
}
const results = Array(tasks.length);
const queue = fromArray2(tasks.map((task, index) => ({
index,
task
})));
const loop = async () => {
let item = shift(queue);
while (item) {
const { index, task } = item;
results[index] = await task;
item = shift(queue);
}
};
const p = [];
for (let i = 0; i < concurrency; ++i) {
p.push(loop());
}
await all(p);
return results;
});
var tryCatch3 = (task) => thunk(() => tryCatch2(task));
var taskify = (fn) => (...args) => thunk(() => fn(...args));
var timeout2 = (ms, fn) => (task) => thunk(() => pipe(task, timeout(ms, fn)));
var struct2 = fcurry2((obj, strategy) => {
const toPairs3 = ([key, task]) => pipe(task, map7((v) => [key, v]));
return pipe(toPairs(obj), map4(toPairs3), strategy, map7(fromPairs));
});
var retry = (strategy) => (task) => {
const run3 = (attempt) => pipe(task, catchError2((err) => pipe(thunk(() => strategy(err, attempt)), chain3(() => run3(attempt + 1)))));
return run3(1);
};
var retryBy = (options) => {
const delay3 = options.delay || 0;
const when = options.when;
return retry((err, attempt) => {
if (attempt >= options.attempts) {
return Task.reject(err);
}
const next = when ? when(err) : true;
if (next) {
const timeout3 = typeof delay3 === "number" ? delay3 : delay3(attempt);
return sleep2(timeout3);
}
return Task.reject(err);
});
};
var Task = {
isTask,
of: of4,
resolve,
reject: reject5,
run: run2,
sleep: sleep2,
delay: delay2,
map: map7,
mapError: mapError2,
chain: chain3,
catchError: catchError2,
tap: tap2,
tapError: tapError2,
all: all2,
sequence,
concurrent,
tryCatch: tryCatch3,
thunk,
from: from2,
struct: struct2,
timeout: timeout2,
taskify,
retry,
retryBy
};
// src/Promise.ts
var thunk2 = (fn) => Promise.resolve().then(fn);
var of3 = (value) => Promise.resolve(value);
var resolve2 = of3;
var reject4 = (value) => Promise.reject(value);
var map8 = (fn) => then(fn);
var mapError3 = (fn) => (promise) => thunk2(() => promise.then(identity, (err) => reject4(fn(err))));
var chain4 = (fn) => then(fn);
var catchError3 = (fn) => (promise) => thunk2(() => promise.then(identity, (err) => fn(err)));
var then = (fn) => (promise) => thunk2(() => promise.then(fn));
var tap = (fn) => then((value) => thunk2(() => fn(value)).then(() => value));
var tapError = (fn) => (promise) => pipe(promise, catchError3((value) => thunk2(() => fn(value)).then(() => reject4(value))));
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
var delay = (ms) => (prom) => pipe(prom, tap(() => sleep(ms)));
var all = (promises) => Promise.all(promises);
var tryCatch2 = (promise) => thunk2(() => promise.then(ok, ko));
var timeout = (ms, fn) => (promise) => Promise.race([promise, pipe(Prom.sleep(ms), Prom.then(fn))]);
function struct3(obj) {
return pipe(obj, map2(from2), struct2(all2), run2);
}
var Prom = {
of: of3,
resolve: resolve2,
reject: reject4,
thunk: thunk2,
sleep,
delay,
map: map8,
mapError: mapError3,
chain: chain4,
catchError: catchError3,
then,
tap,
tapError,
all,
tryCatch: tryCatch2,
struct: struct3,
timeout
};
// src/Exception.ts
var Exception = class extends Error {
constructor(message, cause) {
super(message);
const proto = new.target.prototype;
if (Object.setPrototypeOf) {
Object.setPrototypeOf(this, proto);
} else {
this.__proto__ = proto;
}
Object.defineProperty(this, "name", {
configurable: true,
enumerable: false,
value: this.constructor.name,
writable: true
});
Object.defineProperty(this, "cause", {
configurable: true,
enumerable: false,
value: cause,
writable: true
});
}
};
// src/String.ts
var DOUBLE_BRACE_REGEXP = /{{(\d+|[a-z$_][a-z\d$_]*?(?:\.[a-z\d$_]*?)*?)}}/gi;
var BRACE_REGEXP = /{(\d+|[a-z$_][a-z\d$_]*?(?:\.[a-z\d$_]*?)*?)}/gi;
var of5 = (value) => String(value);
var length2 = (str) => str.length;
var isEmpty3 = (str) => str.length === 0;
function oneOf(arr) {
const set2 = new Set(arr);
return (str) => set2.has(str);
}
var concat4 = (append) => (str) => str + append;
var split = (sep) => (str) => str.split(sep);
var lower = (str) => str.toLowerCase();
var upper = (str) => str.toUpperCase();
var capitalize = (str) => str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
var truncate = (maxLength, suffix = "...") => (str) => str.length > maxLength ? str.slice(0, maxLength) + suffix : str;
var replace = (regexp, replacer) => (str) => str.replace(regexp, replacer);
var replaceAll = (regexp, replacer) => replace(new RegExp(regexp, "g"), replacer);
var regexpEscape = flow(replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"), replace(/-/g, "\\x2d"));
var htmlEscape = flow(replace(/&/g, "&"), replace(/"/g, """), replace(/'/g, "'"), replace(/`/g, "`"), replace(/</g, "<"), replace(/>/g, ">"));
var htmlUnescape = flow(replace(/>/g, ">"), replace(/</g, "<"), replace(/`/g, "`"), replace(/�?39;/g, "'"), replace(/"/g, '"'), replace(/&/g, "&"));
var template = (info2) => flow(replace(DOUBLE_BRACE_REGEXP, (_, key) => pipe(info2, property(key), of5, htmlEscape)), replace(BRACE_REGEXP, (_, key) => pipe(info2, property(key), of5)));
var eq2 = pipe(string, eq);
var WHITESPACE_CHARS = [
" ",
"\f",
"\n",
"\r",
" ",
"\v",
"\xA0",
"\u1680",
"\u2000",
"\u200A",
"\u2028",
"\u2029",
"\u202F",
"\u205F",
"\u3000",
"\uFEFF"
];
var trimWhile = (fn) => {
return (str) => {
let start = 0;
let end = str.length;
while (start < end && fn(str[start]))
++start;
while (end > start && fn(str[end - 1]))
--end;
return start > 0 || end < str.length ? str.substring(start, end) : str;
};
};
var isWhitespace = oneOf(WHITESPACE_CHARS);
var trim = trimWhile(isWhitespace);
var Str = {
of: of5,
length: length2,
isEmpty: isEmpty3,
oneOf,
concat: concat4,
lower,
upper,
capitalize,
truncate,
split,
replace,
replaceAll,
template,
regexpEscape,
htmlEscape,
htmlUnescape,
eq: eq2,
isWhitespace,
trimWhile,
trim
};
// src/Object.ts
var copy = (member) => Object.assign({}, member);
function merge(...members) {
return Object.assign({}, ...members);
}
var property = (path) => (obj) => pipe(path, split("."), reduce2((obj2, prop) => obj2 ? obj2[prop] : void 0, obj));
var omit2 = omit;
var pick2 = pick;
var compact3 = (obj) => {
const out = { ...obj };
for (const key in out) {
if (key === void 0) {
delete out[key];
}
}
return out;
};
var Obj = {
copy,
merge,
property,
omit: omit2,
pick: pick2,
compact: compact3
};
// src/Err.ts
var INFO_RESERVED = /* @__PURE__ */ new Set(["message", "stack", "cause"]);
var isNotReserved = (_, key) => !INFO_RESERVED.has(key);
var info = (err) => {
return pipe(merge(toError(err)), filter2(isNotReserved));
};
var fullInfo = (err) => {
const infos = pipe(err, toError, toArray2, filterMap2(info), reverse);
return merge(...infos);
};
var fullStack = (err) => pipe(err, toError, toArray2, filterMap2((err2) => err2.stack), join2(`
caused by: `));
var of6 = (msg, info2 = {}, cause, constructorOpt) => {
const data = pipe(info2, filter2(isNotReserved));
const message = pipe(msg, template(data));
const e = new Exception(message, cause);
Object.assign(e, data);
Error.captureStackTrace(e, constructorOpt || of6);
return e;
};
var toError = (err) => err instanceof Error ? err : of6(String(err));
var toArray2 = (err) => {
const errors = [];
let cur = toError(err);
while (cur) {
errors.push(cur);
cur = cur.cause;
}
return errors;
};
function wrap(msg, info2) {
return function _wrap(e) {
const err = toError(e);
return of6(msg, info2, err, _wrap);
};
}
function chain5(msg, info2) {
return function _chain(e) {
const err = toError(e);
return of6(`${msg}: ${err.message}`, info2, err, _chain);
};
}
var find2 = (fn) => (source) => {
let cur = toError(source);
while (cur) {
const found = fn(cur);
if (found) {
return cur;
}
cur = cur.cause;
}
return void 0;
};
var has = (fn) => (source) => pipe(source, find2(fn), (value) => value ? true : false);
var hasName = (name) => has((info2) => info2.name === name);
var format = (e) => {
const err = toError(e);
const stack = fullStack(err);
const i = fullInfo(err);
return {
name: i.name ? String(i.name) : err.name,
message: err.message,
stack,
info: i
};
};
var omitStack = omit2(["stack"]);
var Err = {
of: of6,
toError,
wrap,
chain: chain5,
find: find2,
has,
hasName,
format,
omitStack
};
// src/Tree.ts
var of7 = (value, forest = []) => ({
value,
forest
});
var draw = (tree) => tree.value + drawForest("\n", tree.forest);
var drawForest = (indentation, forest) => {
let r = "";
const len = forest.length;
let tree;
for (let i = 0; i < len; i++) {
tree = forest[i];
const isLast = i === len - 1;
r += indentation + (isLast ? "\u2514" : "\u251C") + "\u2500 " + tree.value;
r += drawForest(indentation + (len > 1 && !isLast ? "\u2502 " : " "), tree.forest);
}
return r;
};
var Tree = {
of: of7,
draw
};
// src/Enum.ts
var keys2 = (enumType) => Object.keys(enumType).filter((key) => isNaN(Number(key)));
function values2(enumType) {
return keys2(enumType).map((key) => enumType[key]);
}
var toPairs2 = (enumType) => keys2(enumType).map((key) => [key, enumType[key]]);
var isEnum = (enumType) => {
const set2 = new Set(values2(enumType));
return (input) => set2.has(input);
};
var Enum = {
keys: keys2,
values: values2,
toPairs: toPairs2,
isEnum
};
export {
Arr,
Dict,
Enum,
Err,
Exception,
List,
NonEmptyArray,
Obj,
Option,
Ord,
Ordering,
Prom,
Result,
Str,
Task,
Tree,
add,
and,
cast,
constant,
fcurry2,
first,
flow,
identity,
isFunction,
isNaN2 as isNaN,
isNull,
isNumber,
isObject,
isUndefined,
last,
not,
once,
or,
pipe,
run,
throwError,
tuple,
tupled,
untupled
};