Migrate Views-xxx Index Field Object Skill to be fully universal ( all actions and metadata runner and builder ) + all metadata update actions runner (#17687)
# What this PR does Overall naming `universal` versus `flat` is not always the most updated and so on Will make a big cleaning tour after I've finished the whole migration Migrating all `view` and ( filter fields etc ) `field` `object` `index` to the universal pattern on all `services`, `builder` and `runner` levels ## Universal and flat optimistic tooling `addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow` and its delete counterpart maintain the consistency of `UniversalFlatEntityMaps` when an entity is created or removed. Beyond inserting/removing the entity from its own maps, they walk through `ALL_UNIVERSAL_METADATA_RELATIONS` to update the **aggregator arrays** on related parent entities — the add appends the new entity's `universalIdentifier` to the parent's aggregator (e.g. a new viewField's identifier gets appended to its parent view's `viewFieldUniversalIdentifiers`), and the delete filters it out. This keeps the maps in sync so that diff computations and relation lookups remain accurate throughout the migration building process. ## ALL_UNIVERSAL_METADATA_RELATIONS `ALL_UNIVERSAL_METADATA_RELATIONS` is the universal counterpart of `ALL_METADATA_RELATIONS`. It maps each metadata entity to its many-to-one and one-to-many relations using universal foreign keys (`*UniversalIdentifier`) instead of database IDs (`*Id`). This allows migration actions to reference related entities in a workspace-agnostic way. Relations that are workspace-specific (e.g. `workspace`, `dataSource`, `userWorkspace`) are set to `null` and skipped during resolution. ## `workspaceMigrationCreateIdEnrichment` Reserved to API metadata ( will be able to validate at app installation lvl ) - Workspace migration `create` actions now carry an optional `id` (and `fieldIdByUniversalIdentifier` for object/field actions) so that caller-provided IDs flow through the entire build-validate-run pipeline. - New `enrichCreateWorkspaceMigrationActionsWithIds` utility resolves `universalIdentifier → id` mappings after the builder runs and injects them into the migration actions before the runner persists entities. - Runner action handlers use the provided IDs instead of generating new UUIDs, enabling deterministic entity creation for synchronization workflows. ## `resolveUniversalUpdateRelationIdentifiersToIds` `resolveUniversalUpdateRelationIdentifiersToIds` converts universal identifiers (workspace-agnostic, stable keys) in a migration update payload into concrete database UUIDs, so the update can be applied to a specific workspace. It iterates over the many-to-one relations defined in `ALL_UNIVERSAL_METADATA_RELATIONS` for the given entity type, replaces each `*UniversalIdentifier` property with its corresponding `*Id` by looking up the target entity in `allFlatEntityMaps`, and throws if a non-null identifier can't be resolved. Used by all `update` action handlers in `transpileUniversalActionToFlatAction`, avoiding duplicated resolution logic across handlers. ## What this PR does not - Migrating twenty-standard declaration to universal - Migrating all the inputs transpilers to universal - Migrating all metadata to be fully universal ( we still need to de-scope the type of all of them and refactor their validator very close ) --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
-13
@@ -1,13 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 1`] = `
|
||||
{
|
||||
"isActive": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 2`] = `
|
||||
{
|
||||
"isActive": true,
|
||||
}
|
||||
`;
|
||||
+19
-11
@@ -4,7 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -12,14 +12,18 @@ import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow', () => {
|
||||
it('should add a view and update related objectMetadata with viewId', () => {
|
||||
it('should add a view and update related objectMetadata and fieldMetadata with both id and universal identifier aggregators', () => {
|
||||
const objectMetadataId = 'object-1';
|
||||
const viewId = 'view-1';
|
||||
const applicationId = '20202020-f3ad-452e-b5b6-2d49d3ea88b1';
|
||||
const workspaceId = '20202020-bc64-4148-8a79-b3144f743694';
|
||||
const objectUniversalIdentifier = 'object-universal-1';
|
||||
const fieldUniversalIdentifier = 'field-universal-1';
|
||||
const viewUniversalIdentifier = 'view-universal-1';
|
||||
|
||||
const mockObjectMetadata = getFlatObjectMetadataMock({
|
||||
id: objectMetadataId,
|
||||
universalIdentifier: 'object-universal-1',
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
viewIds: [],
|
||||
fieldIds: [],
|
||||
workspaceId,
|
||||
@@ -34,7 +38,7 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
type: FieldMetadataType.DATE,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
universalIdentifier: 'field-universal-1',
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
calendarViewIds: [],
|
||||
@@ -44,13 +48,15 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
const mockView: Pick<FlatView, 'id'> & Partial<FlatView> = {
|
||||
id: viewId,
|
||||
workspaceId,
|
||||
universalIdentifier: 'view-universal-1',
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
objectMetadataId: objectMetadataId,
|
||||
objectMetadataUniversalIdentifier: objectUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
applicationId,
|
||||
calendarFieldMetadataId: mockFieldMetadata.id,
|
||||
calendarFieldMetadataUniversalIdentifier: fieldUniversalIdentifier,
|
||||
};
|
||||
|
||||
const flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<'view'> =
|
||||
@@ -73,28 +79,30 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockView.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toMatchObject(mockView);
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: [mockView.id],
|
||||
viewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [mockView.id],
|
||||
calendarViewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
|
||||
type TestContext<T extends AllMetadataName = AllMetadataName> = FromTo<
|
||||
MetadataFlatEntity<T>,
|
||||
'flatEntity'
|
||||
> & { metadataName: T };
|
||||
|
||||
describe('compareTwoFlatEntity', () => {
|
||||
const testCases = [
|
||||
{
|
||||
title:
|
||||
'It should detect flat field metadata isActive diff from true to false',
|
||||
context: {
|
||||
fromFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: true,
|
||||
}),
|
||||
metadataName: 'fieldMetadata',
|
||||
toFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'It should detect flat field metadata isActive diff from true to false',
|
||||
context: {
|
||||
fromFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: false,
|
||||
}),
|
||||
metadataName: 'fieldMetadata',
|
||||
toFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: true,
|
||||
}),
|
||||
},
|
||||
},
|
||||
] as const satisfies EachTestingContext<TestContext>[];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { metadataName, fromFlatEntity, toFlatEntity } }) => {
|
||||
const result = compareTwoFlatEntity({
|
||||
fromFlatEntity,
|
||||
propertiesToCompare:
|
||||
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName]
|
||||
.propertiesToCompare as any,
|
||||
propertiesToStringify:
|
||||
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName]
|
||||
.propertiesToStringify as any,
|
||||
toFlatEntity,
|
||||
});
|
||||
|
||||
expect(result).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny({ ...result }),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
+20
-11
@@ -4,7 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -12,16 +12,20 @@ import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow', () => {
|
||||
it('should delete a view and update related objectMetadata and fieldMetadata by removing viewId', () => {
|
||||
it('should delete a view and update related objectMetadata and fieldMetadata by removing both id and universal identifier aggregators', () => {
|
||||
const objectMetadataId = 'object-1';
|
||||
const viewId = 'view-1';
|
||||
const applicationId = '20202020-f3ad-452e-b5b6-2d49d3ea88b1';
|
||||
const workspaceId = '20202020-bc64-4148-8a79-b3144f743694';
|
||||
const objectUniversalIdentifier = 'object-universal-1';
|
||||
const fieldUniversalIdentifier = 'field-universal-1';
|
||||
const viewUniversalIdentifier = 'view-universal-1';
|
||||
|
||||
const mockObjectMetadata = getFlatObjectMetadataMock({
|
||||
id: objectMetadataId,
|
||||
universalIdentifier: 'object-universal-1',
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
viewIds: [viewId, 'something-else'],
|
||||
viewUniversalIdentifiers: [viewUniversalIdentifier, 'something-else-ui'],
|
||||
fieldIds: [],
|
||||
workspaceId,
|
||||
imageIdentifierFieldMetadataId: '20202020-9d65-415f-b0e1-216a2e257ea4',
|
||||
@@ -33,24 +37,27 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
|
||||
objectMetadataId,
|
||||
id: '20202020-4087-423b-852a-91f91acf2df2',
|
||||
type: FieldMetadataType.DATE,
|
||||
universalIdentifier: 'field-universal-1',
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
workspaceId,
|
||||
calendarViewIds: [viewId],
|
||||
calendarViewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
mainGroupByFieldMetadataViewIds: [],
|
||||
applicationId,
|
||||
});
|
||||
|
||||
const mockView: Partial<FlatView> = {
|
||||
id: viewId,
|
||||
universalIdentifier: 'view-universal-1',
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
objectMetadataId: objectMetadataId,
|
||||
objectMetadataUniversalIdentifier: objectUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
workspaceId,
|
||||
calendarFieldMetadataId: mockFieldMetadata.id,
|
||||
calendarFieldMetadataUniversalIdentifier: fieldUniversalIdentifier,
|
||||
createdAt: new Date('2024-01-01').toISOString(),
|
||||
updatedAt: new Date('2024-01-01').toISOString(),
|
||||
icon: 'icon',
|
||||
@@ -83,28 +90,30 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: ['something-else'],
|
||||
viewUniversalIdentifiers: ['something-else-ui'],
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+21
-11
@@ -12,7 +12,7 @@ import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modu
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
type AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
@@ -22,21 +22,30 @@ type AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
<T extends AllMetadataName>({
|
||||
metadataName,
|
||||
flatEntity,
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
}: AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow(
|
||||
{
|
||||
metadataName,
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
const selfFlatEntityMaps =
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey];
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey],
|
||||
});
|
||||
selfFlatEntityMaps.universalIdentifierById[flatEntity.id] =
|
||||
flatEntity.universalIdentifier;
|
||||
|
||||
const manyToOneRelations = Object.values(
|
||||
const idBasedManyToOneRelations = Object.values(
|
||||
ALL_METADATA_RELATIONS[metadataName].manyToOne,
|
||||
) as Array<{
|
||||
metadataName: AllMetadataName;
|
||||
@@ -44,8 +53,8 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
foreignKey: keyof MetadataFlatEntity<T>;
|
||||
} | null>;
|
||||
|
||||
for (const relation of manyToOneRelations) {
|
||||
if (!isDefined(relation)) {
|
||||
for (const idBasedRelation of idBasedManyToOneRelations) {
|
||||
if (!isDefined(idBasedRelation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -53,7 +62,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
metadataName: relatedMetadataName,
|
||||
flatEntityForeignKeyAggregator,
|
||||
foreignKey,
|
||||
} = relation;
|
||||
} = idBasedRelation;
|
||||
|
||||
if (!isDefined(flatEntityForeignKeyAggregator)) {
|
||||
continue;
|
||||
@@ -61,6 +70,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
|
||||
const relatedFlatEntityMapsKey =
|
||||
getMetadataFlatEntityMapsKey(relatedMetadataName);
|
||||
|
||||
const relatedFlatEntityMetadataMaps = flatEntityAndRelatedMapsToMutate[
|
||||
relatedFlatEntityMapsKey as MetadataRelatedFlatEntityMapsKeys<T>
|
||||
] as FlatEntityMaps<MetadataFlatEntity<typeof relatedMetadataName>>;
|
||||
@@ -85,7 +95,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Should never occur, invalid flat entity typing. flat ${metadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
`Should never occur, invalid flat entity typing. flat ${relatedMetadataName} should contain ${String(flatEntityForeignKeyAggregator)}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
);
|
||||
}
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
import diff from 'microdiff';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { parseJson } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { transformFlatEntityForComparison } from 'src/engine/metadata-modules/flat-entity/utils/transform-flat-entity-for-comparison.util';
|
||||
|
||||
export const compareTwoFlatEntity = <
|
||||
T extends AllMetadataName,
|
||||
PToCompare extends Extract<
|
||||
FlatEntityPropertiesToCompare<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>,
|
||||
PJsonB extends PToCompare = PToCompare,
|
||||
>({
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}: FromTo<MetadataFlatEntity<T>, 'flatEntity'> & {
|
||||
propertiesToCompare: readonly PToCompare[];
|
||||
propertiesToStringify: readonly PJsonB[];
|
||||
}): FlatEntityUpdate<T> | undefined => {
|
||||
const [transformedFromFlatEntity, transformedToFlatEntity] = [
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
].map((flatEntity) =>
|
||||
transformFlatEntityForComparison({
|
||||
flatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}),
|
||||
);
|
||||
|
||||
const flatEntityDifferences = diff(
|
||||
transformedFromFlatEntity,
|
||||
transformedToFlatEntity,
|
||||
);
|
||||
|
||||
if (flatEntityDifferences.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const initialAccumulator: FlatEntityUpdate<T> = {};
|
||||
|
||||
return flatEntityDifferences.reduce((accumulator, difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { path, value } = difference;
|
||||
const property = path[0] as PToCompare;
|
||||
const isJsonb = propertiesToStringify.includes(
|
||||
property as unknown as PJsonB,
|
||||
);
|
||||
|
||||
if (isJsonb) {
|
||||
return {
|
||||
...accumulator,
|
||||
[property]: parseJson(value),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...accumulator,
|
||||
[property]: value,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occur, we should only provide null never undefined and so on
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
}, initialAccumulator);
|
||||
};
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityToCreateDeleteUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-to-create-delete-update.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityByIdsMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-by-ids-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
|
||||
export type ComputeFlatEntityMapsFromToArgs<T extends AllMetadataName> = {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
} & FlatEntityToCreateDeleteUpdate<T>;
|
||||
export const computeFlatEntityMapsFromTo = <T extends AllMetadataName>({
|
||||
flatEntityMaps,
|
||||
flatEntityToCreate,
|
||||
flatEntityToDelete,
|
||||
flatEntityToUpdate,
|
||||
}: ComputeFlatEntityMapsFromToArgs<T>): {
|
||||
from: MetadataFlatEntityMaps<T>;
|
||||
to: MetadataFlatEntityMaps<T>;
|
||||
} => {
|
||||
const fromFlatEntityMaps =
|
||||
flatEntityToDelete.length > 0
|
||||
? getSubFlatEntityByIdsMapsOrThrow({
|
||||
flatEntityIds: [...flatEntityToDelete, ...flatEntityToUpdate].map(
|
||||
({ id }) => id,
|
||||
),
|
||||
flatEntityMaps,
|
||||
})
|
||||
: flatEntityMaps;
|
||||
|
||||
const toFlatEntityMapsWithDeleted = flatEntityToDelete.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
entityToDeleteId: flatEntity.id,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
fromFlatEntityMaps,
|
||||
);
|
||||
|
||||
const toFlatEntityMapsWithUpdated = flatEntityToUpdate.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
toFlatEntityMapsWithDeleted,
|
||||
);
|
||||
|
||||
const toFlatEntityMaps = flatEntityToCreate.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
toFlatEntityMapsWithUpdated,
|
||||
);
|
||||
|
||||
return {
|
||||
from: fromFlatEntityMaps,
|
||||
to: toFlatEntityMaps,
|
||||
};
|
||||
};
|
||||
+15
-15
@@ -12,7 +12,7 @@ import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modu
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { deleteUniversalFlatEntityFromUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
type DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
@@ -22,23 +22,23 @@ type DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArg
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
<T extends AllMetadataName>({
|
||||
metadataName,
|
||||
flatEntity,
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
}: DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
deleteUniversalFlatEntityFromUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow(
|
||||
{
|
||||
metadataName,
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
},
|
||||
);
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow<
|
||||
MetadataFlatEntity<T>
|
||||
>({
|
||||
entityToDeleteId: flatEntity.id,
|
||||
flatEntityMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey],
|
||||
});
|
||||
|
||||
const manyToOneRelations = Object.values(
|
||||
const idBasedManyToOneRelations = Object.values(
|
||||
ALL_METADATA_RELATIONS[metadataName].manyToOne,
|
||||
) as Array<{
|
||||
metadataName: AllMetadataName;
|
||||
@@ -46,8 +46,8 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
foreignKey: keyof MetadataFlatEntity<T>;
|
||||
} | null>;
|
||||
|
||||
for (const relation of manyToOneRelations) {
|
||||
if (!isDefined(relation)) {
|
||||
for (const idBasedRelation of idBasedManyToOneRelations) {
|
||||
if (!isDefined(idBasedRelation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
metadataName: relatedMetadataName,
|
||||
flatEntityForeignKeyAggregator,
|
||||
foreignKey,
|
||||
} = relation;
|
||||
} = idBasedRelation;
|
||||
|
||||
if (!isDefined(flatEntityForeignKeyAggregator)) {
|
||||
continue;
|
||||
@@ -92,7 +92,7 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Should never occur, invalid flat entity typing. flat ${metadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
`Should never occur, invalid flat entity typing. flat ${relatedMetadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ import {
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
@@ -15,7 +15,7 @@ export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T => {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifier({
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifier = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
@@ -8,7 +8,7 @@ export const findFlatEntityByUniversalIdentifier = <
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T | undefined => {
|
||||
return flatEntityMaps.byUniversalIdentifier[universalIdentifier];
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export type FindManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrowArgs<
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
> = {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifiers: string[];
|
||||
};
|
||||
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { ALL_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
|
||||
|
||||
export const getMetadataSerializedRelationNames = (
|
||||
metadataName: AllMetadataName,
|
||||
): AllMetadataName[] => {
|
||||
const relations = ALL_METADATA_RELATIONS[metadataName];
|
||||
|
||||
if (!('serializedRelations' in relations)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.keys(relations.serializedRelations) as AllMetadataName[];
|
||||
};
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
export const getSubUniversalFlatEntityByUniversalIdentifiersMapsOrThrow = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
>({
|
||||
universalIdentifiers,
|
||||
universalFlatEntityMaps,
|
||||
}: {
|
||||
universalFlatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifiers: string[];
|
||||
}): UniversalFlatEntityMaps<T> => {
|
||||
const subUniversalFlatEntityMaps: UniversalFlatEntityMaps<T> = {
|
||||
byUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
for (const universalIdentifier of universalIdentifiers) {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: universalFlatEntityMaps,
|
||||
universalIdentifier,
|
||||
});
|
||||
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityMapsToMutate: subUniversalFlatEntityMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return subUniversalFlatEntityMaps;
|
||||
};
|
||||
+4
-2
@@ -4,7 +4,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
ALL_METADATA_RELATIONS,
|
||||
type ManyToOneRelationValue,
|
||||
type MetadataManyToOneRelationConfiguration,
|
||||
} from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
@@ -76,7 +76,9 @@ export const resolveEntityRelationUniversalIdentifiers = <
|
||||
const relations = ALL_METADATA_RELATIONS[metadataName].manyToOne;
|
||||
const result: Record<string, string | null> = {};
|
||||
|
||||
for (const relation of Object.values(relations) as ManyToOneRelationValue<
|
||||
for (const relation of Object.values(
|
||||
relations,
|
||||
) as MetadataManyToOneRelationConfiguration<
|
||||
T,
|
||||
ExtractEntityManyToOneEntityRelationProperties<MetadataEntity<T>>
|
||||
>[]) {
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveUniversalIdentifierFromFlatEntityIdOrThrow = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string;
|
||||
metadataName: T;
|
||||
}): string => {
|
||||
const flatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
});
|
||||
|
||||
if (!isDefined(flatEntity)) {
|
||||
throw new FlatEntityMapsException(
|
||||
t`Could not find ${metadataName}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return flatEntity.universalIdentifier;
|
||||
};
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveNullableUniversalIdentifierFromFlatEntityId = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string | null | undefined;
|
||||
metadataName: T;
|
||||
}): string | null => {
|
||||
if (!isDefined(flatEntityId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveUniversalIdentifierFromFlatEntityIdOrThrow({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
});
|
||||
};
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { orderObjectProperties } from 'src/engine/metadata-modules/flat-entity/utils/order-object-properties.util';
|
||||
|
||||
export function transformFlatEntityForComparison<
|
||||
TFlatEntity extends SyncableFlatEntity,
|
||||
PToCompare extends keyof TFlatEntity,
|
||||
PJsonB extends PToCompare,
|
||||
>({
|
||||
flatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}: {
|
||||
flatEntity: TFlatEntity;
|
||||
propertiesToCompare: readonly PToCompare[];
|
||||
propertiesToStringify: readonly PJsonB[];
|
||||
}): Pick<TFlatEntity, PToCompare> {
|
||||
return propertiesToCompare.reduce(
|
||||
(flatEntityAccumulator, propertyToCompare) => {
|
||||
const currentValue = flatEntity[propertyToCompare];
|
||||
|
||||
if (propertiesToStringify.includes(propertyToCompare as PJsonB)) {
|
||||
const orderedValue = orderObjectProperties(currentValue);
|
||||
|
||||
return {
|
||||
...flatEntityAccumulator,
|
||||
[propertyToCompare]: JSON.stringify(orderedValue),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...flatEntityAccumulator,
|
||||
[propertyToCompare]: currentValue,
|
||||
};
|
||||
},
|
||||
{} as Pick<TFlatEntity, PToCompare>,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user