mixme
Version:
A library for recursively merging JavaScript objects
1 lines • 8.32 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["type AnObject = Record<string, unknown>;\n\ntype SerializableValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | SerializableArray\n | SerializableObject;\n\ntype SerializableArray = SerializableValue[];\n\ntype SerializableObject = {\n [key: string]: SerializableValue;\n};\n\ntype Merge<T extends object[]> = T extends [\n infer Head extends object,\n ...infer Tail extends object[],\n]\n ? Tail extends []\n ? Head\n : Merge<\n [\n MergeObjects<Head, Tail[0]>,\n // eslint-disable-next-line\n ...(Tail extends [infer _First, ...infer Rest] ? Rest : []),\n ]\n >\n : never;\n\ntype MergeObjects<T extends object, U extends object> = {\n [K in keyof T | keyof U]: K extends keyof T & keyof U\n ? T[K] extends object\n ? U[K] extends Buffer\n ? T[K]\n : U[K] extends object\n ? MergeObjects<T[K], U[K]>\n : T[K]\n : U[K]\n : K extends keyof T\n ? T[K]\n : K extends keyof U\n ? U[K]\n : never;\n};\n\ntype SnakeCase<S extends string> = S extends `${infer T}${infer U}`\n ? `${T extends Uppercase<T> ? \"_\" : \"\"}${Lowercase<T>}${SnakeCase<U>}`\n : S;\n\ntype SnakeCaseKeys<T> =\n T extends Array<infer U>\n ? Array<SnakeCaseKeys<U>>\n : T extends object\n ? {\n [K in keyof T as SnakeCase<string & K>]: SnakeCaseKeys<T[K]>;\n }\n : T;\n\nexport function camelize<T extends Record<string, unknown>>(\n source: T,\n depth: boolean | number = true,\n): SnakeCaseKeys<T> {\n const target: Record<string, unknown> = {};\n if (is_object_literal(source)) {\n const d = typeof depth === \"number\" && depth > 0 ? depth - 1 : depth;\n for (const key of Object.keys(source)) {\n const value = source[key];\n const camelizedKey = depth ? camelize_str(key) : key;\n if (is_object(value)) {\n target[camelizedKey] = camelize(value, d);\n } else {\n target[camelizedKey] = value;\n }\n }\n } else {\n return source as SnakeCaseKeys<T>;\n }\n return target as SnakeCaseKeys<T>;\n}\n\nexport function camelize_str(str: string): string {\n return str.replace(/[_.-](\\w|$)/g, (_: string, x: string) => x.toUpperCase());\n}\n\nexport function compare(el1: unknown, el2: unknown): boolean {\n if (is_object_literal(el1) && is_object_literal(el2)) {\n const keys1 = Object.keys(el1).sort();\n const keys2 = Object.keys(el2).sort();\n if (keys1.length !== keys2.length) {\n return false;\n }\n return keys1.every(\n (key, i) => key === keys2[i] && compare(el1[key], el2[key]),\n );\n }\n\n if (Array.isArray(el1) && Array.isArray(el2)) {\n if (el1.length !== el2.length) {\n return false;\n }\n return el1.every((item, i) => compare(item, el2[i]));\n }\n\n return el1 === el2;\n}\n\nexport function clone<T>(target: T): T {\n if (Array.isArray(target)) {\n return target.map((element) => clone(element)) as T;\n }\n if (target && typeof target === \"object\") {\n return mutate({}, target as AnObject) as T;\n }\n return target;\n}\n\nexport function is_object(obj: unknown): obj is AnObject {\n return Boolean(obj) && typeof obj === \"object\" && !Array.isArray(obj);\n}\n\nexport function is_object_literal(obj: unknown): obj is SerializableObject {\n if (typeof obj !== \"object\" || obj === null) {\n return false;\n }\n const proto = Object.getPrototypeOf(obj);\n if (proto === null) {\n return true;\n }\n let test = obj;\n while (true) {\n if (Object.getPrototypeOf((test = Object.getPrototypeOf(test))) === null)\n break;\n }\n return Object.getPrototypeOf(obj) === test;\n}\n\nexport function merge<T extends object[]>(...args: T): Merge<T> {\n return mutate({}, ...args);\n}\n\nexport function mutate<T extends object[]>(\n target: object | null | undefined,\n ...args: T\n): Merge<T> {\n for (let i = 0; i < args.length; i++) {\n const source = args[i];\n if (is_object_literal(source)) {\n if (target == null || !is_object_literal(target)) {\n target = {};\n }\n const targetObj = target as AnObject;\n for (const name of Object.keys(source)) {\n if (/__proto__|prototype/.test(name)) {\n continue;\n }\n targetObj[name] = mutate(\n targetObj[name] as object,\n source[name] as object,\n );\n }\n } else if (Array.isArray(source)) {\n target = source.map((element) => clone(element));\n } else if (source !== undefined) {\n target = source;\n }\n }\n return target as Merge<T>;\n}\n\nexport function snake_case<T extends Record<string, unknown>>(\n source: T,\n depth: boolean | number = true,\n): SnakeCaseKeys<T> {\n const target: Record<string, unknown> = {};\n if (is_object_literal(source)) {\n const d = typeof depth === \"number\" && depth > 0 ? depth - 1 : depth;\n for (const key of Object.keys(source)) {\n const value = source[key];\n const snakeKey = depth ? snake_case_str(key) : key;\n if (is_object(value)) {\n target[snakeKey] = snake_case(value, d);\n } else {\n target[snakeKey] = value;\n }\n }\n } else {\n return source as SnakeCaseKeys<T>;\n }\n return target as SnakeCaseKeys<T>;\n}\n\nexport function snake_case_str(str: string): string {\n return str\n .replace(/([a-z\\d])([A-Z]+)/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n}\n"],"mappings":"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","names":[]}