Object metadata API create one using workspace migration v2 (#13420)
# Introduction In this PR we create basic transpilation methods and utils to handle input to flat, entity to flat, object maps to flat. In order to transpile everything into a common validation that will be implemented in another PR ## FieldMetadataEntity typing Added `never | null` to fields that should never be in order to ease general abstracted method to pass null, as anw it's what is in the database ## Todo - ~~Create a feature flag~~ - Integration test for object creation through metadata api + pg col introspection and snapshoting
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Deep merges two objects or arrays recursively
|
||||
* - Objects are merged by combining their properties
|
||||
* - Arrays are merged by concatenating them
|
||||
* - Primitive values from target override source
|
||||
* - Null values from target are preserved
|
||||
* - Undefined values from target are ignored
|
||||
* - Date and RegExp objects are treated as primitives (replaced, not merged)
|
||||
*
|
||||
* @param source The source object to merge from
|
||||
* @param target The target object to merge into
|
||||
* @returns A new merged object
|
||||
*/
|
||||
export const deepMerge = <T extends object>(
|
||||
source: Required<T>,
|
||||
target: Required<T>,
|
||||
): T => {
|
||||
// Handle null/undefined cases
|
||||
if (!source) return target as T;
|
||||
if (!target) return source;
|
||||
|
||||
// Create a new object to avoid mutations
|
||||
const output = { ...source };
|
||||
|
||||
// Iterate through all keys in target
|
||||
Object.keys(target).forEach((key) => {
|
||||
const sourceValue = source[key as keyof T];
|
||||
const targetValue = target[key as keyof T];
|
||||
|
||||
// Skip undefined values in target
|
||||
if (targetValue === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle null values - explicitly assign them
|
||||
if (targetValue === null) {
|
||||
output[key as keyof T] = null as T[keyof T];
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle arrays - concatenate them
|
||||
if (Array.isArray(sourceValue) && Array.isArray(targetValue)) {
|
||||
output[key as keyof T] = [...sourceValue, ...targetValue] as T[keyof T];
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Date and RegExp objects - treat them as primitives
|
||||
if (
|
||||
targetValue instanceof Date ||
|
||||
targetValue instanceof RegExp ||
|
||||
sourceValue instanceof Date ||
|
||||
sourceValue instanceof RegExp
|
||||
) {
|
||||
output[key as keyof T] = targetValue as T[keyof T];
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle nested objects - recurse
|
||||
if (
|
||||
sourceValue &&
|
||||
targetValue &&
|
||||
typeof sourceValue === 'object' &&
|
||||
typeof targetValue === 'object' &&
|
||||
!Array.isArray(sourceValue) &&
|
||||
!Array.isArray(targetValue)
|
||||
) {
|
||||
output[key as keyof T] = deepMerge(
|
||||
sourceValue as object,
|
||||
targetValue as object,
|
||||
) as T[keyof T];
|
||||
return;
|
||||
}
|
||||
|
||||
// For primitives
|
||||
output[key as keyof T] = targetValue as T[keyof T];
|
||||
});
|
||||
|
||||
return output;
|
||||
};
|
||||
Reference in New Issue
Block a user