Feat workspace migration maintains flat object metadata maps (#13620)
# Introduction The workspace migration runner v2 now computes the next flatObjectMetadataMaps post current ws migration action has been run So the following one have an up to date informations ## Still TODO ~~Remove any contextual information from workspace migration v2 and consume the optimistic cache to retrieve them~~ ## Next steps - Create flat-object-metadata-maps testing toolbox and flat-object/field testing toolbox - Implement strong coverage on every created utils/transpiler and applyWorkspaceMigrationAction method
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
import {
|
||||
appendCommonExceptionCode,
|
||||
CustomException,
|
||||
} from 'src/utils/custom-exception';
|
||||
|
||||
export class FlatObjectMetadataMapsException extends CustomException<
|
||||
keyof typeof FlatObjectMetadataMapsExceptionCode
|
||||
> {}
|
||||
|
||||
export const FlatObjectMetadataMapsExceptionCode = appendCommonExceptionCode({
|
||||
FIELD_METADATA_NOT_FOUND: 'FIELD_METADATA_NOT_FOUND',
|
||||
OBJECT_METADATA_NOT_FOUND: 'OBJECT_METADATA_NOT_FOUND',
|
||||
FIELD_METADATA_ALREADY_EXISTS: 'FIELD_METADATA_ALREADY_EXISTS',
|
||||
OBJECT_METADATA_ALREADY_EXISTS: 'OBJECT_METADATA_ALREADY_EXISTS',
|
||||
} as const);
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-to-flat-object-metadata-with-flat-field-maps-or-throw.util';
|
||||
|
||||
export const addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow = ({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatFieldMetadata: FlatFieldMetadata;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FlatObjectMetadataMaps | undefined => {
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
flatObjectMetadataMaps.byId[flatFieldMetadata.objectMetadataId];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow field parent object metadata not found',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatObjectMetadataMaps.byId,
|
||||
[flatFieldMetadata.objectMetadataId]:
|
||||
addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMapsOrThrow({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
}),
|
||||
},
|
||||
idByNameSingular: flatObjectMetadataMaps.idByNameSingular,
|
||||
};
|
||||
};
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import {
|
||||
FlatFieldMetadataMaps,
|
||||
FlatObjectMetadataWithFlatFieldMaps,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-with-flat-field-metadata-maps.type';
|
||||
|
||||
export const addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMapsOrThrow =
|
||||
({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
}: {
|
||||
flatFieldMetadata: FlatFieldMetadata;
|
||||
flatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps;
|
||||
}): FlatObjectMetadataWithFlatFieldMaps => {
|
||||
if (
|
||||
isDefined(
|
||||
flatObjectMetadataWithFlatFieldMaps.fieldsById[flatFieldMetadata.id],
|
||||
)
|
||||
) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMaps added flatFieldMetadata already exists',
|
||||
FlatObjectMetadataMapsExceptionCode.FIELD_METADATA_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
|
||||
let updatedFieldIdByJoinColumnName:
|
||||
| FlatFieldMetadataMaps['fieldIdByJoinColumnName']
|
||||
| undefined = undefined;
|
||||
|
||||
if (
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) ||
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
if (isDefined(flatFieldMetadata.settings?.joinColumnName)) {
|
||||
updatedFieldIdByJoinColumnName = {
|
||||
[flatFieldMetadata.settings.joinColumnName]: flatFieldMetadata.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...flatObjectMetadataWithFlatFieldMaps,
|
||||
fieldIdByJoinColumnName: {
|
||||
...flatObjectMetadataWithFlatFieldMaps.fieldIdByJoinColumnName,
|
||||
...updatedFieldIdByJoinColumnName,
|
||||
},
|
||||
fieldIdByName: {
|
||||
...flatObjectMetadataWithFlatFieldMaps.fieldIdByName,
|
||||
[flatFieldMetadata.name]: flatFieldMetadata.id,
|
||||
},
|
||||
fieldsById: {
|
||||
...flatObjectMetadataWithFlatFieldMaps.fieldsById,
|
||||
[flatFieldMetadata.id]: flatFieldMetadata,
|
||||
},
|
||||
};
|
||||
};
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { fromFlatObjectMetadataToFlatObjectMetadataWithFlatFieldMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-flat-object-metadata-with-flat-field-maps.util';
|
||||
|
||||
type AddFlatObjectMetadataToFlatObjectMetadataMapsOrThrowArgs = {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
export const addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow = ({
|
||||
flatObjectMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
}: AddFlatObjectMetadataToFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => {
|
||||
if (isDefined(flatObjectMetadataMaps.byId[flatObjectMetadata.id])) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow: flat object metadata to add already exists',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatObjectMetadataMaps.byId,
|
||||
[flatObjectMetadata.id]:
|
||||
fromFlatObjectMetadataToFlatObjectMetadataWithFlatFieldMaps(
|
||||
flatObjectMetadata,
|
||||
),
|
||||
},
|
||||
idByNameSingular: {
|
||||
...flatObjectMetadataMaps.idByNameSingular,
|
||||
[flatObjectMetadata.nameSingular]: flatObjectMetadata.id,
|
||||
},
|
||||
};
|
||||
};
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { deleteFieldFromFlatObjectMetadataWithFlatFieldMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-with-flat-field-maps-or-throw.util';
|
||||
|
||||
type DeleteFieldFromFlatObjectMetadataMapsArgs = {
|
||||
fieldMetadataId: string;
|
||||
objectMetadataId: string;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
export const deleteFieldFromFlatObjectMetadataMapsOrThrow = ({
|
||||
flatObjectMetadataMaps,
|
||||
fieldMetadataId,
|
||||
objectMetadataId,
|
||||
}: DeleteFieldFromFlatObjectMetadataMapsArgs): FlatObjectMetadataMaps => {
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'deleteFieldFromFlatObjectMetadataMapsOrThrow: flat field metadata to delete parent flat object metadata not found',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatObjectMetadataMaps.byId,
|
||||
[objectMetadataId]:
|
||||
deleteFieldFromFlatObjectMetadataWithFlatFieldMapsOrThrow({
|
||||
fieldMetadataId,
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
}),
|
||||
},
|
||||
idByNameSingular: flatObjectMetadataMaps.idByNameSingular,
|
||||
};
|
||||
};
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataWithFlatFieldMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-with-flat-field-metadata-maps.type';
|
||||
|
||||
type DeleteFieldFromFlatObjectMetadataMapsArgs = {
|
||||
fieldMetadataId: string;
|
||||
flatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps;
|
||||
};
|
||||
export const deleteFieldFromFlatObjectMetadataWithFlatFieldMapsOrThrow = ({
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
fieldMetadataId: fieldMetadataIdToRemove,
|
||||
}: DeleteFieldFromFlatObjectMetadataMapsArgs): FlatObjectMetadataWithFlatFieldMaps => {
|
||||
const flatFieldMetadataToRemove =
|
||||
flatObjectMetadataWithFlatFieldMaps.fieldsById[fieldMetadataIdToRemove];
|
||||
|
||||
if (!isDefined(flatFieldMetadataToRemove)) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'deleteFieldFromFlatObjectMetadataWithFlatFieldMapsOrThrow: field to delete not found',
|
||||
FlatObjectMetadataMapsExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
fieldIdByName,
|
||||
fieldsById,
|
||||
flatFieldMetadatas,
|
||||
fieldIdByJoinColumnName,
|
||||
} = flatObjectMetadataWithFlatFieldMaps;
|
||||
const updatedFieldIdByJoinColumnName = Object.entries(
|
||||
fieldIdByJoinColumnName,
|
||||
).filter(([_joinColumnName, fieldId]) => fieldId !== fieldMetadataIdToRemove);
|
||||
|
||||
return {
|
||||
...flatObjectMetadataWithFlatFieldMaps,
|
||||
fieldIdByJoinColumnName: Object.fromEntries(updatedFieldIdByJoinColumnName),
|
||||
fieldIdByName: removePropertiesFromRecord(fieldIdByName, [
|
||||
flatFieldMetadataToRemove.name,
|
||||
]),
|
||||
fieldsById: removePropertiesFromRecord(fieldsById, [
|
||||
fieldMetadataIdToRemove,
|
||||
]),
|
||||
flatFieldMetadatas: flatFieldMetadatas.filter(
|
||||
(flatFieldMetadata) => flatFieldMetadata.id !== fieldMetadataIdToRemove,
|
||||
),
|
||||
};
|
||||
};
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
|
||||
type DeleteObjectFromFlatObjectMetadataMapsOrThrowArgs = {
|
||||
objectMetadataId: string;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
export const deleteObjectFromFlatObjectMetadataMapsOrThrow = ({
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataId,
|
||||
}: DeleteObjectFromFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => {
|
||||
if (!isDefined(flatObjectMetadataMaps.byId[objectMetadataId])) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'deleteObjectFromFlatObjectMetadataMapsOrThrow: object to delete not found',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedIdByNameSingularEntries = Object.entries(
|
||||
flatObjectMetadataMaps.idByNameSingular,
|
||||
).filter(([_nameSingular, id]) => id !== objectMetadataId);
|
||||
|
||||
return {
|
||||
byId: removePropertiesFromRecord(flatObjectMetadataMaps.byId, [
|
||||
objectMetadataId,
|
||||
]),
|
||||
idByNameSingular: Object.fromEntries(updatedIdByNameSingularEntries),
|
||||
};
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
|
||||
export const findFlatFieldMetadataInFlatObjectMetadataMaps = ({
|
||||
flatObjectMetadataMaps,
|
||||
fieldMetadataId,
|
||||
objectMetadataId,
|
||||
}: {
|
||||
objectMetadataId: string;
|
||||
fieldMetadataId: string;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FlatFieldMetadata | undefined => {
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const flatFieldMetadata =
|
||||
flatObjectMetadataWithFlatFieldMaps.fieldsById[fieldMetadataId];
|
||||
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return flatFieldMetadata;
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util';
|
||||
|
||||
export const findFlatObjectdMetadataInFlatObjectMetadataMaps = ({
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataId,
|
||||
}: {
|
||||
objectMetadataId: string;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FlatObjectMetadata | undefined => {
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata(
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
);
|
||||
};
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
import { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util';
|
||||
|
||||
export const replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow = ({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatFieldMetadata: FlatFieldMetadata;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FlatObjectMetadataMaps | undefined => {
|
||||
const flatObjectMetadataMapsWithoutFlatFieldMetadataToReplace =
|
||||
deleteFieldFromFlatObjectMetadataMapsOrThrow({
|
||||
fieldMetadataId: flatFieldMetadata.id,
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataId: flatFieldMetadata.objectMetadataId,
|
||||
});
|
||||
|
||||
return addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps:
|
||||
flatObjectMetadataMapsWithoutFlatFieldMetadataToReplace,
|
||||
});
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util';
|
||||
import { deleteObjectFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-object-from-flat-object-metadata-maps-or-throw.util';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export const replaceFlatObjectMetadataInFlatObjectMetadataMaps = ({
|
||||
flatObjectMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}) => {
|
||||
const flatObjectMetadataMapsWithoutFlatObjectMetadataToReplace =
|
||||
deleteObjectFromFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataId: flatObjectMetadata.id,
|
||||
});
|
||||
|
||||
return addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadata,
|
||||
flatObjectMetadataMaps:
|
||||
flatObjectMetadataMapsWithoutFlatObjectMetadataToReplace,
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user