UNPKG

@rxap/utilities

Version:

A collection of utility functions, types and interfaces.

198 lines 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.COERCE_ARRAY_ITEMS_DEFAULT_OPTIONS = void 0; exports.CoerceArrayItems_normalizeOptions = CoerceArrayItems_normalizeOptions; exports.CoerceArrayItems_handleExistsCase = CoerceArrayItems_handleExistsCase; exports.CoerceArrayItems_handleCompareFnCase = CoerceArrayItems_handleCompareFnCase; exports.CoerceArrayItems_handleDefaultCase = CoerceArrayItems_handleDefaultCase; exports.CoerceArrayItems = CoerceArrayItems; exports.COERCE_ARRAY_ITEMS_DEFAULT_OPTIONS = { merge: false, unshift: false, replace: false, compareTo: (a, b) => a === b, compareFn: null }; /** * Normalizes the options for coercing array items by ensuring all required properties are set. * This function allows customization of the comparison function and the unshift behavior. * * @param {CoerceArrayItemsOptions | ((a: T, b: T) => boolean)} [compareToOrOptions=((a, b) => a === b)] - This parameter can either be a function that compares two items of type T, or an object containing options for coercion. If a function is provided, it will be used as the comparison function. If an object is provided, it will be merged with the default options. If omitted, a strict equality comparison function is used by default. * @param {boolean} [unshift=false] - Determines whether new items should be unshifted (added to the beginning) of the array. This is only used if the first parameter is a function or if the `unshift` property is not specified in the options object. * @returns {Required<CoerceArrayItemsOptions<T>>} - Returns an object containing the normalized options, ensuring both `compareTo` and `unshift` properties are set. * * @template T - The type of the elements in the array to be coerced. * * @example * // Using a custom comparison function without unshifting * const options = CoerceArrayItems_normalizeOptions((item1, item2) => item1.id === item2.id); * // options will be { compareTo: (item1, item2) => item1.id === item2.id, unshift: false } * * @example * // Using default comparison with unshift set to true * const options = CoerceArrayItems_normalizeOptions(undefined, true); * // options will be { compareTo: (a, b) => a === b, unshift: true } * */ function CoerceArrayItems_normalizeOptions(compareToOrOptions = ((a, b) => a === b), unshift = false) { const options = Object.assign({}, exports.COERCE_ARRAY_ITEMS_DEFAULT_OPTIONS); if (!compareToOrOptions) { options.unshift = unshift; } if (typeof compareToOrOptions === 'function') { options.compareTo = compareToOrOptions; options.unshift = unshift; } else { Object.assign(options, compareToOrOptions); } return options; } /** * Modifies an array by replacing or merging an item at a specified index based on provided options. * * This function is designed to handle cases where an item already exists in the array. It can either replace * the existing item or merge it with the new item based on the configuration specified in the `options` parameter. * The function uses a comparator function defined in `options` to find the index of the item if not provided. * * @param options - An object with the following properties: * - `replace`: A boolean that determines if the item should be replaced. * - `merge`: A boolean that determines if the item should be merged with the existing item. * - `compareTo`: A function that takes two arguments of type T and returns a boolean indicating if they are considered equal. * @param array - The array of items of type T. * @param item - The item of type T to be added or merged into the array. * @param index - Optional. The index at which the item should be modified. If not provided, the index is determined by using the `compareTo` function from `options`. * * @remarks * - If `replace` is true, the item at the specified index is replaced with the new item. * - If `merge` is true and both the existing item and the new item are objects, they are merged into a single object. * - If the index is not provided, it is determined by finding the first item in the array that matches the `item` using the `compareTo` function. * - This function directly modifies the original array. */ function CoerceArrayItems_handleExistsCase(options, array, item, index = array.findIndex((a) => options.compareTo(a, item))) { if (options.replace) { array[index] = item; } if (options.merge) { const existingItem = array[index]; if (typeof existingItem === 'object' && typeof item === 'object') { if (existingItem) { array[index] = Object.assign(Object.assign({}, existingItem), item); } else { array[index] = item; } } } } /** * Inserts an item into a sorted array based on a comparison function provided in the options. * * This function ensures that the array remains sorted after the insertion of the new item. If the `unshift` option is true, * the item is inserted in such a way that the first item for which the comparison function returns a negative value will * precede the new item. If `unshift` is false, the item is inserted before the first item for which the comparison function * returns a positive value. If no such position is found, the item is added to the end of the array. * * @param {Required<CoerceArrayItemsOptions<T>>} options - An object containing the necessary options for coercion: * - `compareFn`: A function that takes two arguments of type T and returns a number. The function should return * a negative value if the first argument is less than the second, zero if they're equal, and a positive value * otherwise. * - `unshift`: A boolean indicating whether to insert the new item at the start of its suitable position (true) * or just before a greater item (false). * @param {T[]} array - The array into which the item should be inserted. This array should be sorted according to the * comparison function provided. * @param {T} item - The item to be inserted into the array. * * @throws {Error} If the `compareFn` is not provided in the options. * * @example * // Define a comparison function for numbers * const compareNumbers = (a: number, b: number) => a - b; * // Create an array of numbers * let numbers = [1, 3, 5, 7]; * // Options for insertion * const options = { compareFn: compareNumbers, unshift: false }; * // Insert a new number into the sorted array * CoerceArrayItems_handleCompareFnCase(options, numbers, 4); * console.log(numbers); // Output: [1, 3, 4, 5, 7] * */ function CoerceArrayItems_handleCompareFnCase(options, array, item) { if (!options.compareFn) { throw new Error('options.compareFn must be provided when comparing items'); } if (array.length === 0) { array.push(item); return; } if (options.unshift) { for (let i = array.length - 1; i >= 0; i--) { if (options.compareFn(array[i], item) < 0) { array.splice(i + 1, 0, item); return; } } array.unshift(item); } else { for (let i = 0; i < array.length; i++) { if (options.compareFn(array[i], item) > 0) { array.splice(i, 0, item); return; } } array.push(item); } } /** * Modifies the given array by adding an item either to the beginning or the end of the array based on the provided options. * * @param options - An object of type `Required<CoerceArrayItemsOptions<T>>` which includes the property `unshift`. * If `unshift` is true, the item is added to the beginning of the array. If false, the item is added to the end. * @param array - The array of type `T[]` to which the item will be added. * @param item - The item of type `T` to be added to the array. * * @template T - The type of the elements in the array and the item being added. */ function CoerceArrayItems_handleDefaultCase(options, array, item) { if (options.unshift) { array.unshift(item); } else { array.push(item); } } /** * Modifies the `array` by ensuring that all `items` are included in it based on a comparison strategy. * * This function iterates over each element in `items`, checks if it exists in `array` using a comparison function, * and modifies `array` according to the result of the comparison and the provided options. * * @param {T[]} array - The array to be modified. * @param {ReadonlyArray<T>} items - The items to be coerced into the array. * @param {CoerceArrayItemsOptions | ((a: T, b: T) => boolean)} [compareToOrOptions=((a, b) => a === b)] - * Either a function used to compare elements of the array, or an options object specifying detailed behavior. * By default, items are compared using strict equality. * @param {boolean} [unshift=false] - If true, new items are added to the beginning of the array; otherwise, they are added to the end. * * The function supports several scenarios for handling existing items: * 1. If an item is found in the array (as determined by the comparison function), it is handled according to the logic * defined in `CoerceArrayItems_handleExistsCase`. * 2. If an item is not found and a custom comparison function (`compareFn`) is provided in the options, it is handled * according to `CoerceArrayItems_handleCompareFnCase`. * 3. If an item is not found and no custom comparison function is provided, it is handled according to * `CoerceArrayItems_handleDefaultCase`. * * Note: The function mutates the original array. */ function CoerceArrayItems(array, items, compareToOrOptions = ((a, b) => a === b), unshift = false) { const options = CoerceArrayItems_normalizeOptions(compareToOrOptions, unshift); for (const item of items) { const index = array.findIndex((a) => options.compareTo(a, item)); const exists = index !== -1; if (exists) { CoerceArrayItems_handleExistsCase(options, array, item, index); } else if (options.compareFn) { CoerceArrayItems_handleCompareFnCase(options, array, item); } else { CoerceArrayItems_handleDefaultCase(options, array, item); } } } //# sourceMappingURL=coerce-array-items.js.map