UNPKG

@sandboxed/diff

Version:

A zero dependency, high-performance, security-conscious JavaScript diffing library

1 lines 39.2 kB
{"version":3,"sources":["../src/index.ts","../src/utils/constants.ts","../src/utils/fns.ts","../src/diff/shared.ts","../src/diff/diffObjects.ts","../src/diff/diffSets.ts","../src/diff/diffMaps.ts","../src/diff/diffConstructors.ts","../src/diff/index.ts","../src/utils/toDiffString.ts"],"sourcesContent":["import recursiveDiff from './diff';\nimport type { DiffConfig, DiffStringConfig, Diff } from './types';\nimport {\n ChangeType,\n DefaultPathHints,\n MAX_DEPTH,\n MAX_KEYS,\n MAX_TIMEOUT_MS,\n} from './utils/constants';\nimport toDiffString from './utils/toDiffString';\n\n/**\n * Returns the deep difference between two objects. The return object contains the stringified difference for easy rendering.\n * @param {any} lhs - Lef-hand side object. Can be either Object, Array, Set or Map.\n * @param {any} rhs - Right-hand side object.\n * @param {DiffConfig} [config] - Configuration to be used\n * @param {DiffConfig['exclude']} [config.exclude=[]] - Type differences to be ignored.\n * @param {DiffConfig['include']} [config.include=['add', 'remove', 'update', 'noop']] - Type differences to be logged.\n * @param {DiffConfig['strict']} [config.strict=true] - Indicates whether to enforce type check.\n * @param {DiffConfig['showUpdatedOnly']} [config.showUpdatedOnly=false] - Indicates whether a `remove` operation should be included for every `update`\n * @param {DiffConfig['pathHints']} [config.pathHints={ map: '__MAP__', set: '__SET__' }] - Strings to use as hints for Sets and Maps in the path array\n * @param {DiffConfig['maxDepth']} [config.maxDepth=50] - Max recursive depth that can be traversed before throwing\n * @param {DiffConfig['maxKeys']} [config.maxKeys=1000] - Max keys that can be processed at a time. Throws when LHS + RHS keys > maxKeys\n * @param {DiffConfig['timeout']} [config.timeout=1000] - Throws when the diffing timeout is met\n * @param {DiffConfig['redactKeys']} [config.redactKeys=[]] - Replaces the values of these keys with *****\n */\nfunction diff(lhs: any, rhs: any, config: DiffConfig): Diff {\n const defaultConfig: DiffConfig = {\n include: [\n ChangeType.ADD,\n ChangeType.REMOVE,\n ChangeType.UPDATE,\n ChangeType.NOOP,\n ],\n exclude: [],\n strict: true,\n showUpdatedOnly: false,\n pathHints: {\n map: DefaultPathHints.map,\n set: DefaultPathHints.set,\n },\n maxDepth: MAX_DEPTH,\n maxKeys: MAX_KEYS,\n timeout: MAX_TIMEOUT_MS,\n redactKeys: [\n 'password',\n 'secret',\n 'token',\n 'Symbol(password)',\n 'Symbol(secret)',\n 'Symbol(token)',\n ],\n };\n\n const mergedConfig: DiffConfig = {\n ...defaultConfig,\n ...config,\n };\n\n if (!mergedConfig.maxDepth) mergedConfig.maxDepth = MAX_DEPTH;\n if (!mergedConfig.maxKeys) mergedConfig.maxKeys = MAX_KEYS;\n if (!mergedConfig.timeout) mergedConfig.timeout = MAX_TIMEOUT_MS;\n\n mergedConfig.include = Array.isArray(mergedConfig.include)\n ? mergedConfig.include\n : [mergedConfig.include];\n\n mergedConfig.exclude = Array.isArray(mergedConfig.exclude)\n ? mergedConfig.exclude\n : [mergedConfig.exclude];\n\n const diffResult = recursiveDiff({\n lhs,\n rhs,\n config: mergedConfig,\n depth: 1,\n parent: null,\n seen: new WeakMap(),\n initialChangeType: ChangeType.NOOP,\n path: [],\n startedAt: Date.now(),\n });\n\n // All the changes are \"noop\", or empty array\n const areEqual = diffResult.every(\n (result) => result.type === ChangeType.NOOP\n );\n\n Object.defineProperty(diffResult, 'toDiffString', {\n value: (diffStringConfig: DiffStringConfig) =>\n toDiffString(diffResult, diffStringConfig),\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(diffResult, 'equal', {\n value: areEqual,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n return diffResult as Diff;\n}\n\nexport { ChangeType };\n\nexport default diff;\n","export const Iterables = new Set([Object, Array, Set, Map]);\n\nexport enum ChangeType {\n ADD = 'add',\n UPDATE = 'update',\n REMOVE = 'remove',\n NOOP = 'noop',\n}\n\nexport const DefaultPathHints = {\n map: '__MAP__',\n set: '__SET__',\n};\n\nexport const MAX_DEPTH = 50;\n\nexport const MAX_KEYS = 1000;\n\nexport const ITERATION_TIMEOUT_CHECK = 1000;\n\nexport const MAX_TIMEOUT_MS = 1000;\n\nexport const REDACTED = '*****';\n","import { Iterables } from './constants';\n\nexport function isPrimitive(value: any) {\n return value !== Object(value);\n}\n\nexport function getRawValue(value: any) {\n // If value is primitive (except symbol), then perform validations in its pure form\n if (isPrimitive(value) && typeof value !== 'symbol') return value;\n\n // Serializes the value to perform validations\n return value.toString();\n}\n\nexport function isNullOrUndefined(value: any) {\n return value === null || value === undefined;\n}\nexport function isCustomClassInstance(object: any) {\n if (\n isNullOrUndefined(object) ||\n typeof object !== 'object' ||\n !object.constructor\n ) {\n return false;\n }\n\n return !object.constructor?.toString?.().includes('[native code]');\n}\n\nexport function emptyShellClone(object: any) {\n // Clone the instance shell\n if (isCustomClassInstance(object)) {\n return Object.create(Object.getPrototypeOf(object));\n }\n\n // Objects created with Object.create(null) don't have constructor\n if (isObject(object)) {\n return Object.create(null);\n }\n\n // Creates an empty instance from the native constructor\n return new object.constructor();\n}\n\nexport function getWrapper(obj: any) {\n let wrapper = ['{', '}'];\n\n if (Array.isArray(obj)) {\n wrapper = ['[', ']'];\n } else if (isCustomClassInstance(obj)) {\n wrapper = [`${obj.constructor.name} {`, '}'];\n } else if (obj instanceof Map) {\n wrapper = [`Map (${obj.size}) {`, '}'];\n } else if (obj instanceof Set) {\n wrapper = ['Set [', ']'];\n }\n\n return wrapper;\n}\n\n/**\n * Returns the ref type of the value\n * @param value - The value\n * @returns string\n */\nexport function getRef(value: any) {\n return `ref<${value?.constructor?.name || typeof value}>`;\n}\n\nexport function isObject(obj: any) {\n return (\n obj !== null &&\n typeof obj === 'object' &&\n (Object.getPrototypeOf(obj) === Object.prototype ||\n Object.getPrototypeOf(obj) === null)\n );\n}\n\nexport function areObjects(a: any, b: any) {\n return isObject(a) && isObject(b);\n}\n\nexport function getEnumerableKeys(obj: any) {\n return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];\n}\n\nexport function isIterable(obj: any) {\n return (\n Iterables.has(obj?.constructor) ||\n isObject(obj) ||\n isCustomClassInstance(obj)\n );\n}\n","import type { DiffConfig, DiffResult, PathHints } from '../types';\nimport { ChangeType, REDACTED } from '../utils/constants';\nimport { getRawValue, getWrapper, isPrimitive } from '../utils/fns';\n\nexport function lastPathValue(changeType: ChangeType, value: any) {\n return { deleted: changeType === ChangeType.REMOVE, value };\n}\n\nexport function includeDiffType(type: ChangeType, config: DiffConfig) {\n return config.include?.includes?.(type) && !config.exclude?.includes?.(type);\n}\n\nexport function shouldRedactValue(key: any, config: DiffConfig) {\n const rawKey = getRawValue(key);\n\n return config.redactKeys?.includes?.(rawKey);\n}\n\nexport function createReplacer(config: DiffConfig, obj: any) {\n const seen = new WeakSet();\n\n return function replacer(k: any, v: any) {\n // Redact the entire value if the key matches\n if (shouldRedactValue(k, config)) return REDACTED;\n\n // Returns circular if iterating over the same object from the replacer\n if (k !== '' && v === obj) return '[Circular]';\n\n if (v && typeof v === 'object') {\n if (seen.has(v)) return '[Circular]';\n\n seen.add(v);\n }\n\n if (v instanceof Set) {\n const stringified = JSON.stringify([...v.values()], replacer);\n\n seen.delete(v);\n return `Set ${stringified}`;\n }\n\n if (v instanceof Map) {\n const entries = [...v.entries()];\n const stringified = entries\n .map(([key, value]) => {\n if (seen.has(key)) {\n return `\"[Circular]\": ${JSON.stringify(value, replacer)}`;\n }\n\n if (!isPrimitive(key)) {\n seen.add(key);\n }\n\n const serializedValue = shouldRedactValue(key, config)\n ? REDACTED\n : JSON.stringify(value, replacer);\n const serialized = `${JSON.stringify(key, replacer)}: ${serializedValue}`;\n\n if (!isPrimitive) {\n seen.delete(key);\n }\n\n return serialized;\n })\n .join(', ');\n\n seen.delete(v);\n return `Map (${entries.length}) { ${stringified} }`;\n }\n\n if (v instanceof Function) {\n return `Function ${v.name || '(anonymous)'}`;\n }\n\n if (typeof v === 'symbol') {\n return v.toString();\n }\n\n if (typeof v === 'bigint') {\n return `BigInt(${v.toString()})`;\n }\n\n seen.delete(v);\n return v;\n };\n}\n\nexport function stringify(obj: any, config: DiffConfig) {\n return JSON.stringify(obj, createReplacer(config, obj));\n}\n\nexport function getObjectChangeResult(\n lhs: any,\n rhs: any,\n depth: number,\n key: any,\n parsedKey: any,\n config: DiffConfig,\n path: Array<any>\n) {\n const isLhsMap = lhs instanceof Map;\n const isRhsMap = rhs instanceof Map;\n\n let valueInLhs = lhs?.[key];\n let valueInRhs = rhs?.[key];\n let keyInLhs = Object.hasOwn(lhs, key);\n let keyInRhs = Object.hasOwn(rhs, key);\n\n if (isLhsMap) {\n valueInLhs = lhs.get(key);\n keyInLhs = lhs.has(key);\n }\n\n if (isRhsMap) {\n valueInRhs = rhs.get(key);\n keyInRhs = rhs.has(key);\n }\n\n const redactValue = shouldRedactValue(key, config);\n const rawValueInLhs = getRawValue(valueInLhs);\n const rawValueInRhs = getRawValue(valueInRhs);\n const formattedValueInLhs = stringify(\n redactValue ? REDACTED : rawValueInLhs,\n config\n );\n const formattedValueInRhs = stringify(\n redactValue ? REDACTED : rawValueInRhs,\n config\n );\n\n let type = ChangeType.NOOP;\n let formattedValue = formattedValueInRhs; // Select the most recent change\n let pathValue = valueInRhs;\n\n if (!keyInLhs && keyInRhs) {\n // added in rhs\n type = ChangeType.ADD;\n } else if (keyInLhs && !keyInRhs) {\n // removed in rhs\n type = ChangeType.REMOVE;\n formattedValue = formattedValueInLhs;\n pathValue = valueInLhs;\n } else if (\n config.strict\n ? rawValueInLhs !== rawValueInRhs\n : rawValueInLhs != rawValueInRhs\n ) {\n // different in rhs\n type = ChangeType.UPDATE;\n }\n\n const result: DiffResult[] = [];\n\n // If the type of change should be included in the results\n if (includeDiffType(type, config)) {\n const stringifiedParsedKey = stringify(parsedKey, config);\n\n if (type === ChangeType.UPDATE && !config.showUpdatedOnly) {\n result.push({\n type: ChangeType.REMOVE,\n str: `${stringifiedParsedKey}: ${formattedValueInLhs},`,\n depth,\n path: [...path, lastPathValue(ChangeType.REMOVE, valueInLhs)],\n });\n }\n\n result.push({\n type,\n str: `${stringifiedParsedKey}: ${formattedValue},`,\n depth,\n path: [...path, lastPathValue(type, pathValue)],\n });\n }\n\n return result;\n}\n\nexport function getPathHint(config: DiffConfig, type: keyof PathHints) {\n if (typeof config.pathHints === 'object') {\n const hint = config.pathHints[type];\n\n if (typeof hint === 'string') return hint;\n }\n\n // no hint for this type\n return null;\n}\n\nexport function buildResult(\n rhs: any,\n result: DiffResult[],\n depth: number,\n initialChangeType: ChangeType,\n parent: any,\n path: any[],\n config: DiffConfig\n) {\n if (!includeDiffType(initialChangeType, config)) return result;\n\n const parentDepth = depth - 1;\n const [open, close] = getWrapper(rhs);\n\n return [\n {\n type: initialChangeType,\n str: parentDepth > 0 ? `${stringify(parent, config)}: ${open}` : open,\n depth: parentDepth,\n path,\n },\n ...result,\n {\n type: initialChangeType,\n str: parentDepth > 0 ? `${close},` : close,\n depth: parentDepth,\n path,\n },\n ];\n}\n\n// Prevents bloating the memory for large objects\nexport function timeoutSecurityCheck(startedAt: number, config: DiffConfig) {\n if (Date.now() - startedAt > config.timeout) {\n throw new Error('Diff took too much time! Aborting.');\n }\n}\n\nexport function maxKeysSecurityCheck(size: number, config: DiffConfig) {\n if (size > config.maxKeys) {\n throw new Error('Object is too big to continue! Aborting.');\n }\n}\n","import { type DiffResult, DiffObjectArgs } from '../types';\nimport { ITERATION_TIMEOUT_CHECK } from '../utils/constants';\nimport { getEnumerableKeys, isIterable } from '../utils/fns';\nimport {\n buildResult,\n getObjectChangeResult,\n maxKeysSecurityCheck,\n timeoutSecurityCheck,\n} from './shared';\n\nfunction diffObjects({\n recursiveDiff,\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n}: DiffObjectArgs): DiffResult[] {\n const result: DiffResult[] = [];\n\n const lhsKeys = getEnumerableKeys(lhs);\n maxKeysSecurityCheck(lhsKeys.length, config);\n\n const rhsKeys = getEnumerableKeys(rhs);\n maxKeysSecurityCheck(rhsKeys.length, config);\n\n const keys = new Set<string | number | symbol>([...lhsKeys, ...rhsKeys]);\n\n let i = 0;\n for (const key of keys) {\n if (i++ % ITERATION_TIMEOUT_CHECK === 0) {\n timeoutSecurityCheck(startedAt, config);\n }\n\n const lhsValue = Array.isArray(lhs) ? lhs[key as number] : lhs?.[key];\n const rhsValue = Array.isArray(rhs) ? rhs[key as number] : rhs?.[key];\n const numericKey = typeof key !== 'symbol' ? Number(key) : NaN;\n const parsedKey = isNaN(numericKey) ? key : numericKey;\n const updatedPath = [...path, parsedKey];\n\n if (isIterable(lhsValue) || isIterable(rhsValue)) {\n result.push(\n ...recursiveDiff({\n lhs: lhsValue,\n rhs: rhsValue,\n config,\n depth: depth + 1,\n parent: parsedKey,\n seen,\n initialChangeType,\n path: updatedPath,\n startedAt,\n })\n );\n continue;\n }\n\n result.push(\n ...getObjectChangeResult(\n lhs,\n rhs,\n depth,\n key,\n parsedKey,\n config,\n updatedPath\n )\n );\n }\n\n seen.delete(lhs);\n seen.delete(rhs);\n\n return buildResult(\n rhs,\n result,\n depth,\n initialChangeType,\n parent,\n path,\n config\n );\n}\n\nexport default diffObjects;\n","import { DiffResult, DiffSetArgs } from '../types';\nimport { ChangeType, ITERATION_TIMEOUT_CHECK } from '../utils/constants';\nimport { getRef, isIterable } from '../utils/fns';\nimport {\n buildResult,\n getPathHint,\n includeDiffType,\n lastPathValue,\n maxKeysSecurityCheck,\n stringify,\n timeoutSecurityCheck,\n} from './shared';\n\nfunction diffSets({\n recursiveDiff,\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n}: DiffSetArgs): DiffResult[] {\n const result: DiffResult[] = [];\n\n maxKeysSecurityCheck(lhs.size, config);\n maxKeysSecurityCheck(rhs.size, config);\n\n const mergedSet = new Set([...lhs, ...rhs]);\n\n let i = 0;\n for (const value of mergedSet) {\n if (i++ % ITERATION_TIMEOUT_CHECK === 0) {\n timeoutSecurityCheck(startedAt, config);\n }\n\n const existsInLhs = lhs.has(value);\n const existsInRhs = rhs.has(value);\n const hint = getPathHint(config, 'set');\n const updatedPath = [...path];\n\n if (hint) {\n updatedPath.push(hint);\n }\n\n if (isIterable(value)) {\n result.push(\n ...recursiveDiff({\n lhs: existsInLhs ? value : undefined,\n rhs: existsInRhs ? value : undefined,\n config,\n depth: depth + 1,\n parent: getRef(value),\n seen,\n initialChangeType,\n path: updatedPath,\n startedAt,\n })\n );\n continue;\n }\n\n let type = ChangeType.NOOP;\n\n if (existsInLhs && !existsInRhs) {\n type = ChangeType.REMOVE;\n } else if (!existsInLhs && existsInRhs) {\n type = ChangeType.ADD;\n }\n\n if (includeDiffType(type, config)) {\n result.push({\n type,\n str: `${stringify(value, config)},`,\n depth,\n path: [...updatedPath, lastPathValue(type, value)],\n });\n }\n }\n\n seen.delete(lhs);\n seen.delete(rhs);\n\n return buildResult(\n rhs,\n result,\n depth,\n initialChangeType,\n parent,\n path,\n config\n );\n}\n\nexport default diffSets;\n","import { DiffResult, DiffMapArgs } from '../types';\nimport { ITERATION_TIMEOUT_CHECK } from '../utils/constants';\nimport { isIterable } from '../utils/fns';\nimport {\n buildResult,\n getObjectChangeResult,\n getPathHint,\n maxKeysSecurityCheck,\n timeoutSecurityCheck,\n} from './shared';\n\nfunction diffMaps({\n recursiveDiff,\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n}: DiffMapArgs): DiffResult[] {\n const result: DiffResult[] = [];\n\n maxKeysSecurityCheck(lhs.size, config);\n maxKeysSecurityCheck(rhs.size, config);\n\n const mergedMapKeys = new Set([...lhs.keys(), ...rhs.keys()]);\n\n let i = 0;\n for (const key of mergedMapKeys) {\n if (i++ % ITERATION_TIMEOUT_CHECK === 0) {\n timeoutSecurityCheck(startedAt, config);\n }\n\n const keyInLhs = lhs.has(key);\n const keyInRhs = rhs.has(key);\n const lhsValue = keyInLhs ? lhs.get(key) : null;\n const rhsValue = keyInRhs ? rhs.get(key) : null;\n const hint = getPathHint(config, 'map');\n const pathUpdate = hint ? [hint, key] : [key];\n const updatedPath = [...path, ...pathUpdate];\n\n if (isIterable(lhsValue) || isIterable(rhsValue)) {\n result.push(\n ...recursiveDiff({\n lhs: lhsValue,\n rhs: rhsValue,\n config,\n depth: depth + 1,\n parent: key,\n seen,\n initialChangeType,\n path: updatedPath,\n startedAt,\n })\n );\n continue;\n }\n\n result.push(\n ...getObjectChangeResult(lhs, rhs, depth, key, key, config, updatedPath)\n );\n }\n\n seen.delete(lhs);\n seen.delete(rhs);\n\n return buildResult(\n rhs,\n result,\n depth,\n initialChangeType,\n parent,\n path,\n config\n );\n}\n\nexport default diffMaps;\n","import { type DiffResult, DiffConstructorArgs } from '../types';\nimport { ChangeType } from '../utils/constants';\nimport { emptyShellClone, isObject } from '../utils/fns';\n\nfunction diffConstructors({\n recursiveDiff,\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n}: DiffConstructorArgs): DiffResult[] {\n // Different Constructors\n let modLhs = lhs;\n let modRhs = rhs;\n let defaultChangeType = initialChangeType;\n\n if (isObject(rhs) || rhs?.constructor) {\n // Added in rhs. Use rhs prototype to traverse the added properties\n modLhs = emptyShellClone(rhs);\n\n defaultChangeType = ChangeType.ADD;\n } else if (isObject(lhs) || lhs?.constructor) {\n // Removed in rhs. Use lhs prototype to traverse the removed properties\n modRhs = emptyShellClone(lhs);\n\n defaultChangeType = ChangeType.REMOVE;\n } else {\n // Fail for unknown edge cases\n throw new Error(\"Edge case raised, I don't know how to handle this input\");\n }\n\n return recursiveDiff({\n lhs: modLhs,\n rhs: modRhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType: defaultChangeType,\n path,\n startedAt,\n });\n}\n\nexport default diffConstructors;\n","import { type DiffResult, RecursiveDiffArgs } from '../types';\nimport diffObjects from './diffObjects';\nimport diffSets from './diffSets';\nimport diffMaps from './diffMaps';\nimport diffConstructors from './diffConstructors';\nimport { ChangeType } from '../utils/constants';\nimport { areObjects, isNullOrUndefined, isPrimitive } from '../utils/fns';\nimport {\n includeDiffType,\n lastPathValue,\n timeoutSecurityCheck,\n stringify,\n} from './shared';\n\nfunction recursiveDiff({\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n}: RecursiveDiffArgs): DiffResult[] {\n // Prevents stack overflow\n if (depth > config.maxDepth) {\n throw new Error('Max depth exceeded!');\n }\n\n // Checks for timeout before proceeding\n timeoutSecurityCheck(startedAt, config);\n\n // Allows printing the first level of circular references\n const lhsSeen = seen.get(lhs) ?? 0;\n const rhsSeen = seen.get(rhs) ?? 0;\n\n if (lhsSeen > 1 || rhsSeen > 1) {\n if (!includeDiffType(initialChangeType, config)) return [];\n\n return [\n {\n type: initialChangeType,\n str: `${stringify(parent, config)}: [Circular],`,\n depth: depth - 1,\n path,\n },\n ];\n }\n\n // Prevents circular references except for primitives\n if (typeof lhs === 'object' && lhs !== null) seen.set(lhs, lhsSeen + 1);\n if (typeof rhs === 'object' && rhs !== null) seen.set(rhs, rhsSeen + 1);\n\n const args = {\n recursiveDiff,\n lhs,\n rhs,\n config,\n depth,\n parent,\n seen,\n initialChangeType,\n path,\n startedAt,\n };\n\n // Handles comparing primitives\n if (isPrimitive(lhs) && isPrimitive(rhs)) {\n // Return early if it's the same primitive\n if (config.strict ? lhs === rhs : lhs == rhs) {\n return [];\n }\n\n const parentDepth = depth - 1;\n const lhsValue = stringify(lhs, config);\n const rhsValue = stringify(rhs, config);\n\n const result = [];\n\n if (includeDiffType(ChangeType.UPDATE, config)) {\n if (!config.showUpdatedOnly) {\n result.push({\n type: ChangeType.REMOVE,\n str: `${lhsValue}`,\n depth: parentDepth,\n path: [...path, lastPathValue(ChangeType.REMOVE, lhs)],\n });\n }\n\n result.push({\n type: ChangeType.UPDATE,\n str: `${rhsValue}`,\n depth: parentDepth,\n path: [...path, lastPathValue(ChangeType.UPDATE, rhs)],\n });\n }\n\n return result;\n }\n\n // Different constructor handler\n if (\n !areObjects(lhs, rhs) && // Skips for Object.create(null) vs {}\n (lhs?.constructor !== rhs?.constructor ||\n (isNullOrUndefined(lhs) && rhs) ||\n (lhs && isNullOrUndefined(rhs)))\n ) {\n return diffConstructors(args);\n }\n\n // SETS\n if (lhs instanceof Set && rhs instanceof Set) {\n return diffSets(args);\n }\n\n // MAPS\n if (lhs instanceof Map && rhs instanceof Map) {\n return diffMaps(args);\n }\n\n // Arrays and Objects\n return diffObjects(args);\n}\n\nexport default recursiveDiff;\n","import type { DiffResult, DiffStringConfig } from '../types';\nimport { ChangeType } from './constants';\n\nconst ANSI_RESET = '\\x1b[0m';\n\nfunction colorWrapper(color: string) {\n return (str: string) => `${color}${str}${ANSI_RESET}`;\n}\n\nconst ansiColors = {\n [ChangeType.REMOVE]: colorWrapper('\\x1b[31m'),\n [ChangeType.ADD]: colorWrapper('\\x1b[32m'),\n [ChangeType.UPDATE]: colorWrapper('\\x1b[33m'),\n [ChangeType.NOOP]: colorWrapper(''),\n};\n\n/**\n * Takes the diff result and returns a diff string in md. + Added, - Removed, ! Updated\n * @param {DiffResult[]} diff - The result from the diff\n * @param {DiffStringConfig} [config]\n * @param {DiffStringConfig['withColors']} [config.withColors=true] - If true, outputs the string formatted with AnsiColors\n * @param {DiffStringConfig['colors']} [config.colors] - Each function takes a string and returns it formatted with ansi colors. Maps to each ChangeType.\n * @param {DiffStringConfig['symbols']} [config.symbols] - String map for each ChangeType\n * @param {DiffStringConfig['wrapper']} [config.wrapper=['```diff', '```']] - Strings that wrap the diff string output\n * @param {DiffStringConfig['indentSize']} [config.indentSize=2]\n */\nexport default function toDiffString(\n diff: DiffResult[],\n config?: DiffStringConfig\n) {\n const defaultConfig: DiffStringConfig = {\n withColors: true,\n colors: ansiColors,\n wrapper: [],\n indentSize: 2,\n symbols: {\n [ChangeType.ADD]: '+',\n [ChangeType.REMOVE]: '-',\n [ChangeType.UPDATE]: '!',\n [ChangeType.NOOP]: '',\n },\n };\n\n const mergedConfig = {\n ...defaultConfig,\n ...config,\n colors: {\n ...defaultConfig.colors,\n ...config?.colors,\n },\n symbols: {\n ...defaultConfig.symbols,\n ...config?.symbols,\n },\n };\n\n const diffString = diff\n .map(({ type, str, depth }, index) => {\n let symbolString = mergedConfig.symbols[type];\n\n if (index > 0 && index < diff.length - 1 && !symbolString.length) {\n symbolString = ` ${mergedConfig.symbols[type]}`;\n }\n\n let buildStr = `${symbolString}${' '.repeat(depth * mergedConfig.indentSize)}${str}`;\n\n if (mergedConfig.withColors) {\n buildStr = mergedConfig.colors[type](buildStr);\n }\n\n return buildStr;\n })\n .join('\\n');\n\n const [open = '', close = ''] = mergedConfig.wrapper || [];\n\n return `${open ? `${open}\\n` : ''}${diffString}${close ? `\\n${close}` : ''}`;\n}\n"],"mappings":"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","names":["ChangeType","recursiveDiff","recursiveDiff","recursiveDiff","recursiveDiff","diff"]}