UNPKG

@js-utility/object

Version:

Comprehensive utility library for advanced object manipulation in JavaScript: deep get/set, clone, merge, flatten, and more. Ideal for Node.js and browser projects as a lightweight lodash alternative.

369 lines (357 loc) 14.6 kB
declare const cloneDeep: <T>(obj: T) => T; /** * Check if an object has a specific property. * @param obj The object to check. * @param key The property to check for. * @returns True if the property exists, false otherwise. */ declare const hasProperty: (obj: object, key: string | number) => boolean; /** * Converts an array of dot-separated strings into a nested JSON object with the specified value. * * @param {string[]} arr - An array of strings where each string represents a path in dot notation. * @param {any} [value=1] - The value to assign to the deepest key in the nested structure. * @returns {object} - A nested JSON object based on the provided array of strings. * * @example * const input = ['a.b.c', 'a.b.d', 'e']; * const result = toNestedJson(input); * // Output: { a: { b: { c: 1, d: 1 } }, e: 1 } */ declare const toNestedJson: (arr: string[], value?: any) => any; /** * Converts a nested JSON object into an array of dot-separated strings. * * @param {object} obj - The nested JSON object to convert. * @param {string} [prefix=''] - The prefix for the current level of keys (used for recursion). * @returns {string[]} - An array of strings where each string represents a path in dot notation. * * @example * const input = { a: { b: { c: 1, d: 1 } }, e: 1 }; * const result = fromNestedJson(input); * // Output: ['a.b.c', 'a.b.d', 'e'] */ declare const fromNestedJson: (obj: any, prefix?: string) => string[]; /** * Removes duplicate values from an array. * @param arr The array to process. * @returns A new array with duplicates removed. */ declare const removeDuplicates: (arr: any[]) => any[]; /** * Removes duplicate values from an array. * @param arr The array to process. * @returns A new array with duplicates removed. */ declare const union: (arr: any[]) => any[]; /** * Deeply compares two arrays for equality. * @param arr1 The first array. * @param arr2 The second array. * @returns True if both arrays are deeply equal, false otherwise. */ declare const arrayEquals: (arr1: any[], arr2: any[]) => boolean; /** * Removes duplicate values from an array. * @param arr The array to process. * @returns A new array with duplicates removed. */ declare const intersect: (arr1: any[], arr2: any[]) => any[]; /** * Sorts an array of objects based on multiple sorting criteria, * with optional prefix-based prioritization for string fields. * * @param data - The array of objects to be sorted. * @param sort_by - An array of sort conditions, each containing: * - `key`: The field (can be a nested path) to sort by. * - `order`: `1` for ascending or `-1` for descending order. * - `priority_prefix` (optional): A string prefix that, if present, * gives higher priority to values starting with this prefix. * * @returns The sorted array of objects. * * @example * ```ts * const data = [ * { name: 'apple', rank: 2 }, * { name: 'banana', rank: 1 }, * { name: 'apricot', rank: 1 }, * ]; * * const sorted = sort(data, [ * { key: 'name', order: 1, priority_prefix: 'ap' }, * { key: 'rank', order: -1 } * ]); * * // Result: * // [ * // { name: 'apricot', rank: 1 }, * // { name: 'apple', rank: 2 }, * // { name: 'banana', rank: 1 } * // ] * ``` */ declare const sort: (data: any[], sort_by: { key: string; order: 1 | -1; priority_prefix?: string; }[]) => any[]; /** * Groups an array of objects by a specified key. * * This function takes an array of items and groups them into an object based on the value of a specified key. * The key can be a deep path (e.g., "user.id"), and values are converted to strings for grouping. * * @template T - The type of the elements in the input array. * @param {T[]} arr - The array of items to group. * @param {string} key - The key (can be a deep path) to group by. * @returns {Record<string, T[]>} An object where each key is a group identifier, and the value is an array of items in that group. * * @example * ```ts * const users = [ * { id: 1, info: { role: 'admin' } }, * { id: 2, info: { role: 'user' } }, * { id: 3, info: { role: 'admin' } } * ]; * * const grouped = groupBy(users, 'info.role'); * // Result: * // { * // admin: [{...}, {...}], * // user: [{...}] * // } * ``` */ declare function groupBy<T>(arr: T[], key: string): Record<string, T[]>; /** * Compares two values deeply to determine if they are equal. * * This function performs a deep equality check between two values. It handles * primitive types, objects, and arrays. If the values are objects or arrays, * it recursively compares their properties or elements. * * @param value1 - The first value to compare. * @param value2 - The second value to compare. * @returns `true` if the two values are deeply equal, otherwise `false`. * * @example * ```typescript * deepEqual(1, 1); // true * deepEqual({ a: 1 }, { a: 1 }); // true * deepEqual([1, 2], [1, 2]); // true * deepEqual({ a: 1 }, { b: 1 }); // false * deepEqual(null, null); // true * deepEqual(null, {}); // false * ``` */ declare function deepEqual(a: any, b: any): boolean; type Path = string | Array<string | number>; type DataObject$1 = Record<string, any> | null | undefined; interface DeepExtractOptions { /** * Whether to resolve references like "ID:2" or ["ID:3"] from the root. * Default: true */ resolveRefs?: boolean; /** * The maximum number of times the same reference can be visited during the traversal. * Default: 5 (to prevent infinite loops or excessive resolution in case of deep cycles). */ maxRefVisits?: number; /** * Default value to return if the path is not found or the root is null/undefined. */ default?: any; } /** * Extracts a deeply nested value from an object using a dot/bracket path. * * Supports: * - Arrays at any level * - Wildcards (*) for collecting from all array elements * - Optional reference resolution (string/array pointing to root-level keys) * - Maximum number of reference visits before aborting further resolution (to avoid infinite loops) * * @param root The root object (used for value and reference resolution) * @param path The path to extract (e.g. "items[0].ref.name", "items[*].prop") * @param options Optional settings (e.g. resolveRefs: false to disable ref following, maxRefVisits: 3) * @returns The extracted value (array, value, or undefined) */ declare function deepExtract(root: DataObject$1, path: Path, options?: DeepExtractOptions): any | undefined; declare const getDeep: typeof deepExtract; /** * Creates a deep copy of the given object and removes properties or elements * specified by the provided paths. The original object remains unmodified. * * @param obj - The source object from which properties or elements will be omitted. * @param paths - An array of string paths specifying the properties or elements to omit. * Each path is a dot-separated string representing the property hierarchy. * For example, "a.b.c" targets the `c` property of the `b` object within `a`. * * @returns A new object with the specified properties or elements removed. * * @example * ```typescript * const obj = { a: { b: { c: 1, d: 2 } }, e: 3 }; * const result = omit(obj, ["a.b.c", "e"]); * console.log(result); // Output: { a: { b: { d: 2 } } } * ``` */ declare function deepOmit(obj: any, paths: string[]): any; /** * Recursively picks specific properties from an object or array based on the provided paths. * * @param obj - The source object or array from which properties will be picked. * @param paths - An array of string paths specifying the properties to pick. * Paths can include nested keys separated by dots (e.g., "a.b.c") * and wildcard '*' to match all elements in an array. * * @returns A new object or array containing only the picked properties, * preserving the structure of the original object or array. * * @example * const obj = { a: { b: { c: 1, d: 2 } }, e: [ { f: 3 }, { f: 4 } ] }; * const paths = ["a.b.c", "e.*.f"]; * const result = pickDeep(obj, paths); * // result: { a: { b: { c: 1 } }, e: [ { f: 3 }, { f: 4 } ] } */ declare function pickDeep(obj: any, paths: string[]): any; type DataObject = Record<string, any> | null | undefined; interface DeepAssignOptions { /** * Whether to resolve references like "ID:2" or ["ID:3"] from the root. * Default: true */ resolveRefs?: boolean; /** * The maximum number of times the same reference can be visited during the traversal. * Default: 5 (to prevent infinite loops or excessive resolution in case of deep cycles). */ maxRefVisits?: number; /** * It forcefully sets the value even if the path already exists or type mismatch. */ set_forcefully?: boolean; } /** * Recursively assigns a value to a deeply nested property within an object, creating intermediate * objects or arrays as needed. Supports resolving references and handling wildcard paths. * * @param root - The root object where the value will be assigned. If `null` or `undefined`, the function exits early. * @param path - The path to the property where the value should be assigned. Can include wildcard (`*`) for arrays. * @param value - The value to assign to the specified path. * @param options - Optional configuration for the assignment process. * * @param options.resolveRefs - Whether to resolve references (e.g., "ID:2") from the root object. Default is `true`. * @param options.maxRefVisits - The maximum number of times the same reference can be visited during traversal. * Default is `5` to prevent infinite loops or excessive resolution. * @param options.set_forcefully - If `true`, forcefully sets the value even if the path already exists or there is a type mismatch. * Default is `false`. * * @remarks * - If the path includes a wildcard (`*`), the function will iterate over arrays at that level and apply the value to each element. * - If `resolveRefs` is enabled, the function will attempt to resolve string references within the object. * - The function ensures intermediate objects or arrays are created as needed to complete the assignment. * * @example * ```typescript * const obj = { a: { b: { c: 1 } } }; * deepAssign(obj, 'a.b.c', 42); * console.log(obj); // { a: { b: { c: 42 } } } * * const arr = { items: [{ id: 1 }, { id: 2 }] }; * deepAssign(arr, 'items.*.id', 99); * console.log(arr); // { items: [{ id: 99 }, { id: 99 }] } * ``` */ declare function deepAssign(root: DataObject, path: Path, value: any, options?: DeepAssignOptions): void; declare const setDeep: typeof deepAssign; /** * Computes the difference between two objects or arrays. * * - If either `obj1` or `obj2` is `null` or `undefined`, returns `obj1`. * - If both are arrays, returns an array of items from `obj1` that are not deeply equal to any item in `obj2`. * - If both are objects, returns a new object containing keys from `obj1` whose values are not deeply equal to the corresponding values in `obj2`. * - For primitive values, returns `obj1`. * * @param obj1 - The first object or array to compare. * @param obj2 - The second object or array to compare against. * @returns The difference between `obj1` and `obj2`, preserving the structure of `obj1`. */ declare const difference: (obj1: any, obj2: any) => any; /** * Determines whether a given value is not null, undefined, or an empty/invalid representation * for its type (e.g., empty string, NaN, invalid date, empty array, empty object, etc.). * * @param value - The value to be checked. * @returns `true` if the value is not null, undefined, or an empty/invalid representation; otherwise, `false`. * * @remarks * - For primitive wrappers like `new Number()`, `new String()`, or `new Boolean()`, the function unwraps the value. * - Strings are considered valid if they are non-empty after trimming whitespace. * - Numbers are considered valid if they are not `NaN`. * - Dates are considered valid if they represent a valid date. * - Arrays, Maps, and Sets are considered valid if they are not empty. * - Objects are considered valid if they have at least one enumerable property. * - Booleans are always considered valid since they cannot be null or undefined. * * @example * ```typescript * isNotNull("Hello"); // true * isNotNull(""); // false * isNotNull(42); // true * isNotNull(NaN); // false * isNotNull(null); // false * isNotNull(undefined); // false * isNotNull([]); // false * isNotNull([1, 2, 3]); // true * isNotNull({}); // false * isNotNull({ key: "value" }); // true * isNotNull(new Date()); // true * isNotNull(new Date("invalid date")); // false * ``` */ declare function isNotNull(value: any): boolean; /** * Determines whether a given value is null or undefined. * * @param value - The value to be checked. * @returns `true` if the value is null or undefined; otherwise, `false`. * * @example * ```typescript * isNull(null); // true * isNull(undefined); // true * isNull(0); // false * isNull(""); // false * ``` */ declare function isNull(value: any): boolean; /** * Attempt to parse a string into its original value. * Falls back to the original string if parsing fails. * @param str The string to parse. * @param default_val The default value to return on failure. * @returns The parsed value or default. */ declare const jsonify: (str: any, default_val?: any) => any; /** * Merges multiple source objects into a target object recursively, performing a deep merge. * If a property in both the target and source objects is an object, the function merges them recursively. * Otherwise, the source property overwrites the target property. * * @param target - The target object to which properties will be merged. * @param sources - One or more source objects whose properties will be merged into the target. * @returns The merged target object. * * @example * ```typescript * const target = { a: 1, b: { c: 2 } }; * const source = { b: { d: 3 }, e: 4 }; * const result = mergeObjs(target, source); * // result: { a: 1, b: { c: 2, d: 3 }, e: 4 } * ``` */ declare const mergeObjs: (target: any, ...sources: any[]) => any; export { arrayEquals, cloneDeep, deepAssign, deepEqual, deepExtract, deepOmit, difference, fromNestedJson, getDeep, groupBy, hasProperty, intersect, isNotNull, isNull, jsonify, mergeObjs, pickDeep, removeDuplicates, setDeep, sort, toNestedJson, union };