feat: refactor folder structure (#4498)
* feat: wip refactor folder structure * Fix * fix position --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -0,0 +1,76 @@
|
||||
import {
|
||||
ComputedPartialObjectMetadata,
|
||||
PartialObjectMetadata,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface';
|
||||
import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine-metadata/object-metadata/object-metadata.entity';
|
||||
import { generateTargetColumnMap } from 'src/engine-metadata/field-metadata/utils/generate-target-column-map.util';
|
||||
import { FieldMetadataType } from 'src/engine-metadata/field-metadata/field-metadata.entity';
|
||||
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
|
||||
export const computeStandardObject = (
|
||||
standardObjectMetadata: Omit<PartialObjectMetadata, 'standardId'> & {
|
||||
standardId: string | null;
|
||||
},
|
||||
originalObjectMetadata: ObjectMetadataEntity,
|
||||
customObjectMetadataCollection: ObjectMetadataEntity[] = [],
|
||||
): ComputedPartialObjectMetadata => {
|
||||
const fields: ComputedPartialFieldMetadata[] = [];
|
||||
|
||||
for (const partialFieldMetadata of standardObjectMetadata.fields) {
|
||||
if ('paramsFactory' in partialFieldMetadata) {
|
||||
// Compute standard fields of custom object
|
||||
for (const customObjectMetadata of customObjectMetadataCollection) {
|
||||
const { paramsFactory, ...rest } = partialFieldMetadata;
|
||||
const { joinColumn, ...data } = paramsFactory(customObjectMetadata);
|
||||
|
||||
// Relation
|
||||
fields.push({
|
||||
...data,
|
||||
...rest,
|
||||
defaultValue: null,
|
||||
targetColumnMap: {},
|
||||
});
|
||||
|
||||
// Foreign key
|
||||
fields.push({
|
||||
...rest,
|
||||
standardId: createDeterministicUuid(data.standardId),
|
||||
name: joinColumn,
|
||||
type: FieldMetadataType.UUID,
|
||||
label: `${data.label} ID (foreign key)`,
|
||||
description: `${data.description} id foreign key`,
|
||||
defaultValue: null,
|
||||
icon: undefined,
|
||||
targetColumnMap: generateTargetColumnMap(
|
||||
FieldMetadataType.UUID,
|
||||
rest.isCustom,
|
||||
joinColumn,
|
||||
),
|
||||
isSystem: true,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const labelText =
|
||||
typeof partialFieldMetadata.label === 'function'
|
||||
? partialFieldMetadata.label(originalObjectMetadata)
|
||||
: partialFieldMetadata.label;
|
||||
const descriptionText =
|
||||
typeof partialFieldMetadata.description === 'function'
|
||||
? partialFieldMetadata.description(originalObjectMetadata)
|
||||
: partialFieldMetadata.description;
|
||||
|
||||
fields.push({
|
||||
...partialFieldMetadata,
|
||||
label: labelText,
|
||||
description: descriptionText,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...standardObjectMetadata,
|
||||
fields,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,12 @@
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
|
||||
export const convertClassNameToObjectMetadataName = (name: string): string => {
|
||||
const classSuffix = 'ObjectMetadata';
|
||||
let objectName = camelCase(name);
|
||||
|
||||
if (objectName.endsWith(classSuffix)) {
|
||||
objectName = objectName.slice(0, -classSuffix.length);
|
||||
}
|
||||
|
||||
return objectName;
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
export const createDeterministicUuid = (inputUuid: string): string => {
|
||||
const hash = createHash('sha256').update(inputUuid).digest('hex');
|
||||
|
||||
return `20202020-${hash.substring(0, 4)}-4${hash.substring(
|
||||
4,
|
||||
7,
|
||||
)}-8${hash.substring(7, 10)}-${hash.substring(10, 22)}`;
|
||||
};
|
||||
@ -0,0 +1,11 @@
|
||||
import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface';
|
||||
|
||||
export const isGatedAndNotEnabled = (
|
||||
gate: GateDecoratorParams | undefined,
|
||||
workspaceFeatureFlagsMap: Record<string, boolean>,
|
||||
): boolean => {
|
||||
const featureFlagValue =
|
||||
gate?.featureFlag && workspaceFeatureFlagsMap[gate.featureFlag];
|
||||
|
||||
return gate?.featureFlag !== undefined && !featureFlagValue;
|
||||
};
|
||||
@ -0,0 +1,60 @@
|
||||
import { ObjectMetadataEntity } from 'src/engine-metadata/object-metadata/object-metadata.entity';
|
||||
import { FieldMetadataType } from 'src/engine-metadata/field-metadata/field-metadata.entity';
|
||||
|
||||
import { mapObjectMetadataByUniqueIdentifier } from './sync-metadata.util';
|
||||
|
||||
describe('mapObjectMetadataByUniqueIdentifier', () => {
|
||||
it('should convert an array of ObjectMetadataEntity objects into a map', () => {
|
||||
const arr: DeepPartial<ObjectMetadataEntity>[] = [
|
||||
{
|
||||
standardId: 'user',
|
||||
nameSingular: 'user',
|
||||
fields: [
|
||||
{ name: 'id', type: FieldMetadataType.UUID },
|
||||
{ name: 'name', type: FieldMetadataType.TEXT },
|
||||
],
|
||||
},
|
||||
{
|
||||
standardId: 'product',
|
||||
nameSingular: 'product',
|
||||
fields: [
|
||||
{ name: 'id', type: FieldMetadataType.UUID },
|
||||
{ name: 'name', type: FieldMetadataType.TEXT },
|
||||
{ name: 'price', type: FieldMetadataType.UUID },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const mappedObject = mapObjectMetadataByUniqueIdentifier(
|
||||
arr as ObjectMetadataEntity[],
|
||||
);
|
||||
|
||||
expect(mappedObject).toEqual({
|
||||
user: {
|
||||
standardId: 'user',
|
||||
nameSingular: 'user',
|
||||
fields: [
|
||||
{ name: 'id', type: FieldMetadataType.UUID },
|
||||
{ name: 'name', type: FieldMetadataType.TEXT },
|
||||
],
|
||||
},
|
||||
product: {
|
||||
standardId: 'product',
|
||||
nameSingular: 'product',
|
||||
fields: [
|
||||
{ name: 'id', type: FieldMetadataType.UUID },
|
||||
{ name: 'name', type: FieldMetadataType.TEXT },
|
||||
{ name: 'price', type: FieldMetadataType.UUID },
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty map if the input array is empty', () => {
|
||||
const arr: ObjectMetadataEntity[] = [];
|
||||
|
||||
const mappedObject = mapObjectMetadataByUniqueIdentifier(arr);
|
||||
|
||||
expect(mappedObject).toEqual({});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* This utility function converts an array of ObjectMetadataEntity objects into a map,
|
||||
* where the keys are the nameSingular properties of the objects.
|
||||
* Each object in the map contains the original object metadata and its fields as a nested map.
|
||||
*
|
||||
* @param arr - The array of ObjectMetadataEntity objects to convert.
|
||||
* @returns A map of object metadata, with nameSingular as the key and the object as the value.
|
||||
*/
|
||||
export const mapObjectMetadataByUniqueIdentifier = <
|
||||
T extends { standardId: string | null },
|
||||
>(
|
||||
arr: T[],
|
||||
keyFactory: (obj: T) => string | null = (obj) => obj.standardId,
|
||||
): Record<string, T> => {
|
||||
return arr.reduce(
|
||||
(acc, curr) => {
|
||||
const key = keyFactory(curr);
|
||||
|
||||
if (!key) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc[key] = {
|
||||
...curr,
|
||||
};
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, T>,
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user