UNPKG

@casual-simulation/aux-common

Version:
200 lines 6.12 kB
/* CasualOS is a set of web-based tools designed to facilitate the creation of real-time, multi-user, context-aware interactive experiences. * * Copyright (c) 2019-2025 Casual Simulation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ import { fromByteArray, toByteArray } from 'base64-js'; import { union, isObject, mapValues } from 'es-toolkit/compat'; import { v4 as uuid } from 'uuid'; export function merge(...objs) { let result = {}; const objKeys = objs.map((o) => Object.keys(o)); const allKeys = union(...objKeys); allKeys.forEach((k) => { result[k] = decide(...objs.map((o) => o[k])); }); return result; } function decide(...vals) { const undefed = vals.filter((v) => typeof v !== 'undefined'); if (undefed.length === 1) { return undefed[0]; } else { if (undefed.every((v) => typeof v === 'object' && !Array.isArray(v) && v !== null) && undefed.some((v) => v !== undefed[0])) { return merge(...undefed); } else { return undefed[undefed.length - 1]; } } } /** * Maps all the values of the given object. * @param value The object to map. * @param callback The callback that transforms one value into another. */ export function mapValuesDeep(value, callback) { return isObject(value) ? mapValues(value, (v) => mapValuesDeep(v, callback)) : callback(value); } /** * Splices the given string and returns the final result. * @param str The string to splice. * @param index The index that the splice should be started at. * @param deleteCount The number of characters to delete. * @param text The text to insert. */ export function splice(str, index, deleteCount, text) { return str.slice(0, index) + text + str.slice(index + deleteCount); } export function lerp(start, end, t) { return (1.0 - t) * start + t * end; } export function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } export function normalize(value, min, max) { value = clamp(value, min, max); return (value - min) / (max - min); } export function unnormalize(normal, min, max) { normal = clamp(normal, 0.0, 1.0); return normal * (max - min) + min; } /** * Creates and returns a short 8 character UUID (no dashes). */ export function shortUuid() { return uuid().substr(0, 8); } /** * Converts the given string from dot case (dot.case) to camel case (camelCase). * @param dotCase The string to convert. */ export function dotCaseToCamelCase(dotCase) { const split = dotCase.split('.'); if (split.length <= 0) { return ''; } else if (split.length === 1) { return split[0]; } else { let [isTagHidden, first] = isHidden(split[0]); let others = split.slice(1); let uppercased = []; for (let str of others) { let [hidden, updated] = isHidden(str); str = updated; if (hidden) { isTagHidden = true; } uppercased.push(capitalizeFirstLetter(str)); } let joined = uppercased.join(''); if (isTagHidden) { return '_' + first + joined; } else { return first + joined; } } } function capitalizeFirstLetter(str) { return str.charAt(0).toUpperCase() + str.slice(1); } function isHidden(str) { const hidden = str.indexOf('_') === 0; if (hidden) { return [hidden, str.slice(1)]; } else { return [hidden, str]; } } /** * Determines if the given value might represent an email address. * @param value The value to check. */ export function mightBeEmailAddress(value) { // Test that the value ends with an @ symbol and some characters and a dot (.) and some more characters. const emailTest = /@.+\.\w{2,}$/; return emailTest.test(value); } /** * Trims the given value and removes characters that are not valid in a phone number. * Returns null if the value is definitely not a phone number. * @param value The value that should be cleaned. */ export function cleanPhoneNumber(value) { let sms = value.trim().replace(/[^\d+]/g, ''); if (!sms) { return null; } if (!sms.startsWith('+')) { if (sms.length > 10) { // for US phone numbers, 10 characters make up a country-code less phone number // 3 for area code, sms = '+' + sms; } else if (sms.length > 7) { sms = '+1' + sms; } else { sms = '+1616' + sms; } } return sms; } /** * Converts the given string into a base64 string. * @param str The string to convert. */ export function toBase64String(str) { const encoder = new TextEncoder(); const array = encoder.encode(str); return fromByteArray(array); } /** * Converts the given string from a base64 string. * @param base64 */ export function fromBase64String(base64) { const decoder = new TextDecoder(); const array = toByteArray(base64); return decoder.decode(array); } /** * Tries to parse the given JSON string into a JavaScript Value. * @param json The JSON to parse. */ export function tryParseJson(json) { try { return { success: true, value: JSON.parse(json), }; } catch (err) { return { success: false, error: err, }; } } //# sourceMappingURL=utils.js.map