zync-nest-library
Version:
NestJS library with database backup and file upload utilities
123 lines (111 loc) • 3.96 kB
text/typescript
/**
* Utility functions for object manipulation and mapping
*/
export const ObjectUtils = {
/**
* Maps an object using dot notation keys to extract nested values
* @param obj - The source object
* @param keyPath - Dot notation path (e.g., "account.user.name")
* @returns The value at the specified path or undefined if not found
*
* @example
* const obj = { account: { user: { name: "John" } } };
* mapKey(obj, "account.user.name"); // Returns "John"
* mapKey(obj, "account.user.email"); // Returns undefined
*/
mapKey: <T = any>(obj: any, keyPath: string): T | undefined => {
if (!obj || !keyPath) return undefined;
const path = keyPath.split(".");
return path.reduce((acc, key) => {
return acc != null && typeof acc === "object" ? acc[key] : undefined;
}, obj);
},
/**
* Maps multiple objects using dot notation keys
* @param objects - Array of source objects
* @param keyPath - Dot notation path
* @returns Array of extracted values
*
* @example
* const objects = [
* { account: { user: { name: "John" } } },
* { account: { user: { name: "Jane" } } }
* ];
* mapKeys(objects, "account.user.name"); // Returns ["John", "Jane"]
*/
mapKeys: <T = any>(objects: any[], keyPath: string): (T | undefined)[] => {
return objects.map((obj) => ObjectUtils.mapKey<T>(obj, keyPath));
},
/**
* Creates a new object with mapped values using dot notation
* @param obj - The source object
* @param keyMappings - Object mapping source paths to target keys
* @returns New object with mapped values
*
* @example
* const obj = { account: { user: { name: "John", email: "john@example.com" } } };
* const result = mapObject(obj, {
* "account.user.name": "userName",
* "account.user.email": "userEmail"
* });
* // Returns { userName: "John", userEmail: "john@example.com" }
*/
mapObject: <T = any>(obj: any, keyMappings: Record<string, string>): T => {
const result: any = {};
Object.entries(keyMappings).forEach(([sourcePath, targetKey]) => {
result[targetKey] = ObjectUtils.mapKey(obj, sourcePath);
});
return result;
},
/**
* Converts a string to camelCase
* @param str - The string to convert
* @param mapping - Optional mapping of keys to camelCase
* @returns The camelCase string
*
* @example
* const str = "snake_case_string";
* toCamelCase(str); // Returns "snakeCaseString"
*/
toCamelCase(str: string, mapping?: Record<string, string>): string {
if (mapping && mapping[str]) {
return mapping[str];
}
// Handle snake_case and kebab-case
str = str.replace(/[_-]+/g, " ");
// Split words by lowercase-uppercase or letter-number boundaries
str = str.replace(/([a-z])([A-Z0-9])/g, "$1 $2");
const words = str.trim().split(/\s+/);
return (
words[0].toLowerCase() +
words
.slice(1)
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
.join("")
);
},
/**
* Converts all keys in an object to camelCase
* @param obj - The object to convert
* @param mapping - Optional mapping of keys to camelCase
* @returns The object with camelCase keys
*
* @example
* const obj = { snake_case_key: "value" };
* toCamelCaseKeys(obj); // Returns { camelCaseKey: "value" }
*/
toCamelCaseKeys(obj: any, mapping?: Record<string, string>): any {
if (Array.isArray(obj)) {
// Recursively process each element in array
return obj.map((v) => ObjectUtils.toCamelCaseKeys(v, mapping));
} else if (obj !== null && typeof obj === "object") {
// Convert all keys in object
return Object.entries(obj).reduce((acc, [key, value]) => {
const camelKey = ObjectUtils.toCamelCase(key, mapping);
acc[camelKey] = ObjectUtils.toCamelCaseKeys(value, mapping);
return acc;
}, {});
}
return obj;
},
};