export {} import { validate } from 'jsonschema' import { Utils } from '../BaseUtils' export class DataUtils extends Utils { constructor() { super() } /** * @description Compare two objects and return the difference * @param {object} obj1 - The first object to compare. * @param {object} obj2 - The second object to compare. * @param {array} exclude - An array of keys to exclude from the comparison. * @returns {object|boolean} - Returns the difference between the two objects or false if there is no difference. */ compareObjects = ( obj1: Record, obj2: Record, exclude: Array = [] ): Record | Boolean => { const diff: any = {} for (const key in obj1) { if (obj1.hasOwnProperty(key) && !exclude.includes(key)) { if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') { const nestedDiff = this.compareObjects(obj1[key], obj2[key], exclude) if (Object.keys(nestedDiff).length > 0) { diff[key] = nestedDiff } } else if (obj1[key] !== obj2[key]) { diff[key] = { oldValue: obj1[key], newValue: obj2[key] } } } } for (const key in obj2) { if ( obj2.hasOwnProperty(key) && !obj1.hasOwnProperty(key) && !exclude.includes(key) ) { diff[key] = { oldValue: undefined, newValue: obj2[key] } } } return JSON.stringify(diff) === '{}' ? false : diff } /** * @description Validate JSON against a schema * @param {string|object} json - The JSON (or object) to validate. * @param {string|object} schema - The JSON schema (or object) to validate against. * @returns {boolean|object} - Returns true if valid or an object of issues. */ validateJson = ( json: string | object, schema: string | object ): boolean | string[] => { try { if (typeof json === 'string') { json = JSON.parse(json) } if (typeof schema === 'string') { schema = JSON.parse(schema) } const result = validate(json, schema) if (!result.valid) { return result.errors.map((e) => { const field = e.property.replace(/^instance\./, "") let errorField = schema['properties'][field] if(errorField?.errorMessage){ return errorField.errorMessage } else { return e.stack.replace(/^instance\./, "") } }) } return true } catch (error) { return false } } /** * @description Converts a string to camel-case * @param {string} str - The string to be converted * @returns {string} - Returns string formatted as camel-case */ toCamelCase = (str: string): string => { return str .toLowerCase() .replace(/(?:^\w|[A-Z]|\b\w)/g, (ltr, idx) => idx === 0 ? ltr.toLowerCase() : ltr.toUpperCase() ) .replace(/\s+/g, '') } /** * @description Converts a string in camel-case to snake-case * @param {string} str - The camel-case string to be converted * @returns {string} - Returns string formatted as snake-case */ camelToSnake = (str: string): string => { return str .replace(/\W+/g, '-') .replace(/([a-z\d])([A-Z])/g, '$1-$2') .toLowerCase() } /** * @description Removes hyphens * @param {string} str - Source string * @returns {string} - Returns string without hyphens */ hyphenToNull = (str: string): string => { return str.replace(/-/g, '') } /** * @description Replaces hyphens with spaces * @param {string} str - Source string * @returns {string} - Returns string without hyphens */ hyphenToSpace = (str: string): string => { return str.replace(/-/g, ' ') } /** * @description Replaces underscores with spaces * @param {string} str - Source string * @returns {string} - Returns string without underscores */ underscoreToSpace = (str: string): string => { return str.replace(/(_)/g, ' ') } /** * @description Replaces spaces with hyphens * @param {string} str - Source string * @returns {string} - Returns string with hyphens */ spaceToHyphen = (str: string): string => { return str.replace(/ /g, '-') } /** * @description Changes camel or pascal case to capitalized words * @param {string} str - Source string * @returns {string} - Returns converted string */ toRegularForm = (str: string): string => { return str .replace(/([A-Z])/g, ' $1') .replace(/^./, (ltr) => ltr.toUpperCase()) } /** * @description Prepend prefix to converted snake case string * @param {string} str - Source string * @returns {string} - Returns converted string */ prefixSnakeCase = (pre: string, str: string): string => { return `${pre}-${this.camelToSnake(str)}` } /** * @description Parses intials from a "name" string * @param {string} str - Name string (e.g. "John Hancock", "John", "John Tyler Smith") * @returns {string} - Returns initials */ parseInitials = (str: string): string => { const parts = str.split(' ') if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase() return `${parts[0].substring(0, 1).toUpperCase()}${parts[parts.length - 1].substring(0, 1).toUpperCase()}` } /** * @description Provides ordinal of a number * @param {number} num - Number to be converted to ordinal * @param {boolean} isUpperCase - Set to uppercase when true or lowercase when not true * @returns {string} - Returns ordinal string */ numToOrdinal = (num: number, isUpperCase: boolean): string => { if (typeof num !== 'number') throw Error('num must be a number') const s = ['th', 'st', 'nd', 'rd'] const v = num % 100 const output = num + (s[(v - 20) % 10] || s[v] || s[0]) return isUpperCase ? output.toUpperCase() : output } }