UNPKG

@resk/core

Version:

An innovative TypeScript framework that empowers developers to build applications with a fully decorator-based architecture for efficient resource management. By combining the power of decorators with a resource-oriented design, DecorRes enhances code cla

497 lines (496 loc) 20.2 kB
import { IDict, IPrimitive } from "../types"; /** * Checks if the given variable is a plain object. * * A plain object is defined as an object that is created by the Object constructor * or one that inherits from `Object.prototype`. This function will return false for * instances of classes, arrays, and other non-plain objects. * * @param {any} obj - The variable to check for being a plain object. * * @returns {boolean} Returns true if the variable is a plain object, false otherwise. * * @example * ```ts * // Example with a string * console.log(isPlainObj("hello")); // Outputs: false * * // Example with a plain object * console.log(isPlainObj({ a: true })); // Outputs: true * * // Example with a function * console.log(isPlainObj(() => true)); // Outputs: false * * // Example with an array * console.log(isPlainObj([1, 2, 3])); // Outputs: false * * // Example with a Date object * console.log(isPlainObj(new Date())); // Outputs: false * * // Example with a plain object created using Object.create * const obj = Object.create(null); * console.log(isPlainObj(obj)); // Outputs: true * ``` */ export declare const isPlainObj: (obj: any) => boolean; /** * Clones a source object by returning a non-reference copy of the object. * * This function creates a deep copy of the provided object. * Any nested objects or arrays within the source will also be cloned, ensuring that the * returned object does not reference the original object. * * @template T - The type of the object to clone. This can be any type, including arrays and nested objects. * @param {T} source - The object to clone. This can be any type, including arrays and nested objects. * * @returns {T} A deep cloned copy of the source object. The return type can be * either an object or an array, depending on the input. * * @example * ```ts * // Example with a simple object * const original = { a: 1, b: { c: 2 } }; * const cloned = cloneObject(original); * console.log(cloned); // Outputs: { a: 1, b: { c: 2 } } * * // Modifying the cloned object does not affect the original * cloned.b.c = 3; * console.log(original.b.c); // Outputs: 2 (original remains unchanged) * * // Example with an array * const originalArray = [1, 2, { a: 3 }]; * const clonedArray = cloneObject(originalArray); * console.log(clonedArray); // Outputs: [1, 2, { a: 3 }] * * // Modifying the cloned array does not affect the original * clonedArray[2].a = 4; * console.log(originalArray[2].a); // Outputs: 3 (original remains unchanged) * * // Example with a nested structure * const complexObject = { a: 1, b: [2, { c: 3 }] }; * const clonedComplex = cloneObject(complexObject); * console.log(clonedComplex); // Outputs: { a: 1, b: [2, { c: 3 }] } * ``` */ export declare function cloneObject<T = any>(source: T): T; /** * Determines if the given variable is a plain object. * * This function checks whether the provided variable is a plain object, which is defined as an object * created by the Object constructor or one that inherits from `Object.prototype`. It will return false * for instances of classes, arrays, and other non-plain objects. * * @param {any} obj - The variable to check for being an object. * * @returns {boolean} Returns true if the variable is a plain object, false otherwise. * * @example * ```ts * // Example with a string * console.log(isObj("hello")); // Outputs: false * * // Example with a plain object * console.log(isObj({ a: true })); // Outputs: true * * // Example with an array * console.log(isObj([1, 2, 3])); // Outputs: false * * // Example with a function * console.log(isObj(() => true)); // Outputs: false * * // Example with a Date object * console.log(isObj(new Date())); // Outputs: false * * // Example with a plain object created using Object.create * const obj = Object.create(null); * console.log(isObj(obj)); // Outputs: true * ``` */ export declare function isObj<T = any>(obj: T): obj is IObject<T>; type IObject<T = any> = T extends IDict ? T : T extends undefined ? never : any; /** * Calculates the size of an object or array. * * This function returns the number of own properties of an object or the length of an array. * If the input is null or not an object, it returns 0. * * @param {any} obj - The object or array whose size is to be calculated. * @param {boolean} [breakOnFirstElementFound=false] - Optional flag to determine if the function should * return the size immediately upon finding the first property or element. * * @returns {number} The size of the object or array. Returns 0 if the input is null or not an object. * * @example * // Example with an object * const exampleObject = { a: 1, b: 2, c: 3 }; * const size = objectSize(exampleObject); * console.log(size); // Outputs: 3 * * @example * // Example with an array * const exampleArray = [1, 2, 3, 4]; * const arraySize = objectSize(exampleArray); * console.log(arraySize); // Outputs: 4 * * @example * // Example with breakOnFirstElementFound * const earlyExitSize = objectSize(exampleObject, true); * console.log(earlyExitSize); // Outputs: 1, as it returns after the first property * * @example * // Example with a null input * const nullSize = objectSize(null); * console.log(nullSize); // Outputs: 0 * * @example * // Example with a non-object input * const nonObjectSize = objectSize(42); * console.log(nonObjectSize); // Outputs: 0 */ export declare const objectSize: (obj: any, breakOnFirstElementFound?: boolean) => number; /** * Returns a default object based on the provided arguments. * * This function takes multiple arguments and returns the first non-empty object found. * If only one argument is provided, it returns that argument if it is an object; otherwise, it returns an empty object. * If no valid object is found among the arguments, it returns an empty object. * * @param {...any[]} args - The arguments to check for objects. * @template T - The type of the object to return. * * @returns {object} The first non-empty object found among the arguments, or an empty object if none is found. * * @example * ```ts * // Example with one valid object * const result1 = defaultObj({ a: 1 }); * console.log(result1); // Outputs: { a: 1 } * * // Example with one invalid argument * const result2 = defaultObj("not an object"); * console.log(result2); // Outputs: {} * * // Example with multiple arguments, returning the first non-empty object * const result3 = defaultObj({}, { b: 2 }, { c: 3 }); * console.log(result3); // Outputs: { b: 2 } * * // Example with multiple arguments, returning the last valid object * const result4 = defaultObj({}, {}, { d: 4 }); * console.log(result4); // Outputs: { d: 4 } * * // Example with no valid objects * const result5 = defaultObj(null, undefined, "string"); * console.log(result5); // Outputs: {} * ``` */ export declare function defaultObj<T extends object = any>(...args: any[]): T; /** * Declares a global interface extension for the built-in `Object` type. */ declare global { /** * Interface extension for the built-in `Object` type. */ interface Object { /** * Clones a source object by returning a non-reference copy of the object. * * This method creates a deep clone of the provided object, ensuring that nested objects * are also cloned, and modifications to the cloned object do not affect the original. * * @param {any} obj - The object to clone. This can be any type, including arrays and nested objects. * @returns {any} The cloned object, which can be an object or an array. * * @example * ```ts * const original = { a: 1, b: { c: 2 } }; * const cloned = Object.clone(original); * console.log(cloned); // Outputs: { a: 1, b: { c: 2 } } * * cloned.b.c = 3; * console.log(original.b.c); // Outputs: 2 (original remains unchanged) * ``` * @template T - The type of the object to clone. * @param {T} obj - The object to clone. * @returns {T} A clone of the object. */ clone: <T = any>(obj: T) => T; /** * Determines the size of an object or array. * * This method calculates the number of own enumerable properties in an object or * the number of elements in an array. If the `breakOnFirstElementFound` parameter * is set to true, it will return 1 immediately upon finding the first element or property. * * @param {any} obj - The object or array to determine the size of. * @param {boolean} [breakOnFirstElementFound=false] - Whether to return immediately after the first element is found. * @returns {number} The size of the object or array. Returns 0 if the input is not an object or array. * * @example * ```ts * const obj = { a: 1, b: 2, c: 3 }; * const size = Object.getSize(obj); * console.log(size); // Outputs: 3 * * const arr = [1, 2, 3]; * const arrSize = Object.getSize(arr); * console.log(arrSize); // Outputs: 3 * * const singleElementSize = Object.getSize(arr, true); * console.log(singleElementSize); // Outputs: 1 (returns immediately) * * const emptyObjSize = Object.getSize({}); * console.log(emptyObjSize); // Outputs: 0 * ``` */ getSize: (obj: any, breakOnFirstElementFound?: boolean) => number; /** * Flattens a nested object structure into a single-level object with dot/bracket notation keys. * Handles various data structures including Arrays, Sets, Maps, and plain objects. * Skips non-primitive values like functions, class instances. * * @param {any} obj - The object to flatten * @param {string} [prefix=''] - The prefix to use for nested keys * @returns {Record<string, Primitive>} A flattened object with primitive values * * @example * // Basic object flattening * _flattenObject({ * a: { * b: 'value', * c: 42 * } * }) * // Returns: { 'a.b': 'value', 'a.c': 42 } * * @example * // Array handling * _flattenObject({ * items: ['a', 'b', { nested: 'value' }] * }) * // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' } * * @example * // Map handling * _flattenObject({ * map: new Map([ * ['key1', 'value1'], * ['key2', { nested: 'value2' }] * ]) * }) * // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' } * * @example * // Complex nested structure * _flattenObject({ * array: [1, { a: 2 }], * set: new Set(['x', { b: 'y' }]), * map: new Map([['k', { c: 'v' }]]), * obj: { * deep: { * nested: 'value', * fn: () => {}, // Will be skipped * date: new Date() // Will be skipped * } * } * }) * // Returns: { * // 'array[0]': 1, * // 'array[1].a': 2, * // 'set[0]': 'x', * // 'set[1].b': 'y', * // 'map[k].c': 'v', * // 'obj.deep.nested': 'value' * // } * * @throws {Error} Will not throw errors, but silently skips non-primitive values * * @category Utilities * @since 1.0.0 */ flatten(obj: any): Record<string, IPrimitive>; /** * Enhanced version of Object.entries that preserves key types in TypeScript inference. * * Unlike the standard Object.entries which types all keys as string, this method * maintains the original key types (string | number | symbol) in TypeScript's type system * while still following JavaScript's runtime behavior where all keys are strings. * * @template T - The object type extending Record<string | number, any> * @param obj - The object to extract entries from * @returns Array of key-value tuples with preserved key types in TypeScript * * @example * ```typescript * const obj = { 1: "one", "foo": "bar", 42: "answer" } as const; * * // Standard Object.entries - all keys typed as string * const standard = Object.entries(obj); // [string, string][] * * // Enhanced Object.typedEntries - preserves original key types * const typed = Object.typedEntries(obj); * // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[] * ``` * * @remarks * - Runtime behavior is identical to Object.entries (all keys are strings) * - Only TypeScript inference is enhanced to remember original key types * - Works best with objects declared with 'as const' for literal type inference * - Particularly useful for objects with mixed string and numeric keys * * @since 1.0.0 */ typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{ [K in keyof T]: [K, T[K]]; }[keyof T]>; } } /** * Extends an object by merging properties from one or more source objects. * * This function takes a target object and one or more source objects, merging the properties * from the source objects into the target object. If a property exists in both the target * and a source object, the value from the source object will overwrite the target's value. * For arrays, the function merges the contents of the arrays, preserving the original order of the elements. *@template T - The type of the target object. * @param {T} target - The object to extend. It will receive the new properties. * @param {...any[]} sources - The source objects to merge into the target. These objects will not be modified. * @returns {T} The extended target object, which contains properties from the source objects. * * @example * ```ts * const target = { a: 1, b: 2 }; * const source1 = { b: 3, c: 4 }; * const source2 = { d: 5 }; * * const extended = extendObj(target, source1, source2); * console.log(extended); // Outputs: { a: 1, b: 3, c: 4, d: 5 } * console.log(target); // Outputs: { a: 1, b: 3 } (target is modified) * ``` * Merges the contents of two or more objects together into the first object. * Similar to jQuery's $.extend function. * @remarks * This function is used to merge the contents of multiple objects into a single object. It takes an optional target object as the first argument and one or more source objects as additional arguments. The function returns the merged object, which is a new object that contains all the properties from the source objects. * * If the target object is not provided or is not a plain object, an empty object is returned. * * If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object. * * If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object. * For arrays, The function replaces the contents of the arrays, preserving the original order of the elements. * Empty values like null, undefined, and empty strings are ignored. */ export declare function extendObj<T extends Record<string, any> = any>(target: any, ...sources: any[]): T; /** * Flattens a nested object structure into a single-level object with dot/bracket notation keys. * Handles various data structures including Arrays, Sets, Maps, and plain objects. * Skips non-primitive values like functions, class instances. * * @param {any} obj - The object to flatten * @param {string} [prefix=''] - The prefix to use for nested keys * @returns {Record<string, Primitive>} A flattened object with primitive values * * @example * // Basic object flattening * _flattenObject({ * a: { * b: 'value', * c: 42 * } * }) * // Returns: { 'a.b': 'value', 'a.c': 42 } * * @example * // Array handling * _flattenObject({ * items: ['a', 'b', { nested: 'value' }] * }) * // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' } * * @example * // Map handling * _flattenObject({ * map: new Map([ * ['key1', 'value1'], * ['key2', { nested: 'value2' }] * ]) * }) * // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' } * * @example * // Complex nested structure * _flattenObject({ * array: [1, { a: 2 }], * set: new Set(['x', { b: 'y' }]), * map: new Map([['k', { c: 'v' }]]), * obj: { * deep: { * nested: 'value', * fn: () => {}, // Will be skipped * date: new Date() // Will be skipped * } * } * }) * // Returns: { * // 'array[0]': 1, * // 'array[1].a': 2, * // 'set[0]': 'x', * // 'set[1].b': 'y', * // 'map[k].c': 'v', * // 'obj.deep.nested': 'value' * // } * * @throws {Error} Will not throw errors, but silently skips non-primitive values * * @category Utilities * @since 1.0.0 */ export declare function flattenObject(obj: any): Record<string, any>; /** * Checks if a value is an iterable data structure (Array, Set, Map, WeakMap, WeakSet). * * @param {any} value - The value to check * @returns {boolean} True if the value is an iterable structure, false otherwise * * @example * isIterableStructure([1, 2, 3]) // returns true * isIterableStructure(new Set([1, 2, 3])) // returns true * isIterableStructure(new Map()) // returns true * isIterableStructure({}) // returns false */ export declare function isIterableStructure(value: any): boolean; /** * Enhanced version of Object.entries that preserves key types in TypeScript inference. * * Unlike the standard Object.entries which types all keys as string, this method * maintains the original key types (string | number | symbol) in TypeScript's type system * while still following JavaScript's runtime behavior where all keys are strings. * * @template T - The object type extending Record<string | number, any> * @param obj - The object to extract entries from * @returns Array of key-value tuples with preserved key types in TypeScript * * @example * ```typescript * const obj = { 1: "one", "foo": "bar", 42: "answer" } as const; * * // Standard Object.entries - all keys typed as string * const standard = Object.entries(obj); // [string, string][] * * // Enhanced Object.typedEntries - preserves original key types * const typed = Object.typedEntries(obj); * // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[] * ``` * * @remarks * - Runtime behavior is identical to Object.entries (all keys are strings) * - Only TypeScript inference is enhanced to remember original key types * - Works best with objects declared with 'as const' for literal type inference * - Particularly useful for objects with mixed string and numeric keys * * @since 1.0.0 */ export declare function typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{ [K in keyof T]: [K, T[K]]; }[keyof T]>; export {};