+ if (value instanceof Date) {
+ return new Date(value.valueOf()) as O
+ }
+ if (typeof value !== 'object' || value === null) {
+ return value as unknown as O
+ }
+ const clone: Record<string, CloneableData> = {}
+ refs.set(value, clone as O)
+ for (const key of Object.keys(value)) {
+ clone[typeof formatKey === 'function' ? formatKey(key) : key] = deepClone(
+ value[key],
+ formatKey,
+ refs
+ )
+ }
+ return clone as O
+}
+
+export const cloneObject = <T>(object: T): T => {
+ return deepClone(object as CloneableData) as T
+}
+
+export const hasOwnProp = (object: unknown, property: PropertyKey): boolean => {
+ return isObject(object) && Object.hasOwn(object as object, property)
+}
+
+export const isCFEnvironment = (): boolean => {
+ return env.VCAP_APPLICATION != null
+}
+
+export const isIterable = <T>(obj: T): boolean => {
+ return obj != null ? typeof obj[Symbol.iterator as keyof T] === 'function' : false
+}
+
+const isString = (value: unknown): boolean => {
+ return typeof value === 'string'
+}
+
+export const isEmptyString = (value: unknown): boolean => {
+ return value == null || (isString(value) && (value as string).trim().length === 0)
+}
+
+export const isNotEmptyString = (value: unknown): boolean => {
+ return isString(value) && (value as string).trim().length > 0
+}