@allmaps/stdlib
Version:
Allmaps Standard Library
169 lines (168 loc) • 5.55 kB
JavaScript
import { isEqual, cloneDeep } from 'lodash-es';
export function degreesToRadians(degrees) {
return degrees * (Math.PI / 180);
}
export function radiansToDegrees(radians) {
return radians * (180 / Math.PI);
}
export function angle(line) {
return Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0]);
}
export function bearing(line) {
return angle(line) - Math.PI / 2;
}
// Define vanilla groupBy function, since official one is only baseline 2024
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy
// Vanilla code from https://stackoverflow.com/a/62765924/2386673
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function groupBy(arr, key) {
return arr.reduce((groups, item) => {
;
(groups[key(item)] ||= []).push(item);
return groups;
}, {});
}
// Note: this checks equality of the object
// which is only a good idea for primitive types (string, number), not JSON objects
export function isEqualArray(array0, array1, isEqualObject = (t0, t1) => t0 == t1) {
if (array0.length !== array1.length) {
return false;
}
for (let i = 0; i < array0.length; i++) {
if (!isEqualObject(array0[i], array1[i])) {
return false;
}
}
return true;
}
// Returns objects in array0 that are not in array1
export function arrayDifference(array0, array1, isEqualObject = (t0, t1) => t0 == t1) {
const result = [];
for (let i = 0; i < array0.length; i++) {
let found = false;
for (let j = 0; j < array1.length; j++) {
if (isEqualObject(array0[i], array1[j])) {
found = true;
break;
}
}
if (!found) {
result.push(array0[i]);
}
}
return result;
}
export function arrayUnique(array, isEqualObject = (t0, t1) => t0 == t1) {
const result = [];
for (let i = 0; i < array.length; i++) {
let found = false;
for (let j = 0; j < i; j++) {
if (isEqualObject(array[i], array[j])) {
found = true;
break;
}
}
if (!found) {
result.push(array[i]);
}
}
return result;
}
export function arrayRepeated(array, isEqualObject = (t0, t1) => t0 == t1) {
const result = [];
for (let i = 0; i < array.length; i++) {
let found = false;
for (let j = 0; j < i; j++) {
if (isEqualObject(array[i], array[j])) {
found = true;
break;
}
}
if (found) {
result.push(array[i]);
}
}
return result;
}
// TODO: replace with Set subset once available
// Note: this checks equality of the object
// which is only a good idea for primitive types (string, number), not JSON objects
export function subSetArray(arr1, arr2) {
for (let i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) === -1) {
return false;
}
}
return true;
}
// TODO: Replace with Set equality once available
// Note: this checks equality of the object
// which is only a good idea for primitive types (string, number), not JSON objects
export function equalSet(set1, set2) {
if (!set1 || !set2) {
return false;
}
if (set1.size !== set2.size) {
return false;
}
return [...set1].every((x) => set2.has(x));
}
// Compare two objects, and return an object with all (key, value) pairs from the new object
// that are (deeply) different from the base object
export function objectDifference(newObject, baseObject, objectKeysPossiblyChanged) {
const result = {};
if (objectKeysPossiblyChanged && objectKeysPossiblyChanged.length === 0) {
return result;
}
const baseEntries = new Map();
let newKeys = newObject ? Object.keys(newObject) : [];
if (objectKeysPossiblyChanged) {
newKeys = newKeys.filter((k) => objectKeysPossiblyChanged.includes(k));
}
const baseKeys = baseObject ? Object.keys(baseObject) : [];
for (const key of baseKeys) {
if (Object.prototype.hasOwnProperty.call(baseObject, key)) {
baseEntries.set(key, baseObject[key]);
}
}
for (const key of newKeys) {
if (!Object.prototype.hasOwnProperty.call(newObject, key))
continue;
const newVal = newObject[key];
if (!baseEntries.has(key) || !isEqual(newVal, baseEntries.get(key))) {
result[key] = newVal;
}
}
return result;
}
// export function objectOmitDifference(
// newObject: object,
// baseObject: object
// ): object {
// const keysToOmit = Object.keys(objectDifference(newObject, baseObject))
// return pick(newObject, keysToOmit)
// }
// Basic omit function as replacement for lodash omit, since it will be removed in v5
// See: https://github.com/lodash/lodash/issues/2930#issuecomment-272298477
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function omit(object, keys) {
const result = cloneDeep(object);
for (const key of keys) {
delete result[key];
}
return result;
}
export function isValidHttpUrl(string) {
let url;
try {
url = new URL(string);
}
catch (_) {
return false;
}
return url.protocol === 'http:' || url.protocol === 'https:';
}
export function camelCaseToWords(string) {
const result = string.replace(/([A-Z])/g, ' $1');
return result.charAt(0).toUpperCase() + result.slice(1);
}