buildDeepPropertiesObject = (obj, prefix = '') => {
    const result = {}
    const descriptors = Object.getOwnPropertyDescriptors(obj)
    for (const key in descriptors) {
        if (Object.prototype.hasOwnProperty.call(descriptors, key)) {
            const descriptor = descriptors[key]
            const newPrefix = prefix ? `${prefix}.${key}` : key
            if (descriptor.get || descriptor.set) {
                result[newPrefix] = {
                    get: !!descriptor.get,
                    set: !!descriptor.set
                }
            } else if (typeof descriptor.value === 'object' && descriptor.value !== null) {
                result[newPrefix] = buildDeepPropertiesObject(descriptor.value, newPrefix)
            } else {
                result[newPrefix] = descriptor.value
            }
        }
    }
    return result
}
Recursively builds an object with all properties of an object, including getters and setters
@param {object} obj - The object to log
@param {string} [prefix=''] - The prefix for nested properties
@returns {object} - The nested object with all properties