basant307/AI_Governance_Project
045
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7import { MergeStrategy } from '../config/settingsSchema.js';8 9export type Mergeable =10 | string11 | number12 | boolean13 | null14 | undefined15 | object16 | Mergeable[];17 18export type MergeableObject = Record<string, Mergeable>;19 20function isPlainObject(item: unknown): item is MergeableObject {21 return !!item && typeof item === 'object' && !Array.isArray(item);22}23 24function mergeRecursively(25 target: MergeableObject,26 source: MergeableObject,27 getMergeStrategyForPath: (path: string[]) => MergeStrategy | undefined,28 path: string[] = [],29) {30 for (const key of Object.keys(source)) {31 if (key === '__proto__' || key === 'constructor' || key === 'prototype') {32 continue;33 }34 const newPath = [...path, key];35 const srcValue = source[key];36 const objValue = target[key];37 const mergeStrategy = getMergeStrategyForPath(newPath);38 39 if (mergeStrategy === MergeStrategy.SHALLOW_MERGE && objValue && srcValue) {40 const obj1 =41 typeof objValue === 'object' && objValue !== null ? objValue : {};42 const obj2 =43 typeof srcValue === 'object' && srcValue !== null ? srcValue : {};44 target[key] = { ...obj1, ...obj2 };45 continue;46 }47 48 if (Array.isArray(objValue)) {49 const srcArray = Array.isArray(srcValue) ? srcValue : [srcValue];50 if (mergeStrategy === MergeStrategy.CONCAT) {51 target[key] = objValue.concat(srcArray);52 continue;53 }54 if (mergeStrategy === MergeStrategy.UNION) {55 target[key] = [...new Set(objValue.concat(srcArray))];56 continue;57 }58 }59 60 if (isPlainObject(objValue) && isPlainObject(srcValue)) {61 mergeRecursively(objValue, srcValue, getMergeStrategyForPath, newPath);62 } else if (isPlainObject(srcValue)) {63 target[key] = {};64 mergeRecursively(65 target[key] as MergeableObject,66 srcValue,67 getMergeStrategyForPath,68 newPath,69 );70 } else {71 target[key] = srcValue;72 }73 }74 return target;75}76 77export function customDeepMerge(78 getMergeStrategyForPath: (path: string[]) => MergeStrategy | undefined,79 ...sources: MergeableObject[]80): MergeableObject {81 const result: MergeableObject = {};82 83 for (const source of sources) {84 if (source) {85 mergeRecursively(result, source, getMergeStrategyForPath);86 }87 }88 89 return result;90}91 