native-dash
Version:
a replacement of lodash functions that are exported in both CJS and ES but where there are zero dependencies ... just modern JS code.
680 lines (635 loc) • 19.6 kB
JavaScript
// src/atRandom.ts
function atRandom(things, excluding = []) {
things = things.filter(
(i) => typeof excluding === "function" ? excluding(i) : !excluding.includes(i)
);
const random = Math.floor(Math.random() * things.length);
return things[random];
}
// src/base64.ts
function toBase64(input) {
const buffer = Buffer.from(input, "utf-8");
return buffer.toString("base64");
}
function fromBase64(input, isJson = false) {
const buffer = Buffer.from(input, "base64");
return isJson ? JSON.parse(buffer.toString("utf-8")) : buffer.toString("utf-8");
}
// src/between.ts
function between(start, end) {
const diff = Math.abs(end - start) + 1;
const random = Math.floor(Math.random() * diff);
return start + random;
}
// src/capitalize.ts
function capitalize(input) {
return input.slice(0, 1).toUpperCase() + input.slice(1);
}
// src/pascalize.ts
function pascalize(input, preserveWhitespace = void 0) {
const [_, preWhite, focus, postWhite] = /^(\s*)(.*?)(\s*)$/.exec(
input
);
const convertInteriorToCap = (i) => i.replace(/[ |_|-]+([0-9]*?[a-z|A-Z]{1})/gs, (_2, p1) => p1.toUpperCase());
const startingToCap = (i) => i.replace(/^[_|-]*?([0-9]*?[a-z]{1})/gs, (_2, p1) => p1.toUpperCase());
const replaceLeadingTrash = (i) => i.replace(/^[-_]/s, "");
const replaceTrailingTrash = (i) => i.replace(/[-_]$/s, "");
const pascal = `${preserveWhitespace ? preWhite : ""}${capitalize(
replaceTrailingTrash(replaceLeadingTrash(convertInteriorToCap(startingToCap(focus))))
)}${preserveWhitespace ? postWhite : ""}`;
return pascal;
}
// src/camelize.ts
function camelize(input, preserveWhitespace) {
const pascal = preserveWhitespace ? pascalize(input, preserveWhitespace) : pascalize(input);
const [_, preWhite, focus, postWhite] = /^(\s*)(.*?)(\s*)$/.exec(
pascal
);
const camel = (preserveWhitespace ? preWhite : "") + focus.replace(/^.*?([0-9]*?[a-z|A-Z]{1})/s, (_2, p1) => p1.toLowerCase()) + (preserveWhitespace ? postWhite : "");
return camel;
;
}
// src/createLookup.ts
var defaultMiss = (missed) => {
throw new Error(`Failure in lookup searching for "${missed}"`);
};
function createLookup(known, miss = defaultMiss) {
return (v) => {
const value = v === true ? "true" : v === false ? "false" : v;
return value in known ? known[value] : miss(value);
};
}
// src/dasherize.ts
function dasherize(input, preserveWhitespace) {
const [_, preWhite, focus, postWhite] = /^(\s*)(.*?)(\s*)$/.exec(input);
const replaceWhitespace = (i) => i.replace(/\s/gs, "-");
const replaceUppercase = (i) => i.replace(/[A-Z]/g, (c) => `-${c[0].toLowerCase()}`);
const replaceLeadingDash = (i) => i.replace(/^-/s, "");
const replaceTrailingDash = (i) => i.replace(/-$/s, "");
const replaceUnderscore = (i) => i.replace(/_/g, "-");
const removeDupDashes = (i) => i.replace(/-+/g, "-");
return `${preWhite}${replaceUnderscore(
replaceTrailingDash(
replaceLeadingDash(removeDupDashes(replaceWhitespace(replaceUppercase(focus))))
)
)}${postWhite}`;
}
// src/types/other-types.ts
var DataType = /* @__PURE__ */ ((DataType2) => {
DataType2["null"] = "null";
DataType2["string"] = "string";
DataType2["number"] = "number";
DataType2["bigint"] = "bigint";
DataType2["symbol"] = "symbol";
DataType2["boolean"] = "boolean";
DataType2["function"] = "function";
DataType2["undefined"] = "undefined";
DataType2["dictionary"] = "dictionary";
DataType2["object"] = "object";
DataType2["array"] = "array";
DataType2["stringArray"] = "string[]";
DataType2["numberArray"] = "number[]";
DataType2["booleanArray"] = "boolean[]";
DataType2["symbolArray"] = "symbol[]";
DataType2["functionArray"] = "function[]";
DataType2["undefinedArray"] = "undefined[]";
DataType2["nullArray"] = "null[]";
DataType2["objectArray"] = "object[]";
DataType2["dictionaryArray"] = "dictionary[]";
return DataType2;
})(DataType || {});
function isNonNullObject(thingy) {
return typeof thingy === "object" && thingy !== null;
}
// src/describe.ts
function describe(data) {
if (!isNonNullObject(data)) {
return data === null ? "null" /* null */ : DataType[typeof data];
}
if (Array.isArray(data)) {
if (data.length === 0) {
return "array" /* array */;
}
const SAMPLE_SIZE = 5;
const partial = data.slice(0, SAMPLE_SIZE);
const elements = partial.map((p) => describe(p));
return elements;
}
if (Object.keys(data).length === 0) {
return "object" /* object */;
}
const dictionary = data;
const dataStruct = Object.keys(dictionary).reduce((agg, key) => {
return {
...agg,
...isNonNullObject(dictionary[key]) ? { [key]: describe(dictionary[key]) } : { [key]: typeof dictionary[key] }
};
}, {});
return dataStruct;
}
// src/deserialize.ts
function deserialize(arr) {
return arr.split("\n").map((i) => JSON.parse(i));
}
// src/errors.ts
import { createError } from "brilliant-errors";
var [KnownError, isKnownError] = createError("KnownError", "NativeDash")("cardinality", "network", "invalid-type", "missing-resource", "not-allowed")()()();
var [UnknownError, isUnknownError] = createError("KnownError", "NativeDash")()()()();
// src/equal.ts
import { dictToKv } from "inferred-types";
function type(v) {
return Array.isArray(v) ? "array" /* array */ : v === null ? "null" /* null */ : typeof v;
}
function equal(a, b, depth = 1) {
const ta = type(a);
const tb = type(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case "null" /* null */:
case void 0:
return true;
case "boolean":
case "string":
case "symbol":
case "number":
case "bigint":
return a === b;
case "array" /* array */:
if (a.length !== b.length) {
return false;
}
return a.every((v, idx) => equal(v, b[idx]));
case "object":
const ka = dictToKv(a);
const kb = dictToKv(b);
if (ka.length !== kb.length) {
return false;
}
return ka.every(
(i) => type(i.value) === "object" ? depth > 0 ? equal(i.value, b[i.key], depth - 1) : false : i.value === b[i.key]
);
default:
return a === b;
}
}
// src/find.ts
var find = (pattern, ...names) => (content) => {
let re;
try {
re = new RegExp(pattern);
} catch {
throw new KnownError(
`Invalid RegExp pattern passed into find(): ${pattern}`,
"invalid-type/RegExp"
);
}
if (names && names.includes("all")) {
throw new KnownError(
`The name "all" can not be used in find() because an "all" value will always be passed back!`,
"not-allowed/named-property"
);
}
const found = content.match(re);
const arr = [];
const obj = {};
if (found) {
for (let idx = 0; idx < found.length; idx++) {
arr.push(found[idx]);
if (names.length > 0) {
const key = idx === 0 ? "all" : idx - 1 < names.length ? names[idx - 1] : `unknown_${idx}`;
obj[key] = found[idx];
}
}
}
return found ? names.length > 0 ? {
...obj,
found: true,
next: () => {
const nextContent = content.replace(obj.all, "");
return find(pattern, ...names)(nextContent);
}
} : arr : names.length > 0 ? { found: false } : false;
};
// src/findAll.ts
function reduceToFindAllResult(result) {
const blob = { ...result };
delete blob.found;
delete blob.next;
return blob;
}
function isNamedFind(result) {
return typeof result === "object" && !Array.isArray(result);
}
function isUnnamedFind(result) {
return !isNamedFind(result);
}
var findAll = (pattern, ...names) => (content) => {
let re;
try {
re = new RegExp(pattern);
} catch {
throw new KnownError(
`Invalid RegExp pattern passed into findAll(): ${pattern}`,
"invalid-type/RegExp"
);
}
let result = find(pattern, ...names)(content);
let output = [];
if (isNamedFind(result)) {
const results = [];
while (result.found) {
results.push(reduceToFindAllResult(result));
result = result.next();
}
output = results;
}
if (isUnnamedFind(result)) {
const results = [];
while (result) {
results.push(result);
const newContent = content.replace(result[0], "");
result = find(pattern, ...names)(newContent);
}
output = results;
}
return output;
};
// src/first.ts
function first(arr) {
return arr.slice(0, 1)[0];
}
// src/firstKey.ts
function firstKey(dict) {
const key = Object.keys(dict).slice(0, 1).pop();
return key ? key : false;
}
// src/flatten.ts
function flatten(arr) {
return arr.flat ? arr.flat() : arr.reduce((acc, val) => acc.concat(val), []);
}
// src/get.ts
function get(obj, dotPath, defaultValue) {
const parts = dotPath.split(".");
let value = obj;
parts.forEach((p) => {
value = typeof value === "object" && Object.keys(value).includes(p) ? value[p] : void 0;
});
return value ? value : defaultValue;
}
// src/omit.ts
function omit(obj, ...removals) {
const untyped = removals;
return Object.fromEntries(
Object.entries(obj).filter(([key]) => !untyped.includes(key))
);
}
// src/groupBy.ts
function isFunction(thingy) {
return typeof thingy === "function";
}
function groupBy(propOrFn, data) {
return data.reduce((acc, i) => {
if (isFunction(propOrFn)) {
const [key, val] = propOrFn(i);
const current = acc[key] || [];
return {
...acc,
[key]: current.concat(val)
};
} else {
const key = i[propOrFn];
const current = acc[key] || [];
if (Array.isArray(current)) {
return { ...acc, [key]: current.concat(omit(i, propOrFn)) };
}
}
}, {});
}
// src/randomString.ts
function randomString() {
return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1);
}
// src/uuid.ts
function uuid(dasherized = true) {
return dasherized ? randomString() + randomString() + "-" + randomString() + "-" + randomString() + "-" + randomString() + "-" + randomString() + randomString() + randomString() : randomString() + randomString() + randomString() + randomString() + randomString() + randomString() + randomString() + randomString();
}
// src/guid.ts
function guid() {
return uuid();
}
// src/hash.ts
function hash(digest) {
let hash2 = 0, i, chr;
for (i = 0; i < digest.length; i++) {
chr = digest.charCodeAt(i);
hash2 = (hash2 << 5) - hash2 + chr;
hash2 |= 0;
}
return hash2;
}
// src/initials.ts
function initials(input, strategy = "all") {
let re;
let takeFirst = false;
switch (strategy) {
case "all":
re = /(\s+|[A-Z]{1}|-[a-zA-Z]{1}|_[a-zA-Z]{1}|\.[a-zA-Z]{1}|[0-9]+)/g;
takeFirst = true;
break;
default:
throw new Error("only the 'all' strategy is implemented currently");
}
const trimmed = input.trim();
const first2 = takeFirst ? trimmed.slice(0, 1).toUpperCase() : "";
const rest = takeFirst ? trimmed.slice(1) : trimmed;
const parts = rest.split(re).filter((i) => i.trim() && i.match(re));
const breakChars = ["_", "-"];
const remaining = parts.map((i) => {
const atBreak = i.slice(0, 1);
return breakChars.includes(atBreak) ? i.slice(1).toUpperCase() : atBreak.toUpperCase();
});
return [first2, ...remaining].join("");
}
// src/isEven.ts
function isEven(value) {
return value % 2 ? false : true;
}
// src/isLeapYear.ts
function isLeapYear(year) {
const y = typeof year === "number" ? year : year.getFullYear();
return new Date(y, 1, 29).getDate() === 29;
}
// src/isOdd.ts
function isOdd(value) {
return value % 2 ? true : false;
}
// src/isUuid.ts
function isUuid(candidate, allowNonDashedForm) {
const dasherizedGuid = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/;
const plainGuid = /^(\{{0,1}([0-9a-fA-F]){32}\}{0,1})$/;
return allowNonDashedForm === true ? plainGuid.test(candidate) || dasherizedGuid.test(candidate) : dasherizedGuid.test(candidate);
}
// src/keys.ts
function keys(obj) {
return Object.keys(obj);
}
// src/last.ts
function last(arr) {
return arr.slice(-1)[0];
}
// src/lastKey.ts
function lastKey(dict) {
const key = Object.keys(dict).slice(-1).pop();
return key ? key : false;
}
// src/pathJoin.ts
function pathJoin(...args) {
const leadingSlash = args[0] && (args[0].startsWith("/") || args[0].startsWith("\\"));
const parts = args.filter((i) => i).map((i) => removeSlashAtFrontAndBack(makeForwardSlashBeBackward(i)));
if (parts.slice(1).some((i) => i.includes(".."))) {
throw new Error(
`pathJoin() only accepts the ".." notation at the beginning of the first string and no where else. Input was invalid: ${JSON.stringify(
args
)}`
);
}
return `${leadingSlash ? "/" : ""}${parts.join("/")}`;
}
function removeSlashAtFrontAndBack(input) {
input = input.startsWith("/") ? input.slice(1) : input;
input = input.endsWith("/") ? input.slice(0, input.length - 1) : input;
return input;
}
function makeForwardSlashBeBackward(input) {
return input.replace(/\\/gs, "/");
}
// src/pluralize.ts
var defaultRules = [
[/(us)$/i, (i) => `${i.replace(/us$/, "")}i`, ["bus", "us"]],
[/(is)$/i, (i, r) => `${i.replace(r, "")}es`],
[/(s|sh|ch|x|z|o)$/, (i) => `${i}es`],
[/fe{0,1}$/i, (i, r) => `${i.replace(r, "")}ves`],
[
/[b|c|d|f|g|h|j|k|l|m|n|p|q|r|s|t|v|w|x|z|y]y$/i,
(i) => `${i.slice(0, i.length - 1)}ies`
]
];
function pluralize(input, options = {}) {
if (input === "") {
if (options.ignoreEmptyStrings)
return "";
throw new Error("Attempt to pluralize an empty string");
}
const defaultExceptions = [
[/(.*)(photo)$/i, "$1$2s"],
[/(.*)(piano)$/i, "$1$2s"],
[/(.*)(halo)$/i, "$1$2s"],
[/(.*)(foot)$/i, "$1feet"],
[/(.*)(man)$/i, "$1men"],
[/(.*)(pe)rson$/i, "$1$2ople"],
[/(.*)(mouse)$/i, "$1mice"],
[/(.*)(series)$/i, "$1series"],
[/(.*)(sheep)$/i, "$1sheep"],
[/(.*)(deer)$/i, "$1deer"],
[/^(fun)$/i, "$1"]
];
const exceptions = [
...defaultExceptions,
...options.bespokeExceptions ? options.bespokeExceptions : []
].filter((e) => {
const [re, _] = e;
return re.test(input.toLowerCase());
});
if (exceptions.length > 0) {
const [re, result] = exceptions[0];
return input.replace(re, result);
}
const pRules = options.rules || options.additionalRules ? defaultRules.concat(...options.additionalRules) : defaultRules;
let index = 0;
const rules = pRules.filter(
(r) => r[0 /* regex */].test(input.toLowerCase()) && !(r[2 /* exceptions */] || []).includes(input)
);
if (rules.length > 0) {
const [r, fn, exceptions2] = rules[0];
return fn(input, r, exceptions2 || []);
} else {
return `${input}s`;
}
}
// src/retain.ts
function retain(obj, ...retainedProps) {
const untyped = retainedProps;
return Object.fromEntries(
Object.entries(obj).filter(([key]) => untyped.includes(key))
);
}
// src/serialize.ts
function serialize(arr) {
return arr.map((i) => JSON.stringify(i)).join("\n");
}
// src/set.ts
function set(obj, dotPath, value, createIfNonExistant = true) {
if (!dotPath) {
throw new Error(`Attempt to set value into a dotPath but the dotPath was empty!`);
}
const parts = dotPath.split(/\??\./);
const allButLast = parts.slice(0, parts.length - 1);
const key = parts.pop();
let ref = obj;
allButLast.forEach((p) => {
if (!ref[p]) {
if (createIfNonExistant) {
ref[p] = {};
} else {
throw new Error(
`The dotPath -- ${dotPath} -- does not exist in the passed in object. You must either expressly state that you want the object structure created or this a real error that must be addressed otherwise. The part of the path which this failed on was "${p}".`
);
}
} else if (typeof ref[p] !== "object") {
throw new Error(
`Failed to set the path of "${dotPath}" of the passed in base object because the base object had a scalar value along that path and setting this would have changed the object's data structure in way which is not allowed! The scalar value was found in the "${p}" component of the path.`
);
}
ref = ref[p];
});
ref[key] = value;
}
// src/snakerize.ts
function snakerize(input, preserveWhitespace = false) {
const [_, preWhite, focus, postWhite] = /^(\s*)(.*?)(\s*)$/.exec(input);
const convertInteriorSpace = (input2) => input2.replace(/\s+/gs, "_");
const convertDashes = (input2) => input2.replace(/-/gs, "_");
const injectUnderscoreBeforeCaps = (input2) => input2.replace(/([A-Z])/gs, "_$1");
const removeLeadingUnderscore = (input2) => input2.startsWith("_") ? input2.slice(1) : input2;
return ((preserveWhitespace ? preWhite : "") + removeLeadingUnderscore(
injectUnderscoreBeforeCaps(convertDashes(convertInteriorSpace(focus)))
).toLowerCase() + (preserveWhitespace ? postWhite : "")).replace(/__/g, "_");
}
// src/unique.ts
function unique(list, property) {
return Array.from(new Set(list.map((i) => i[property])));
}
// src/formatting/private/constants.ts
var RESET_FG = `\x1B[39m`;
var RESET_BG = `\x1B[49m`;
var COLOR = {
black: [30, 40],
red: [31, 41],
magenta: [35, 45],
yellow: [33, 43],
green: [32, 42],
brightRed: [91, 40],
brightGreen: [92, 42],
brightYellow: [93, 43]
};
// src/formatting/private/paint.ts
function paint(text = "", fg, bg) {
const foreground = "\x1B[" + fg(COLOR)[0] + "m";
const bgc = bg ? bg(COLOR)[1] : null;
const background = bgc ? "\x1B[" + bgc + "m" : "";
const reset = background ? `${RESET_FG}${RESET_BG}` : `${RESET_FG}`;
return `${RESET_FG}${foreground}${background}${text}${reset}`;
}
// src/formatting/format.ts
function italicize(text = "") {
return `\x1B[3m${text}\x1B[0m`;
}
function underline(text = "") {
return `\x1B[4m${text}\x1B[0m`;
}
function strikethrough(text = "") {
return `\x1B[9m${text}\x1B[0m`;
}
// src/formatting/private/replace.ts
function replace(find2, corpus, formatting, global = true) {
const re = new RegExp(find2, global ? "gs" : "s");
let replacement = find2;
if (formatting.color)
replacement = paint(replacement, formatting.color, formatting.bg);
if (formatting.italics)
replacement = italicize(replacement);
if (formatting.underline)
replacement = underline(replacement);
if (formatting.strikeThrough)
replacement = strikethrough(replacement);
return corpus.replace(re, replacement);
}
// src/formatting/color.ts
var color = {
red: (text = "", bg) => {
return paint(text, (c) => c.red, bg);
},
magenta: (text = "", bg) => {
return paint(text, (c) => c.magenta, bg);
},
black: (text = "", bg) => {
return paint(text, (c) => c.black, bg);
},
yellow: (text = "", bg) => {
return paint(text, (c) => c.yellow, bg);
},
green: (text = "", bg) => {
return paint(text, (c) => c.green, bg);
},
brightRed: (text = "", bg) => {
return paint(text, (c) => c.brightRed, bg);
}
};
export {
COLOR,
DataType,
KnownError,
RESET_BG,
RESET_FG,
UnknownError,
atRandom,
between,
camelize,
capitalize,
color,
createLookup,
dasherize,
describe,
deserialize,
equal,
find,
findAll,
first,
firstKey,
flatten,
fromBase64,
get,
groupBy,
guid,
hash,
initials,
isEven,
isKnownError,
isLeapYear,
isNonNullObject,
isOdd,
isUnknownError,
isUuid,
italicize,
keys,
last,
lastKey,
omit,
paint,
pascalize,
pathJoin,
pluralize,
randomString,
replace,
retain,
serialize,
set,
snakerize,
strikethrough,
toBase64,
underline,
unique,
uuid
};