Skip to main content
Glama
zqushair
by zqushair
transformation.ts9.63 kB
import logger from './logger.js'; /** * Data transformation utility * This utility provides methods for transforming data between different formats */ export class TransformationUtil { /** * Transform an object by mapping its properties * @param obj The object to transform * @param mapping The property mapping * @returns The transformed object */ public transformObject<T extends Record<string, any>, U extends Record<string, any>>( obj: T, mapping: { [K in keyof U]?: keyof T | ((obj: T) => U[K]); } ): U { const result: Record<string, any> = {}; try { // Apply the mapping to each property for (const [targetKey, sourceKeyOrFn] of Object.entries(mapping)) { try { if (typeof sourceKeyOrFn === 'function') { // If the mapping is a function, call it with the object result[targetKey] = sourceKeyOrFn(obj); } else if (sourceKeyOrFn !== undefined) { // If the mapping is a property key, copy the value result[targetKey] = obj[sourceKeyOrFn as keyof T]; } } catch (error: any) { logger.error(`Error transforming property '${targetKey}'`, { error: error.message, stack: error.stack, }); throw new Error(`Error transforming property '${targetKey}': ${error.message}`); } } return result as U; } catch (error: any) { logger.error('Error transforming object', { error: error.message, stack: error.stack, obj, mapping, }); throw error; } } /** * Transform an array of objects by mapping their properties * @param arr The array to transform * @param mapping The property mapping * @returns The transformed array */ public transformArray<T extends Record<string, any>, U extends Record<string, any>>( arr: T[], mapping: { [K in keyof U]?: keyof T | ((obj: T) => U[K]); } ): U[] { try { // Transform each object in the array return arr.map((obj) => this.transformObject(obj, mapping)); } catch (error: any) { logger.error('Error transforming array', { error: error.message, stack: error.stack, arr, mapping, }); throw error; } } /** * Transform a value using a custom transformer function * @param value The value to transform * @param transformer The transformer function * @returns The transformed value */ public transformValue<T, U>(value: T, transformer: (value: T) => U): U { try { return transformer(value); } catch (error: any) { logger.error('Error transforming value', { error: error.message, stack: error.stack, value, }); throw error; } } /** * Transform a date to an ISO string * @param date The date to transform * @returns The ISO string representation of the date */ public dateToISOString(date: Date | number | string): string { try { // Convert the date to a Date object const dateObj = date instanceof Date ? date : new Date(date); // Convert the Date object to an ISO string return dateObj.toISOString(); } catch (error: any) { logger.error('Error transforming date to ISO string', { error: error.message, stack: error.stack, date, }); throw new Error(`Invalid date: ${error.message}`); } } /** * Transform a date to a Unix timestamp (seconds since epoch) * @param date The date to transform * @returns The Unix timestamp */ public dateToUnixTimestamp(date: Date | number | string): number { try { // Convert the date to a Date object const dateObj = date instanceof Date ? date : new Date(date); // Convert the Date object to a Unix timestamp (seconds since epoch) return Math.floor(dateObj.getTime() / 1000); } catch (error: any) { logger.error('Error transforming date to Unix timestamp', { error: error.message, stack: error.stack, date, }); throw new Error(`Invalid date: ${error.message}`); } } /** * Transform a Unix timestamp to a Date object * @param timestamp The Unix timestamp (seconds since epoch) * @returns The Date object */ public unixTimestampToDate(timestamp: number): Date { try { // Convert the Unix timestamp to a Date object return new Date(timestamp * 1000); } catch (error: any) { logger.error('Error transforming Unix timestamp to Date', { error: error.message, stack: error.stack, timestamp, }); throw new Error(`Invalid timestamp: ${error.message}`); } } /** * Transform a string to camelCase * @param str The string to transform * @returns The camelCase string */ public toCamelCase(str: string): string { try { // Convert the string to camelCase return str .replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase()) .replace(/^[A-Z]/, (chr) => chr.toLowerCase()); } catch (error: any) { logger.error('Error transforming string to camelCase', { error: error.message, stack: error.stack, str, }); throw new Error(`Invalid string: ${error.message}`); } } /** * Transform a string to snake_case * @param str The string to transform * @returns The snake_case string */ public toSnakeCase(str: string): string { try { // Convert the string to snake_case return str .replace(/([a-z])([A-Z])/g, '$1_$2') .replace(/[\s-]+/g, '_') .toLowerCase(); } catch (error: any) { logger.error('Error transforming string to snake_case', { error: error.message, stack: error.stack, str, }); throw new Error(`Invalid string: ${error.message}`); } } /** * Transform a string to kebab-case * @param str The string to transform * @returns The kebab-case string */ public toKebabCase(str: string): string { try { // Convert the string to kebab-case return str .replace(/([a-z])([A-Z])/g, '$1-$2') .replace(/[\s_]+/g, '-') .toLowerCase(); } catch (error: any) { logger.error('Error transforming string to kebab-case', { error: error.message, stack: error.stack, str, }); throw new Error(`Invalid string: ${error.message}`); } } /** * Transform an object's keys to camelCase * @param obj The object to transform * @returns The transformed object with camelCase keys */ public objectKeysToCamelCase<T extends Record<string, any>>(obj: T): Record<string, any> { try { // If the object is null or not an object, return it as is if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) { return obj; } // Create a new object with camelCase keys const result: Record<string, any> = {}; // Transform each key in the object for (const [key, value] of Object.entries(obj)) { const camelKey = this.toCamelCase(key); // Recursively transform nested objects if (value !== null && typeof value === 'object') { if (Array.isArray(value)) { // Transform each item in the array result[camelKey] = value.map((item) => typeof item === 'object' && item !== null ? this.objectKeysToCamelCase(item) : item ); } else { // Transform the nested object result[camelKey] = this.objectKeysToCamelCase(value); } } else { // Copy the value as is result[camelKey] = value; } } return result; } catch (error: any) { logger.error('Error transforming object keys to camelCase', { error: error.message, stack: error.stack, obj, }); throw error; } } /** * Transform an object's keys to snake_case * @param obj The object to transform * @returns The transformed object with snake_case keys */ public objectKeysToSnakeCase<T extends Record<string, any>>(obj: T): Record<string, any> { try { // If the object is null or not an object, return it as is if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) { return obj; } // Create a new object with snake_case keys const result: Record<string, any> = {}; // Transform each key in the object for (const [key, value] of Object.entries(obj)) { const snakeKey = this.toSnakeCase(key); // Recursively transform nested objects if (value !== null && typeof value === 'object') { if (Array.isArray(value)) { // Transform each item in the array result[snakeKey] = value.map((item) => typeof item === 'object' && item !== null ? this.objectKeysToSnakeCase(item) : item ); } else { // Transform the nested object result[snakeKey] = this.objectKeysToSnakeCase(value); } } else { // Copy the value as is result[snakeKey] = value; } } return result; } catch (error: any) { logger.error('Error transforming object keys to snake_case', { error: error.message, stack: error.stack, obj, }); throw error; } } } // Export a singleton instance export const transformationUtil = new TransformationUtil();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zqushair/Frontapp-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server