Factorize from entity to flat entity utils (#21972)
## What Factorizes the two responsibilities that were copy‑pasted across every `from-<entity>-entity-to-flat-<entity>` util into two reusable tools. ### `fromEntityToScalarEntity` Projects a TypeORM entity into its scalar flat shape using an **allow‑list** driven by `ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME` (plus the base columns `id`/`workspaceId`/`applicationId`/`universalIdentifier`). Only registered scalar columns are forwarded, `Date`s are serialized to ISO strings, and absent values are normalized to `null`. Replaces the previous deny‑list (`removePropertiesFromRecord`) approach, so unregistered/deprecated columns can no longer silently leak into the flat entity. ### `resolveManyToOneRelationIdsToUniversalIdentifiers` Resolves an entity's many‑to‑one foreign keys to their universal identifiers, driven by `ALL_MANY_TO_ONE_METADATA_RELATIONS`. Handles the always‑present `application`, nullable relations, and throws a `FlatEntityMapsException` when a referenced id is missing from its identifier map. Mirrors `resolveUniversalRelationIdentifiersToIds` in the opposite direction. Each `from-<entity>` util now reduces to: scalar spread + relation spread (+ explicit one‑to‑many id/universalIdentifier arrays where applicable). ### Note The allow‑list drops `isUIReadOnly` (a `WasRemovedInUpgrade` column not in the config) from `fieldMetadata`, which is the only integration‑snapshot change. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21972?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+18
-31
@@ -1,39 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatApplicationVariable } from 'src/engine/metadata-modules/flat-application-variable/types/flat-application-variable.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromApplicationVariableEntityToFlatApplicationVariable = ({
|
||||
entity: applicationVariableEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'applicationVariable'>): FlatApplicationVariable => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
applicationVariableEntity.applicationId,
|
||||
);
|
||||
export const fromApplicationVariableEntityToFlatApplicationVariable = (
|
||||
args: FromEntityToFlatEntityArgs<'applicationVariable'>,
|
||||
): FlatApplicationVariable => {
|
||||
const { entity: applicationVariableEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${applicationVariableEntity.applicationId} not found for applicationVariable ${applicationVariableEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const applicationVariableScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'applicationVariable',
|
||||
entity: applicationVariableEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'applicationVariable',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: applicationVariableEntity.id,
|
||||
key: applicationVariableEntity.key,
|
||||
value: applicationVariableEntity.value,
|
||||
description: applicationVariableEntity.description,
|
||||
isSecret: applicationVariableEntity.isSecret,
|
||||
workspaceId: applicationVariableEntity.workspaceId,
|
||||
universalIdentifier: applicationVariableEntity.universalIdentifier,
|
||||
applicationId: applicationVariableEntity.applicationId,
|
||||
createdAt: applicationVariableEntity.createdAt.toISOString(),
|
||||
updatedAt: applicationVariableEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
...applicationVariableScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+22
-98
@@ -1,79 +1,30 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { fromCommandMenuItemOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-command-menu-item/utils/from-command-menu-item-overrides-to-universal-overrides.util';
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromCommandMenuItemOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-command-menu-item/utils/from-command-menu-item-overrides-to-universal-overrides.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
entity: commandMenuItemEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
frontComponentIdToUniversalIdentifierMap,
|
||||
pageLayoutIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'commandMenuItem'>): FlatCommandMenuItem => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
commandMenuItemEntity.applicationId,
|
||||
);
|
||||
export const fromCommandMenuItemEntityToFlatCommandMenuItem = (
|
||||
args: FromEntityToFlatEntityArgs<'commandMenuItem'>,
|
||||
): FlatCommandMenuItem => {
|
||||
const {
|
||||
entity: commandMenuItemEntity,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
pageLayoutIdToUniversalIdentifierMap,
|
||||
} = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${commandMenuItemEntity.applicationId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const commandMenuItemScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'commandMenuItem',
|
||||
entity: commandMenuItemEntity,
|
||||
});
|
||||
|
||||
let availabilityObjectMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(commandMenuItemEntity.availabilityObjectMetadataId)) {
|
||||
availabilityObjectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
commandMenuItemEntity.availabilityObjectMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(availabilityObjectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${commandMenuItemEntity.availabilityObjectMetadataId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let frontComponentUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(commandMenuItemEntity.frontComponentId)) {
|
||||
frontComponentUniversalIdentifier =
|
||||
frontComponentIdToUniversalIdentifierMap.get(
|
||||
commandMenuItemEntity.frontComponentId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(frontComponentUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FrontComponent with id ${commandMenuItemEntity.frontComponentId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let pageLayoutUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(commandMenuItemEntity.pageLayoutId)) {
|
||||
pageLayoutUniversalIdentifier =
|
||||
pageLayoutIdToUniversalIdentifierMap.get(
|
||||
commandMenuItemEntity.pageLayoutId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(pageLayoutUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`PageLayout with id ${commandMenuItemEntity.pageLayoutId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'commandMenuItem',
|
||||
...args,
|
||||
});
|
||||
|
||||
const universalOverrides = isDefined(commandMenuItemEntity.overrides)
|
||||
? fromCommandMenuItemOverridesToUniversalOverrides({
|
||||
@@ -89,35 +40,8 @@ export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
: null;
|
||||
|
||||
return {
|
||||
id: commandMenuItemEntity.id,
|
||||
workflowVersionId: commandMenuItemEntity.workflowVersionId,
|
||||
frontComponentId: commandMenuItemEntity.frontComponentId,
|
||||
engineComponentKey: commandMenuItemEntity.engineComponentKey,
|
||||
label: commandMenuItemEntity.label,
|
||||
icon: commandMenuItemEntity.icon,
|
||||
shortLabel: commandMenuItemEntity.shortLabel,
|
||||
position: commandMenuItemEntity.position,
|
||||
isPinned: commandMenuItemEntity.isPinned,
|
||||
payload: commandMenuItemEntity.payload,
|
||||
hotKeys: commandMenuItemEntity.hotKeys,
|
||||
availabilityType: commandMenuItemEntity.availabilityType,
|
||||
availabilityObjectMetadataId:
|
||||
commandMenuItemEntity.availabilityObjectMetadataId,
|
||||
workspaceId: commandMenuItemEntity.workspaceId,
|
||||
universalIdentifier: commandMenuItemEntity.universalIdentifier,
|
||||
applicationId: commandMenuItemEntity.applicationId,
|
||||
createdAt: commandMenuItemEntity.createdAt.toISOString(),
|
||||
updatedAt: commandMenuItemEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
conditionalAvailabilityExpression:
|
||||
commandMenuItemEntity.conditionalAvailabilityExpression,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
pageLayoutId: commandMenuItemEntity.pageLayoutId,
|
||||
pageLayoutUniversalIdentifier,
|
||||
isActive: commandMenuItemEntity.isActive,
|
||||
isSystemSideEffect: commandMenuItemEntity.isSystemSideEffect,
|
||||
overrides: commandMenuItemEntity.overrides,
|
||||
...commandMenuItemScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
universalOverrides,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-31
@@ -1,39 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatConnectionProvider } from 'src/engine/metadata-modules/flat-connection-provider/types/flat-connection-provider.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromConnectionProviderEntityToFlatConnectionProvider = ({
|
||||
entity: connectionProviderEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'connectionProvider'>): FlatConnectionProvider => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
connectionProviderEntity.applicationId,
|
||||
);
|
||||
export const fromConnectionProviderEntityToFlatConnectionProvider = (
|
||||
args: FromEntityToFlatEntityArgs<'connectionProvider'>,
|
||||
): FlatConnectionProvider => {
|
||||
const { entity: connectionProviderEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${connectionProviderEntity.applicationId} not found for connection provider ${connectionProviderEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const connectionProviderScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'connectionProvider',
|
||||
entity: connectionProviderEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'connectionProvider',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: connectionProviderEntity.id,
|
||||
universalIdentifier: connectionProviderEntity.universalIdentifier,
|
||||
applicationId: connectionProviderEntity.applicationId,
|
||||
workspaceId: connectionProviderEntity.workspaceId,
|
||||
name: connectionProviderEntity.name,
|
||||
displayName: connectionProviderEntity.displayName,
|
||||
type: connectionProviderEntity.type,
|
||||
oauthConfig: connectionProviderEntity.oauthConfig,
|
||||
createdAt: connectionProviderEntity.createdAt.toISOString(),
|
||||
updatedAt: connectionProviderEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
...connectionProviderScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type EntityWithRegroupedOneToManyRelations } from 'src/engine/workspace-cache/types/entity-with-regrouped-one-to-many-relations.type';
|
||||
|
||||
const buildArgs = <T extends AllMetadataName>(
|
||||
metadataName: T,
|
||||
entity: Record<string, unknown>,
|
||||
): {
|
||||
metadataName: T;
|
||||
entity: EntityWithRegroupedOneToManyRelations<MetadataEntity<T>>;
|
||||
} => ({
|
||||
metadataName,
|
||||
entity: entity as unknown as EntityWithRegroupedOneToManyRelations<
|
||||
MetadataEntity<T>
|
||||
>,
|
||||
});
|
||||
|
||||
describe('fromEntityToScalarEntity', () => {
|
||||
it('should return the registered scalar properties along with the base columns', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('permissionFlag', {
|
||||
id: 'permission-flag-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
universalIdentifier: 'permission-flag-ui-1',
|
||||
key: 'IMPERSONATE',
|
||||
label: 'Impersonate',
|
||||
description: 'Allows impersonation',
|
||||
icon: 'IconUser',
|
||||
permissionType: 'WORKSPACE',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
id: 'permission-flag-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
universalIdentifier: 'permission-flag-ui-1',
|
||||
key: 'IMPERSONATE',
|
||||
label: 'Impersonate',
|
||||
description: 'Allows impersonation',
|
||||
icon: 'IconUser',
|
||||
permissionType: 'WORKSPACE',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-02T00:00:00.000Z',
|
||||
});
|
||||
});
|
||||
|
||||
it('should drop relation objects, regrouped one-to-many arrays and any unregistered property', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('permissionFlag', {
|
||||
id: 'permission-flag-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
universalIdentifier: 'permission-flag-ui-1',
|
||||
key: 'IMPERSONATE',
|
||||
label: 'Impersonate',
|
||||
description: 'Allows impersonation',
|
||||
icon: 'IconUser',
|
||||
permissionType: 'WORKSPACE',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
workspace: { id: 'workspace-id-1' },
|
||||
application: { id: 'app-id-1' },
|
||||
rolePermissionFlags: [{ id: 'role-permission-flag-id-1' }],
|
||||
someTransientProperty: 'should-not-leak',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(Object.keys(result).sort()).toEqual(
|
||||
[
|
||||
'id',
|
||||
'workspaceId',
|
||||
'applicationId',
|
||||
'universalIdentifier',
|
||||
'key',
|
||||
'label',
|
||||
'description',
|
||||
'icon',
|
||||
'permissionType',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
].sort(),
|
||||
);
|
||||
expect(result).not.toHaveProperty('workspace');
|
||||
expect(result).not.toHaveProperty('application');
|
||||
expect(result).not.toHaveProperty('rolePermissionFlags');
|
||||
expect(result).not.toHaveProperty('someTransientProperty');
|
||||
});
|
||||
|
||||
it('should keep many-to-one foreign key columns while dropping their relation objects', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('viewSort', {
|
||||
id: 'view-sort-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
universalIdentifier: 'view-sort-ui-1',
|
||||
direction: 'ASC',
|
||||
subFieldName: null,
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
deletedAt: null,
|
||||
fieldMetadata: { id: 'field-id-1' },
|
||||
view: { id: 'view-id-1' },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.fieldMetadataId).toBe('field-id-1');
|
||||
expect(result.viewId).toBe('view-id-1');
|
||||
expect(result).not.toHaveProperty('fieldMetadata');
|
||||
expect(result).not.toHaveProperty('view');
|
||||
});
|
||||
|
||||
it('should serialize Date columns to ISO strings while leaving null dates untouched', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('viewSort', {
|
||||
id: 'view-sort-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
universalIdentifier: 'view-sort-ui-1',
|
||||
direction: 'ASC',
|
||||
subFieldName: null,
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
deletedAt: null,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.createdAt).toBe('2024-01-01T00:00:00.000Z');
|
||||
expect(result.updatedAt).toBe('2024-01-02T00:00:00.000Z');
|
||||
expect(result.deletedAt).toBeNull();
|
||||
});
|
||||
|
||||
it('should normalize absent properties to null instead of undefined', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('permissionFlag', {
|
||||
id: 'permission-flag-id-1',
|
||||
key: 'IMPERSONATE',
|
||||
label: 'Impersonate',
|
||||
description: 'Allows impersonation',
|
||||
icon: 'IconUser',
|
||||
permissionType: 'WORKSPACE',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toHaveProperty('workspaceId', null);
|
||||
expect(result).toHaveProperty('applicationId', null);
|
||||
expect(result).toHaveProperty('universalIdentifier', null);
|
||||
expect(Object.values(result)).not.toContain(undefined);
|
||||
});
|
||||
|
||||
it('should keep explicit null values and normalize undefined ones to null', () => {
|
||||
const result = fromEntityToScalarEntity(
|
||||
buildArgs('viewSort', {
|
||||
id: 'view-sort-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: null,
|
||||
universalIdentifier: 'view-sort-ui-1',
|
||||
direction: 'ASC',
|
||||
subFieldName: null,
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
deletedAt: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toHaveProperty('applicationId', null);
|
||||
expect(result).toHaveProperty('subFieldName', null);
|
||||
expect(result).toHaveProperty('deletedAt', null);
|
||||
});
|
||||
});
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME } from 'src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type ScalarFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/scalar-flat-entity.type';
|
||||
import { type EntityWithRegroupedOneToManyRelations } from 'src/engine/workspace-cache/types/entity-with-regrouped-one-to-many-relations.type';
|
||||
|
||||
const serializeScalarValue = (value: unknown): unknown => {
|
||||
if (value instanceof Date) {
|
||||
return value.toISOString();
|
||||
}
|
||||
|
||||
return value ?? null;
|
||||
};
|
||||
|
||||
const BASE_SCALAR_PROPERTY_NAMES = [
|
||||
'id',
|
||||
'workspaceId',
|
||||
'applicationId',
|
||||
'universalIdentifier',
|
||||
] as const;
|
||||
|
||||
// Allow-list counterpart to removePropertiesFromRecord: rather than forwarding
|
||||
// every entity property except the known relations (deny-list), this forwards only
|
||||
// the scalar columns registered in
|
||||
// ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME plus the always-present base
|
||||
// columns, serialized into their flat (ScalarFlatEntity) shape. Anything unexpected
|
||||
// on the entity instance is dropped, so a flat entity can never silently leak an
|
||||
// unregistered property. Absent values are normalized to `null` so the output always
|
||||
// has a stable key shape and never an `undefined` value.
|
||||
export const fromEntityToScalarEntity = <T extends AllMetadataName>({
|
||||
metadataName,
|
||||
entity,
|
||||
}: {
|
||||
metadataName: T;
|
||||
entity: EntityWithRegroupedOneToManyRelations<MetadataEntity<T>>;
|
||||
}): ScalarFlatEntity<MetadataEntity<T>> => {
|
||||
const propertiesConfiguration =
|
||||
ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME[metadataName];
|
||||
const entityRecord = entity as Record<string, unknown>;
|
||||
|
||||
const scalarProperties: Record<string, unknown> = {};
|
||||
|
||||
for (const propertyName of [
|
||||
...BASE_SCALAR_PROPERTY_NAMES,
|
||||
...Object.keys(propertiesConfiguration),
|
||||
]) {
|
||||
scalarProperties[propertyName] = serializeScalarValue(
|
||||
entityRecord[propertyName],
|
||||
);
|
||||
}
|
||||
|
||||
return scalarProperties as ScalarFlatEntity<MetadataEntity<T>>;
|
||||
};
|
||||
+21
-77
@@ -1,80 +1,30 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { isFieldMetadataSettingsOfType } from 'src/engine/metadata-modules/field-metadata/utils/is-field-metadata-settings-of-type.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromFieldMetadataEntityToFlatFieldMetadata = ({
|
||||
entity: fieldMetadataEntity,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'fieldMetadata'>): FlatFieldMetadata => {
|
||||
const fieldMetadataWithoutRelations = removePropertiesFromRecord(
|
||||
fieldMetadataEntity,
|
||||
getMetadataEntityRelationProperties('fieldMetadata'),
|
||||
);
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
fieldMetadataEntity.applicationId,
|
||||
);
|
||||
export const fromFieldMetadataEntityToFlatFieldMetadata = (
|
||||
args: FromEntityToFlatEntityArgs<'fieldMetadata'>,
|
||||
): FlatFieldMetadata => {
|
||||
const {
|
||||
entity: fieldMetadataEntity,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
} = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${fieldMetadataEntity.applicationId} not found when building flat field metadata for field ${fieldMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const fieldMetadataScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'fieldMetadata',
|
||||
entity: fieldMetadataEntity,
|
||||
});
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
fieldMetadataEntity.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Object metadata with id ${fieldMetadataEntity.objectMetadataId} not found when building flat field metadata for field ${fieldMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let relationTargetObjectMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(fieldMetadataEntity.relationTargetObjectMetadataId)) {
|
||||
relationTargetObjectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
fieldMetadataEntity.relationTargetObjectMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(relationTargetObjectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Relation target object metadata with id ${fieldMetadataEntity.relationTargetObjectMetadataId} not found when building flat field metadata for field ${fieldMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let relationTargetFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(fieldMetadataEntity.relationTargetFieldMetadataId)) {
|
||||
relationTargetFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
fieldMetadataEntity.relationTargetFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(relationTargetFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Relation target field metadata with id ${fieldMetadataEntity.relationTargetFieldMetadataId} not found when building flat field metadata for field ${fieldMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'fieldMetadata',
|
||||
...args,
|
||||
});
|
||||
|
||||
const settings = fieldMetadataEntity.settings;
|
||||
const isRelationSettings =
|
||||
@@ -94,10 +44,8 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = ({
|
||||
: settings;
|
||||
|
||||
return {
|
||||
...fieldMetadataWithoutRelations,
|
||||
universalIdentifier: fieldMetadataWithoutRelations.universalIdentifier,
|
||||
createdAt: fieldMetadataWithoutRelations.createdAt.toISOString(),
|
||||
updatedAt: fieldMetadataWithoutRelations.updatedAt.toISOString(),
|
||||
...fieldMetadataScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
kanbanAggregateOperationViewIds:
|
||||
fieldMetadataEntity.kanbanAggregateOperationViews.map(({ id }) => id),
|
||||
calendarViewIds: fieldMetadataEntity.calendarViews.map(({ id }) => id),
|
||||
@@ -108,10 +56,6 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = ({
|
||||
viewFilterIds: fieldMetadataEntity.viewFilters.map(({ id }) => id),
|
||||
fieldPermissionIds:
|
||||
fieldMetadataEntity.fieldPermissions?.map(({ id }) => id) ?? [],
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
relationTargetObjectMetadataUniversalIdentifier,
|
||||
relationTargetFieldMetadataUniversalIdentifier,
|
||||
viewFieldUniversalIdentifiers: fieldMetadataEntity.viewFields.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
|
||||
+17
-72
@@ -1,81 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatFieldPermission } from 'src/engine/metadata-modules/flat-field-permission/types/flat-field-permission.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromFieldPermissionEntityToFlatFieldPermission = ({
|
||||
entity: fieldPermissionEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'fieldPermission'>): FlatFieldPermission => {
|
||||
const fieldPermissionEntityWithoutRelations = removePropertiesFromRecord(
|
||||
fieldPermissionEntity,
|
||||
getMetadataEntityRelationProperties('fieldPermission'),
|
||||
);
|
||||
export const fromFieldPermissionEntityToFlatFieldPermission = (
|
||||
args: FromEntityToFlatEntityArgs<'fieldPermission'>,
|
||||
): FlatFieldPermission => {
|
||||
const { entity: fieldPermissionEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
fieldPermissionEntity.applicationId,
|
||||
);
|
||||
const fieldPermissionScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'fieldPermission',
|
||||
entity: fieldPermissionEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${fieldPermissionEntity.applicationId} not found for fieldPermission ${fieldPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
fieldPermissionEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${fieldPermissionEntity.roleId} not found for fieldPermission ${fieldPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
fieldPermissionEntity.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${fieldPermissionEntity.objectMetadataId} not found for fieldPermission ${fieldPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
fieldPermissionEntity.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${fieldPermissionEntity.fieldMetadataId} not found for fieldPermission ${fieldPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'fieldPermission',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...fieldPermissionEntityWithoutRelations,
|
||||
createdAt: fieldPermissionEntity.createdAt.toISOString(),
|
||||
updatedAt: fieldPermissionEntity.updatedAt.toISOString(),
|
||||
universalIdentifier:
|
||||
fieldPermissionEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
...fieldPermissionScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-35
@@ -1,43 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromFrontComponentEntityToFlatFrontComponent = ({
|
||||
entity: frontComponentEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'frontComponent'>): FlatFrontComponent => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
frontComponentEntity.applicationId,
|
||||
);
|
||||
export const fromFrontComponentEntityToFlatFrontComponent = (
|
||||
args: FromEntityToFlatEntityArgs<'frontComponent'>,
|
||||
): FlatFrontComponent => {
|
||||
const { entity: frontComponentEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${frontComponentEntity.applicationId} not found for frontComponent ${frontComponentEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const frontComponentScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'frontComponent',
|
||||
entity: frontComponentEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'frontComponent',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: frontComponentEntity.id,
|
||||
name: frontComponentEntity.name,
|
||||
description: frontComponentEntity.description,
|
||||
sourceComponentPath: frontComponentEntity.sourceComponentPath,
|
||||
builtComponentPath: frontComponentEntity.builtComponentPath,
|
||||
componentName: frontComponentEntity.componentName,
|
||||
builtComponentChecksum: frontComponentEntity.builtComponentChecksum,
|
||||
isHeadless: frontComponentEntity.isHeadless,
|
||||
usesSdkClient: frontComponentEntity.usesSdkClient,
|
||||
workspaceId: frontComponentEntity.workspaceId,
|
||||
universalIdentifier: frontComponentEntity.universalIdentifier,
|
||||
applicationId: frontComponentEntity.applicationId,
|
||||
createdAt: frontComponentEntity.createdAt.toISOString(),
|
||||
updatedAt: frontComponentEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
...frontComponentScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+24
-41
@@ -4,53 +4,38 @@ import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromIndexMetadataEntityToFlatIndexMetadata = ({
|
||||
entity: indexMetadataEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'index'> & {
|
||||
fieldMetadataIdToUniversalIdentifierMap: Map<string, string>;
|
||||
}): FlatIndexMetadata => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
indexMetadataEntity.applicationId,
|
||||
);
|
||||
type FromIndexMetadataEntityToFlatIndexMetadataArgs =
|
||||
FromEntityToFlatEntityArgs<'index'> & {
|
||||
fieldMetadataIdToUniversalIdentifierMap: Map<string, string>;
|
||||
};
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${indexMetadataEntity.applicationId} not found for index ${indexMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
export const fromIndexMetadataEntityToFlatIndexMetadata = (
|
||||
args: FromIndexMetadataEntityToFlatIndexMetadataArgs,
|
||||
): FlatIndexMetadata => {
|
||||
const {
|
||||
entity: indexMetadataEntity,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
} = args;
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
indexMetadataEntity.objectMetadataId,
|
||||
);
|
||||
const indexMetadataScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'index',
|
||||
entity: indexMetadataEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${indexMetadataEntity.objectMetadataId} not found for index ${indexMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const indexMetadataEntityWithoutRelations = removePropertiesFromRecord(
|
||||
indexMetadataEntity,
|
||||
getMetadataEntityRelationProperties('index'),
|
||||
);
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'index',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...indexMetadataEntityWithoutRelations,
|
||||
createdAt: indexMetadataEntity.createdAt.toISOString(),
|
||||
updatedAt: indexMetadataEntity.updatedAt.toISOString(),
|
||||
universalIdentifier:
|
||||
indexMetadataEntityWithoutRelations.universalIdentifier,
|
||||
...indexMetadataScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
flatIndexFieldMetadatas: indexMetadataEntity.indexFieldMetadatas.map(
|
||||
(indexFieldMetadata) => ({
|
||||
...removePropertiesFromRecord(indexFieldMetadata, [
|
||||
@@ -86,7 +71,5 @@ export const fromIndexMetadataEntityToFlatIndexMetadata = ({
|
||||
fieldMetadataUniversalIdentifier,
|
||||
};
|
||||
}),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-109
@@ -1,118 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromNavigationMenuItemEntityToFlatNavigationMenuItem = ({
|
||||
entity: navigationMenuItemEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
navigationMenuItemIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
pageLayoutIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'navigationMenuItem'>): FlatNavigationMenuItem => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
navigationMenuItemEntity.applicationId,
|
||||
);
|
||||
export const fromNavigationMenuItemEntityToFlatNavigationMenuItem = (
|
||||
args: FromEntityToFlatEntityArgs<'navigationMenuItem'>,
|
||||
): FlatNavigationMenuItem => {
|
||||
const { entity: navigationMenuItemEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${navigationMenuItemEntity.applicationId} not found for navigationMenuItem ${navigationMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const navigationMenuItemScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'navigationMenuItem',
|
||||
entity: navigationMenuItemEntity,
|
||||
});
|
||||
|
||||
let targetObjectMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(navigationMenuItemEntity.targetObjectMetadataId)) {
|
||||
targetObjectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
navigationMenuItemEntity.targetObjectMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(targetObjectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${navigationMenuItemEntity.targetObjectMetadataId} not found for navigationMenuItem ${navigationMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let folderUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(navigationMenuItemEntity.folderId)) {
|
||||
folderUniversalIdentifier =
|
||||
navigationMenuItemIdToUniversalIdentifierMap.get(
|
||||
navigationMenuItemEntity.folderId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(folderUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`NavigationMenuItem (folder) with id ${navigationMenuItemEntity.folderId} not found for navigationMenuItem ${navigationMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let viewUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(navigationMenuItemEntity.viewId)) {
|
||||
viewUniversalIdentifier =
|
||||
viewIdToUniversalIdentifierMap.get(navigationMenuItemEntity.viewId) ??
|
||||
null;
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${navigationMenuItemEntity.viewId} not found for navigationMenuItem ${navigationMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let pageLayoutUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(navigationMenuItemEntity.pageLayoutId)) {
|
||||
pageLayoutUniversalIdentifier =
|
||||
pageLayoutIdToUniversalIdentifierMap.get(
|
||||
navigationMenuItemEntity.pageLayoutId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(pageLayoutUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`PageLayout with id ${navigationMenuItemEntity.pageLayoutId} not found for navigationMenuItem ${navigationMenuItemEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'navigationMenuItem',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: navigationMenuItemEntity.id,
|
||||
type: navigationMenuItemEntity.type,
|
||||
userWorkspaceId: navigationMenuItemEntity.userWorkspaceId,
|
||||
targetRecordId: navigationMenuItemEntity.targetRecordId,
|
||||
targetObjectMetadataId: navigationMenuItemEntity.targetObjectMetadataId,
|
||||
viewId: navigationMenuItemEntity.viewId,
|
||||
folderId: navigationMenuItemEntity.folderId,
|
||||
name: navigationMenuItemEntity.name,
|
||||
link: navigationMenuItemEntity.link,
|
||||
icon: navigationMenuItemEntity.icon,
|
||||
color: navigationMenuItemEntity.color,
|
||||
pageLayoutId: navigationMenuItemEntity.pageLayoutId,
|
||||
position: navigationMenuItemEntity.position,
|
||||
workspaceId: navigationMenuItemEntity.workspaceId,
|
||||
universalIdentifier: navigationMenuItemEntity.universalIdentifier,
|
||||
applicationId: navigationMenuItemEntity.applicationId,
|
||||
createdAt: navigationMenuItemEntity.createdAt.toISOString(),
|
||||
updatedAt: navigationMenuItemEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
targetObjectMetadataUniversalIdentifier,
|
||||
folderUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
pageLayoutUniversalIdentifier,
|
||||
...navigationMenuItemScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+25
-33
@@ -1,40 +1,36 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
type FromObjectMetadataEntityToFlatObjectMetadataArgs =
|
||||
FromEntityToFlatEntityArgs<'objectMetadata'> & {
|
||||
fieldMetadataIdToUniversalIdentifierMap: Map<string, string>;
|
||||
};
|
||||
|
||||
export const fromObjectMetadataEntityToFlatObjectMetadata = ({
|
||||
entity: objectMetadataEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromObjectMetadataEntityToFlatObjectMetadataArgs): FlatObjectMetadata => {
|
||||
const objectMetadataEntityWithoutRelations = removePropertiesFromRecord(
|
||||
objectMetadataEntity,
|
||||
getMetadataEntityRelationProperties('objectMetadata'),
|
||||
);
|
||||
export const fromObjectMetadataEntityToFlatObjectMetadata = (
|
||||
args: FromObjectMetadataEntityToFlatObjectMetadataArgs,
|
||||
): FlatObjectMetadata => {
|
||||
const {
|
||||
entity: objectMetadataEntity,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
} = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
objectMetadataEntity.applicationId,
|
||||
);
|
||||
const objectMetadataScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'objectMetadata',
|
||||
entity: objectMetadataEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${objectMetadataEntity.applicationId} not found when building flat object metadata for object ${objectMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'objectMetadata',
|
||||
...args,
|
||||
});
|
||||
|
||||
// labelIdentifier/imageIdentifier are soft field references (not modeled
|
||||
// relations) resolved without throwing on missing identifiers
|
||||
let labelIdentifierFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(objectMetadataEntity.labelIdentifierFieldMetadataId)) {
|
||||
@@ -70,11 +66,10 @@ export const fromObjectMetadataEntityToFlatObjectMetadata = ({
|
||||
}
|
||||
|
||||
return {
|
||||
...objectMetadataEntityWithoutRelations,
|
||||
universalIdentifier:
|
||||
objectMetadataEntityWithoutRelations.universalIdentifier,
|
||||
createdAt: objectMetadataEntity.createdAt.toISOString(),
|
||||
updatedAt: objectMetadataEntity.updatedAt.toISOString(),
|
||||
...objectMetadataScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
imageIdentifierFieldMetadataUniversalIdentifier,
|
||||
viewIds: objectMetadataEntity.views.map(({ id }) => id),
|
||||
indexMetadataIds: objectMetadataEntity.indexMetadatas.map(({ id }) => id),
|
||||
searchFieldMetadataIds: objectMetadataEntity.searchFieldMetadatas.map(
|
||||
@@ -86,9 +81,6 @@ export const fromObjectMetadataEntityToFlatObjectMetadata = ({
|
||||
),
|
||||
fieldPermissionIds:
|
||||
objectMetadataEntity.fieldPermissions?.map(({ id }) => id) ?? [],
|
||||
applicationUniversalIdentifier,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
imageIdentifierFieldMetadataUniversalIdentifier,
|
||||
fieldUniversalIdentifiers: objectMetadataEntity.fields.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
|
||||
+17
-58
@@ -1,67 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatObjectPermission } from 'src/engine/metadata-modules/flat-object-permission/types/flat-object-permission.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromObjectPermissionEntityToFlatObjectPermission = ({
|
||||
entity: objectPermissionEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'objectPermission'>): FlatObjectPermission => {
|
||||
const objectPermissionEntityWithoutRelations = removePropertiesFromRecord(
|
||||
objectPermissionEntity,
|
||||
getMetadataEntityRelationProperties('objectPermission'),
|
||||
);
|
||||
export const fromObjectPermissionEntityToFlatObjectPermission = (
|
||||
args: FromEntityToFlatEntityArgs<'objectPermission'>,
|
||||
): FlatObjectPermission => {
|
||||
const { entity: objectPermissionEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
objectPermissionEntity.applicationId,
|
||||
);
|
||||
const objectPermissionScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'objectPermission',
|
||||
entity: objectPermissionEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${objectPermissionEntity.applicationId} not found for objectPermission ${objectPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
objectPermissionEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${objectPermissionEntity.roleId} not found for objectPermission ${objectPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
objectPermissionEntity.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${objectPermissionEntity.objectMetadataId} not found for objectPermission ${objectPermissionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'objectPermission',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...objectPermissionEntityWithoutRelations,
|
||||
createdAt: objectPermissionEntity.createdAt.toISOString(),
|
||||
updatedAt: objectPermissionEntity.updatedAt.toISOString(),
|
||||
universalIdentifier:
|
||||
objectPermissionEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
...objectPermissionScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+26
-69
@@ -1,14 +1,11 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { fromPageLayoutWidgetConfigurationToUniversalConfiguration } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util';
|
||||
import { fromPageLayoutWidgetOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-overrides-to-universal-overrides.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
type FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs =
|
||||
FromEntityToFlatEntityArgs<'pageLayoutWidget'> & {
|
||||
@@ -18,64 +15,32 @@ type FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs =
|
||||
viewUniversalIdentifierById?: Partial<Record<string, string>>;
|
||||
};
|
||||
|
||||
export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
|
||||
entity: pageLayoutWidgetEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
pageLayoutTabIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataUniversalIdentifierById,
|
||||
frontComponentUniversalIdentifierById,
|
||||
viewFieldGroupUniversalIdentifierById,
|
||||
viewUniversalIdentifierById,
|
||||
}: FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs): FlatPageLayoutWidget => {
|
||||
const pageLayoutWidgetEntityWithoutRelations = removePropertiesFromRecord(
|
||||
pageLayoutWidgetEntity,
|
||||
getMetadataEntityRelationProperties('pageLayoutWidget'),
|
||||
);
|
||||
export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = (
|
||||
args: FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs,
|
||||
): FlatPageLayoutWidget => {
|
||||
const {
|
||||
entity: pageLayoutWidgetEntity,
|
||||
pageLayoutTabIdToUniversalIdentifierMap,
|
||||
fieldMetadataUniversalIdentifierById,
|
||||
frontComponentUniversalIdentifierById,
|
||||
viewFieldGroupUniversalIdentifierById,
|
||||
viewUniversalIdentifierById,
|
||||
} = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
pageLayoutWidgetEntity.applicationId,
|
||||
);
|
||||
const pageLayoutWidgetScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
entity: pageLayoutWidgetEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${pageLayoutWidgetEntity.applicationId} not found for pageLayoutWidget ${pageLayoutWidgetEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const pageLayoutTabUniversalIdentifier =
|
||||
pageLayoutTabIdToUniversalIdentifierMap.get(
|
||||
pageLayoutWidgetEntity.pageLayoutTabId,
|
||||
);
|
||||
|
||||
if (!isDefined(pageLayoutTabUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`PageLayoutTab with id ${pageLayoutWidgetEntity.pageLayoutTabId} not found for pageLayoutWidget ${pageLayoutWidgetEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let objectMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(pageLayoutWidgetEntity.objectMetadataId)) {
|
||||
objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
pageLayoutWidgetEntity.objectMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${pageLayoutWidgetEntity.objectMetadataId} not found for pageLayoutWidget ${pageLayoutWidgetEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
...args,
|
||||
});
|
||||
|
||||
const configurationWithUniversalIdentifiers =
|
||||
fromPageLayoutWidgetConfigurationToUniversalConfiguration({
|
||||
configuration: pageLayoutWidgetEntityWithoutRelations.configuration,
|
||||
configuration: pageLayoutWidgetScalarEntity.configuration,
|
||||
fieldMetadataUniversalIdentifierById,
|
||||
frontComponentUniversalIdentifierById,
|
||||
viewFieldGroupUniversalIdentifierById,
|
||||
@@ -95,16 +60,8 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
|
||||
: null;
|
||||
|
||||
return {
|
||||
...pageLayoutWidgetEntityWithoutRelations,
|
||||
createdAt: pageLayoutWidgetEntity.createdAt.toISOString(),
|
||||
updatedAt: pageLayoutWidgetEntity.updatedAt.toISOString(),
|
||||
deletedAt: pageLayoutWidgetEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
pageLayoutWidgetEntityWithoutRelations.universalIdentifier,
|
||||
applicationId: pageLayoutWidgetEntityWithoutRelations.applicationId,
|
||||
applicationUniversalIdentifier,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
...pageLayoutWidgetScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
universalConfiguration: configurationWithUniversalIdentifiers,
|
||||
universalOverrides,
|
||||
};
|
||||
|
||||
+17
-30
@@ -1,40 +1,27 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatPermissionFlag } from 'src/engine/metadata-modules/flat-permission-flag/types/flat-permission-flag.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromPermissionFlagEntityToFlatPermissionFlag = ({
|
||||
entity: permissionFlagEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'permissionFlag'>): FlatPermissionFlag => {
|
||||
const entityWithoutRelations = removePropertiesFromRecord(
|
||||
permissionFlagEntity,
|
||||
getMetadataEntityRelationProperties('permissionFlag'),
|
||||
);
|
||||
export const fromPermissionFlagEntityToFlatPermissionFlag = (
|
||||
args: FromEntityToFlatEntityArgs<'permissionFlag'>,
|
||||
): FlatPermissionFlag => {
|
||||
const { entity: permissionFlagEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
permissionFlagEntity.applicationId,
|
||||
);
|
||||
const permissionFlagScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'permissionFlag',
|
||||
entity: permissionFlagEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${permissionFlagEntity.applicationId} not found for permissionFlag ${permissionFlagEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'permissionFlag',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...entityWithoutRelations,
|
||||
createdAt: permissionFlagEntity.createdAt.toISOString(),
|
||||
updatedAt: permissionFlagEntity.updatedAt.toISOString(),
|
||||
universalIdentifier: entityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
...permissionFlagScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
rolePermissionFlagIds: permissionFlagEntity.rolePermissionFlags.map(
|
||||
({ id }) => id,
|
||||
),
|
||||
|
||||
+17
-58
@@ -1,67 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatRolePermissionFlag } from 'src/engine/metadata-modules/flat-role-permission-flag/types/flat-role-permission-flag.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromRolePermissionFlagEntityToFlatRolePermissionFlag = ({
|
||||
entity: rolePermissionFlagEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
permissionFlagIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'rolePermissionFlag'>): FlatRolePermissionFlag => {
|
||||
const rolePermissionFlagEntityWithoutRelations = removePropertiesFromRecord(
|
||||
rolePermissionFlagEntity,
|
||||
getMetadataEntityRelationProperties('rolePermissionFlag'),
|
||||
);
|
||||
export const fromRolePermissionFlagEntityToFlatRolePermissionFlag = (
|
||||
args: FromEntityToFlatEntityArgs<'rolePermissionFlag'>,
|
||||
): FlatRolePermissionFlag => {
|
||||
const { entity: rolePermissionFlagEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
rolePermissionFlagEntity.applicationId,
|
||||
);
|
||||
const rolePermissionFlagScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'rolePermissionFlag',
|
||||
entity: rolePermissionFlagEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${rolePermissionFlagEntity.applicationId} not found for rolePermissionFlag ${rolePermissionFlagEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
rolePermissionFlagEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${rolePermissionFlagEntity.roleId} not found for rolePermissionFlag ${rolePermissionFlagEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const permissionFlagUniversalIdentifier =
|
||||
permissionFlagIdToUniversalIdentifierMap.get(
|
||||
rolePermissionFlagEntity.permissionFlagId,
|
||||
);
|
||||
|
||||
if (!isDefined(permissionFlagUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`PermissionFlag with id ${rolePermissionFlagEntity.permissionFlagId} not found for rolePermissionFlag ${rolePermissionFlagEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'rolePermissionFlag',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...rolePermissionFlagEntityWithoutRelations,
|
||||
createdAt: rolePermissionFlagEntity.createdAt.toISOString(),
|
||||
updatedAt: rolePermissionFlagEntity.updatedAt.toISOString(),
|
||||
universalIdentifier:
|
||||
rolePermissionFlagEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
permissionFlagUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
...rolePermissionFlagScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-41
@@ -1,50 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromRoleTargetEntityToFlatRoleTarget = ({
|
||||
entity: roleTargetEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'roleTarget'>): FlatRoleTarget => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(roleTargetEntity.applicationId);
|
||||
export const fromRoleTargetEntityToFlatRoleTarget = (
|
||||
args: FromEntityToFlatEntityArgs<'roleTarget'>,
|
||||
): FlatRoleTarget => {
|
||||
const { entity: roleTargetEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${roleTargetEntity.applicationId} not found when building flat role target for role target ${roleTargetEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const roleTargetScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'roleTarget',
|
||||
entity: roleTargetEntity,
|
||||
});
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
roleTargetEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${roleTargetEntity.roleId} not found when building flat role target for role target ${roleTargetEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'roleTarget',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: roleTargetEntity.id,
|
||||
workspaceId: roleTargetEntity.workspaceId,
|
||||
roleId: roleTargetEntity.roleId,
|
||||
userWorkspaceId: roleTargetEntity.userWorkspaceId,
|
||||
agentId: roleTargetEntity.agentId,
|
||||
apiKeyId: roleTargetEntity.apiKeyId,
|
||||
applicationId: roleTargetEntity.applicationId,
|
||||
universalIdentifier: roleTargetEntity.universalIdentifier,
|
||||
createdAt: roleTargetEntity.createdAt.toISOString(),
|
||||
updatedAt: roleTargetEntity.updatedAt.toISOString(),
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
...roleTargetScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-38
@@ -1,14 +1,10 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type EntityManyToOneIdByUniversalIdentifierMaps } from 'src/engine/workspace-cache/types/entity-many-to-one-id-by-universal-identifier-maps.type';
|
||||
import { type EntityWithRegroupedOneToManyRelations } from 'src/engine/workspace-cache/types/entity-with-regrouped-one-to-many-relations.type';
|
||||
import { type RegroupedEntity } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
type FromRoleEntityToFlatRoleArgs = {
|
||||
entity: Omit<
|
||||
@@ -21,40 +17,25 @@ type FromRoleEntityToFlatRoleArgs = {
|
||||
};
|
||||
} & EntityManyToOneIdByUniversalIdentifierMaps<'role'>;
|
||||
|
||||
export const fromRoleEntityToFlatRole = ({
|
||||
entity: roleEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromRoleEntityToFlatRoleArgs): FlatRole => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(roleEntity.applicationId);
|
||||
export const fromRoleEntityToFlatRole = (
|
||||
args: FromRoleEntityToFlatRoleArgs,
|
||||
): FlatRole => {
|
||||
const { entity: roleEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${roleEntity.applicationId} not found for role ${roleEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const roleScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'role',
|
||||
entity: roleEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'role',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: roleEntity.id,
|
||||
label: roleEntity.label,
|
||||
description: roleEntity.description,
|
||||
icon: roleEntity.icon,
|
||||
isEditable: roleEntity.isEditable,
|
||||
canUpdateAllSettings: roleEntity.canUpdateAllSettings,
|
||||
canAccessAllTools: roleEntity.canAccessAllTools,
|
||||
canReadAllObjectRecords: roleEntity.canReadAllObjectRecords,
|
||||
canUpdateAllObjectRecords: roleEntity.canUpdateAllObjectRecords,
|
||||
canSoftDeleteAllObjectRecords: roleEntity.canSoftDeleteAllObjectRecords,
|
||||
canDestroyAllObjectRecords: roleEntity.canDestroyAllObjectRecords,
|
||||
canBeAssignedToUsers: roleEntity.canBeAssignedToUsers,
|
||||
canBeAssignedToAgents: roleEntity.canBeAssignedToAgents,
|
||||
canBeAssignedToApiKeys: roleEntity.canBeAssignedToApiKeys,
|
||||
workspaceId: roleEntity.workspaceId,
|
||||
createdAt: roleEntity.createdAt.toISOString(),
|
||||
updatedAt: roleEntity.updatedAt.toISOString(),
|
||||
universalIdentifier: roleEntity.universalIdentifier,
|
||||
applicationId: roleEntity.applicationId,
|
||||
...roleScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
roleTargetIds: roleEntity.roleTargets.map(({ id }) => id),
|
||||
objectPermissionIds: roleEntity.objectPermissions.map(({ id }) => id),
|
||||
rolePermissionFlagIds: roleEntity.rolePermissionFlags.map(({ id }) => id),
|
||||
@@ -64,7 +45,6 @@ export const fromRoleEntityToFlatRole = ({
|
||||
),
|
||||
rowLevelPermissionPredicateGroupIds:
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(({ id }) => id),
|
||||
applicationUniversalIdentifier,
|
||||
roleTargetUniversalIdentifiers: roleEntity.roleTargets.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export const ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'role',
|
||||
'fieldMetadata',
|
||||
'workspaceMemberFieldMetadata',
|
||||
'objectMetadata',
|
||||
'rowLevelPermissionPredicateGroup',
|
||||
'application',
|
||||
] as const;
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export const ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'role',
|
||||
'parentRowLevelPermissionPredicateGroup',
|
||||
'childRowLevelPermissionPredicateGroups',
|
||||
'rowLevelPermissionPredicates',
|
||||
'application',
|
||||
] as const;
|
||||
+17
-118
@@ -1,130 +1,29 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/row-level-permission-predicate-entity-relation-properties.constant';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromRowLevelPermissionPredicateEntityToFlatRowLevelPermissionPredicate =
|
||||
({
|
||||
entity: rowLevelPermissionPredicateEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
rowLevelPermissionPredicateGroupIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'rowLevelPermissionPredicate'>): FlatRowLevelPermissionPredicate => {
|
||||
const rowLevelPermissionPredicateEntityWithoutRelations =
|
||||
removePropertiesFromRecord(rowLevelPermissionPredicateEntity, [
|
||||
...ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES,
|
||||
] as (typeof ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES)[number][]);
|
||||
(
|
||||
args: FromEntityToFlatEntityArgs<'rowLevelPermissionPredicate'>,
|
||||
): FlatRowLevelPermissionPredicate => {
|
||||
const { entity: rowLevelPermissionPredicateEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.applicationId,
|
||||
);
|
||||
const rowLevelPermissionPredicateScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
entity: rowLevelPermissionPredicateEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${rowLevelPermissionPredicateEntity.applicationId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${rowLevelPermissionPredicateEntity.fieldMetadataId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${rowLevelPermissionPredicateEntity.objectMetadataId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${rowLevelPermissionPredicateEntity.roleId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let workspaceMemberFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
rowLevelPermissionPredicateEntity.workspaceMemberFieldMetadataId,
|
||||
)
|
||||
) {
|
||||
workspaceMemberFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.workspaceMemberFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(workspaceMemberFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${rowLevelPermissionPredicateEntity.workspaceMemberFieldMetadataId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let rowLevelPermissionPredicateGroupUniversalIdentifier: string | null =
|
||||
null;
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
rowLevelPermissionPredicateEntity.rowLevelPermissionPredicateGroupId,
|
||||
)
|
||||
) {
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier =
|
||||
rowLevelPermissionPredicateGroupIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateEntity.rowLevelPermissionPredicateGroupId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(rowLevelPermissionPredicateGroupUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`RowLevelPermissionPredicateGroup with id ${rowLevelPermissionPredicateEntity.rowLevelPermissionPredicateGroupId} not found for rowLevelPermissionPredicate ${rowLevelPermissionPredicateEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...rowLevelPermissionPredicateEntityWithoutRelations,
|
||||
createdAt: rowLevelPermissionPredicateEntity.createdAt.toISOString(),
|
||||
updatedAt: rowLevelPermissionPredicateEntity.updatedAt.toISOString(),
|
||||
deletedAt:
|
||||
rowLevelPermissionPredicateEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
...rowLevelPermissionPredicateScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-94
@@ -1,103 +1,31 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/row-level-permission-predicate-group-entity-relation-properties.constant';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
|
||||
type FromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroupArgs =
|
||||
FromEntityToFlatEntityArgs<'rowLevelPermissionPredicateGroup'> & {
|
||||
rowLevelPermissionPredicateGroupIdToUniversalIdentifierMap: Map<
|
||||
string,
|
||||
string
|
||||
>;
|
||||
};
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroup =
|
||||
({
|
||||
entity: rowLevelPermissionPredicateGroupEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
rowLevelPermissionPredicateGroupIdToUniversalIdentifierMap,
|
||||
}: FromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroupArgs): FlatRowLevelPermissionPredicateGroup => {
|
||||
const rowLevelPermissionPredicateGroupEntityWithoutRelations =
|
||||
removePropertiesFromRecord(rowLevelPermissionPredicateGroupEntity, [
|
||||
...ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES,
|
||||
] as (typeof ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES)[number][]);
|
||||
(
|
||||
args: FromEntityToFlatEntityArgs<'rowLevelPermissionPredicateGroup'>,
|
||||
): FlatRowLevelPermissionPredicateGroup => {
|
||||
const { entity: rowLevelPermissionPredicateGroupEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateGroupEntity.applicationId,
|
||||
);
|
||||
const rowLevelPermissionPredicateGroupScalarEntity =
|
||||
fromEntityToScalarEntity({
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
entity: rowLevelPermissionPredicateGroupEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${rowLevelPermissionPredicateGroupEntity.applicationId} not found for rowLevelPermissionPredicateGroup ${rowLevelPermissionPredicateGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateGroupEntity.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${rowLevelPermissionPredicateGroupEntity.objectMetadataId} not found for rowLevelPermissionPredicateGroup ${rowLevelPermissionPredicateGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleUniversalIdentifier = roleIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateGroupEntity.roleId,
|
||||
);
|
||||
|
||||
if (!isDefined(roleUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Role with id ${rowLevelPermissionPredicateGroupEntity.roleId} not found for rowLevelPermissionPredicateGroup ${rowLevelPermissionPredicateGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let parentRowLevelPermissionPredicateGroupUniversalIdentifier:
|
||||
| string
|
||||
| null = null;
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
rowLevelPermissionPredicateGroupEntity.parentRowLevelPermissionPredicateGroupId,
|
||||
)
|
||||
) {
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier =
|
||||
rowLevelPermissionPredicateGroupIdToUniversalIdentifierMap.get(
|
||||
rowLevelPermissionPredicateGroupEntity.parentRowLevelPermissionPredicateGroupId,
|
||||
) ?? null;
|
||||
|
||||
if (
|
||||
!isDefined(parentRowLevelPermissionPredicateGroupUniversalIdentifier)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
`RowLevelPermissionPredicateGroup with id ${rowLevelPermissionPredicateGroupEntity.parentRowLevelPermissionPredicateGroupId} not found for rowLevelPermissionPredicateGroup ${rowLevelPermissionPredicateGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...rowLevelPermissionPredicateGroupEntityWithoutRelations,
|
||||
createdAt: rowLevelPermissionPredicateGroupEntity.createdAt.toISOString(),
|
||||
updatedAt: rowLevelPermissionPredicateGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt:
|
||||
rowLevelPermissionPredicateGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateGroupEntityWithoutRelations.universalIdentifier,
|
||||
...rowLevelPermissionPredicateGroupScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
childRowLevelPermissionPredicateGroupIds: (
|
||||
rowLevelPermissionPredicateGroupEntity.childRowLevelPermissionPredicateGroups ??
|
||||
[]
|
||||
@@ -106,10 +34,6 @@ export const fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionP
|
||||
rowLevelPermissionPredicateGroupEntity.rowLevelPermissionPredicates ??
|
||||
[]
|
||||
).map(({ id }) => id),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
childRowLevelPermissionPredicateGroupUniversalIdentifiers: (
|
||||
rowLevelPermissionPredicateGroupEntity.childRowLevelPermissionPredicateGroups ??
|
||||
[]
|
||||
|
||||
+18
-32
@@ -1,40 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatSkill } from 'src/engine/metadata-modules/flat-skill/types/flat-skill.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromSkillEntityToFlatSkill = ({
|
||||
entity: skillEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'skill'>): FlatSkill => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(skillEntity.applicationId);
|
||||
export const fromSkillEntityToFlatSkill = (
|
||||
args: FromEntityToFlatEntityArgs<'skill'>,
|
||||
): FlatSkill => {
|
||||
const { entity: skillEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${skillEntity.applicationId} not found for skill ${skillEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const skillScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'skill',
|
||||
entity: skillEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'skill',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
createdAt: skillEntity.createdAt.toISOString(),
|
||||
updatedAt: skillEntity.updatedAt.toISOString(),
|
||||
id: skillEntity.id,
|
||||
name: skillEntity.name,
|
||||
label: skillEntity.label,
|
||||
icon: skillEntity.icon,
|
||||
description: skillEntity.description,
|
||||
content: skillEntity.content,
|
||||
workspaceId: skillEntity.workspaceId,
|
||||
isCustom: skillEntity.isCustom,
|
||||
isActive: skillEntity.isActive,
|
||||
universalIdentifier: skillEntity.universalIdentifier,
|
||||
applicationId: skillEntity.applicationId,
|
||||
applicationUniversalIdentifier,
|
||||
...skillScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-45
@@ -1,55 +1,27 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewFieldGroup } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewFieldGroupEntityToFlatViewFieldGroup = ({
|
||||
entity: viewFieldGroupEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewFieldGroup'>): FlatViewFieldGroup => {
|
||||
const viewFieldGroupEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewFieldGroupEntity,
|
||||
getMetadataEntityRelationProperties('viewFieldGroup'),
|
||||
);
|
||||
export const fromViewFieldGroupEntityToFlatViewFieldGroup = (
|
||||
args: FromEntityToFlatEntityArgs<'viewFieldGroup'>,
|
||||
): FlatViewFieldGroup => {
|
||||
const { entity: viewFieldGroupEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
viewFieldGroupEntity.applicationId,
|
||||
);
|
||||
const viewFieldGroupScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewFieldGroup',
|
||||
entity: viewFieldGroupEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewFieldGroupEntity.applicationId} not found for viewFieldGroup ${viewFieldGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewFieldGroupEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewFieldGroupEntity.viewId} not found for viewFieldGroup ${viewFieldGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewFieldGroup',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...viewFieldGroupEntityWithoutRelations,
|
||||
createdAt: viewFieldGroupEntity.createdAt.toISOString(),
|
||||
updatedAt: viewFieldGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFieldGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
viewFieldGroupEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
...viewFieldGroupScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
viewFieldIds:
|
||||
viewFieldGroupEntity.viewFields?.map((viewField) => viewField.id) ?? [],
|
||||
viewFieldUniversalIdentifiers:
|
||||
|
||||
+19
-73
@@ -1,74 +1,27 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { fromViewFieldOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-view-field/utils/from-view-field-overrides-to-universal-overrides.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewFieldEntityToFlatViewField = ({
|
||||
entity: viewFieldEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
viewFieldGroupIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewField'>): FlatViewField => {
|
||||
const viewFieldEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewFieldEntity,
|
||||
getMetadataEntityRelationProperties('viewField'),
|
||||
);
|
||||
export const fromViewFieldEntityToFlatViewField = (
|
||||
args: FromEntityToFlatEntityArgs<'viewField'>,
|
||||
): FlatViewField => {
|
||||
const { entity: viewFieldEntity, viewFieldGroupIdToUniversalIdentifierMap } =
|
||||
args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewFieldEntity.applicationId);
|
||||
const viewFieldScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewField',
|
||||
entity: viewFieldEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewFieldEntity.applicationId} not found for viewField ${viewFieldEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewFieldEntity.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewFieldEntity.fieldMetadataId} not found for viewField ${viewFieldEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewFieldEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewFieldEntity.viewId} not found for viewField ${viewFieldEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let viewFieldGroupUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewFieldEntity.viewFieldGroupId)) {
|
||||
viewFieldGroupUniversalIdentifier =
|
||||
viewFieldGroupIdToUniversalIdentifierMap.get(
|
||||
viewFieldEntity.viewFieldGroupId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(viewFieldGroupUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ViewFieldGroup with id ${viewFieldEntity.viewFieldGroupId} not found for viewField ${viewFieldEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
...args,
|
||||
});
|
||||
|
||||
const viewFieldGroupUniversalIdentifierById = Object.fromEntries(
|
||||
viewFieldGroupIdToUniversalIdentifierMap.entries(),
|
||||
@@ -83,15 +36,8 @@ export const fromViewFieldEntityToFlatViewField = ({
|
||||
: null;
|
||||
|
||||
return {
|
||||
...viewFieldEntityWithoutRelations,
|
||||
createdAt: viewFieldEntity.createdAt.toISOString(),
|
||||
updatedAt: viewFieldEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFieldEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewFieldEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFieldGroupUniversalIdentifier,
|
||||
...viewFieldScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
universalOverrides,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-68
@@ -1,81 +1,30 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewFilterGroup } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
type FromViewFilterGroupEntityToFlatViewFilterGroupArgs =
|
||||
FromEntityToFlatEntityArgs<'viewFilterGroup'> & {
|
||||
viewFilterGroupIdToUniversalIdentifierMap: Map<string, string>;
|
||||
};
|
||||
export const fromViewFilterGroupEntityToFlatViewFilterGroup = (
|
||||
args: FromEntityToFlatEntityArgs<'viewFilterGroup'>,
|
||||
): FlatViewFilterGroup => {
|
||||
const { entity: viewFilterGroupEntity } = args;
|
||||
|
||||
export const fromViewFilterGroupEntityToFlatViewFilterGroup = ({
|
||||
entity: viewFilterGroupEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewFilterGroupIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
}: FromViewFilterGroupEntityToFlatViewFilterGroupArgs): FlatViewFilterGroup => {
|
||||
const viewFilterGroupEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewFilterGroupEntity,
|
||||
getMetadataEntityRelationProperties('viewFilterGroup'),
|
||||
);
|
||||
const viewFilterGroupScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewFilterGroup',
|
||||
entity: viewFilterGroupEntity,
|
||||
});
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
viewFilterGroupEntity.applicationId,
|
||||
);
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewFilterGroupEntity.applicationId} not found for viewFilterGroup ${viewFilterGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let parentViewFilterGroupUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewFilterGroupEntity.parentViewFilterGroupId)) {
|
||||
parentViewFilterGroupUniversalIdentifier =
|
||||
viewFilterGroupIdToUniversalIdentifierMap.get(
|
||||
viewFilterGroupEntity.parentViewFilterGroupId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(parentViewFilterGroupUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ViewFilterGroup with id ${viewFilterGroupEntity.parentViewFilterGroupId} not found for viewFilterGroup ${viewFilterGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewFilterGroupEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewFilterGroupEntity.viewId} not found for viewFilterGroup ${viewFilterGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewFilterGroup',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...viewFilterGroupEntityWithoutRelations,
|
||||
createdAt: viewFilterGroupEntity.createdAt.toISOString(),
|
||||
updatedAt: viewFilterGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFilterGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
viewFilterGroupEntityWithoutRelations.universalIdentifier,
|
||||
...viewFilterGroupScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
viewFilterIds: viewFilterGroupEntity.viewFilters?.map(({ id }) => id) ?? [],
|
||||
childViewFilterGroupIds:
|
||||
viewFilterGroupEntity.childViewFilterGroups?.map(({ id }) => id) ?? [],
|
||||
applicationUniversalIdentifier,
|
||||
parentViewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFilterUniversalIdentifiers:
|
||||
viewFilterGroupEntity.viewFilters?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
|
||||
+17
-91
@@ -1,100 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewFilterEntityToFlatViewFilter = ({
|
||||
entity: viewFilterEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
viewFilterGroupIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewFilter'>): FlatViewFilter => {
|
||||
const viewFilterEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewFilterEntity,
|
||||
getMetadataEntityRelationProperties('viewFilter'),
|
||||
);
|
||||
export const fromViewFilterEntityToFlatViewFilter = (
|
||||
args: FromEntityToFlatEntityArgs<'viewFilter'>,
|
||||
): FlatViewFilter => {
|
||||
const { entity: viewFilterEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewFilterEntity.applicationId);
|
||||
const viewFilterScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewFilter',
|
||||
entity: viewFilterEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewFilterEntity.applicationId} not found for viewFilter ${viewFilterEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewFilterEntity.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewFilterEntity.fieldMetadataId} not found for viewFilter ${viewFilterEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let viewFilterGroupUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewFilterEntity.viewFilterGroupId)) {
|
||||
viewFilterGroupUniversalIdentifier =
|
||||
viewFilterGroupIdToUniversalIdentifierMap.get(
|
||||
viewFilterEntity.viewFilterGroupId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(viewFilterGroupUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ViewFilterGroup with id ${viewFilterEntity.viewFilterGroupId} not found for viewFilter ${viewFilterEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewFilterEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewFilterEntity.viewId} not found for viewFilter ${viewFilterEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let relationTargetFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewFilterEntity.relationTargetFieldMetadataId)) {
|
||||
relationTargetFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewFilterEntity.relationTargetFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(relationTargetFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewFilterEntity.relationTargetFieldMetadataId} not found for viewFilter ${viewFilterEntity.id} (relation target)`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewFilter',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...viewFilterEntityWithoutRelations,
|
||||
createdAt: viewFilterEntity.createdAt.toISOString(),
|
||||
updatedAt: viewFilterEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFilterEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewFilterEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
relationTargetFieldMetadataUniversalIdentifier,
|
||||
viewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
...viewFilterScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-42
@@ -1,51 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewGroupEntityToFlatViewGroup = ({
|
||||
entity: viewGroupEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewGroup'>): FlatViewGroup => {
|
||||
const viewGroupEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewGroupEntity,
|
||||
getMetadataEntityRelationProperties('viewGroup'),
|
||||
);
|
||||
export const fromViewGroupEntityToFlatViewGroup = (
|
||||
args: FromEntityToFlatEntityArgs<'viewGroup'>,
|
||||
): FlatViewGroup => {
|
||||
const { entity: viewGroupEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewGroupEntity.applicationId);
|
||||
const viewGroupScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewGroup',
|
||||
entity: viewGroupEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewGroupEntity.applicationId} not found for viewGroup ${viewGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewGroupEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewGroupEntity.viewId} not found for viewGroup ${viewGroupEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewGroup',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...viewGroupEntityWithoutRelations,
|
||||
createdAt: viewGroupEntity.createdAt.toISOString(),
|
||||
updatedAt: viewGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewGroupEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
...viewGroupScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-55
@@ -1,63 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import type { FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewSortEntityToFlatViewSort = ({
|
||||
entity: viewSortEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewSort'>): FlatViewSort => {
|
||||
const viewSortEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewSortEntity,
|
||||
getMetadataEntityRelationProperties('viewSort'),
|
||||
);
|
||||
export const fromViewSortEntityToFlatViewSort = (
|
||||
args: FromEntityToFlatEntityArgs<'viewSort'>,
|
||||
): FlatViewSort => {
|
||||
const { entity: viewSortEntity } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewSortEntity.applicationId);
|
||||
const viewSortScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'viewSort',
|
||||
entity: viewSortEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewSortEntity.applicationId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewSortEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewSortEntity.viewId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(viewSortEntity.fieldMetadataId);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Field metadata with id ${viewSortEntity.fieldMetadataId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'viewSort',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...viewSortEntityWithoutRelations,
|
||||
createdAt: viewSortEntity.createdAt.toISOString(),
|
||||
updatedAt: viewSortEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewSortEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewSortEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
...viewSortScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-93
@@ -1,93 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { fromViewOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-view/utils/from-view-overrides-to-universal-overrides.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromViewEntityToFlatView = ({
|
||||
entity: viewEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'view'>): FlatView => {
|
||||
const viewEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewEntity,
|
||||
getMetadataEntityRelationProperties('view'),
|
||||
);
|
||||
export const fromViewEntityToFlatView = (
|
||||
args: FromEntityToFlatEntityArgs<'view'>,
|
||||
): FlatView => {
|
||||
const { entity: viewEntity, fieldMetadataIdToUniversalIdentifierMap } = args;
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewEntity.applicationId);
|
||||
const viewScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'view',
|
||||
entity: viewEntity,
|
||||
});
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewEntity.applicationId} not found for view ${viewEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataUniversalIdentifier =
|
||||
objectMetadataIdToUniversalIdentifierMap.get(viewEntity.objectMetadataId);
|
||||
|
||||
if (!isDefined(objectMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ObjectMetadata with id ${viewEntity.objectMetadataId} not found for view ${viewEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
let kanbanAggregateOperationFieldMetadataUniversalIdentifier: string | null =
|
||||
null;
|
||||
|
||||
if (isDefined(viewEntity.kanbanAggregateOperationFieldMetadataId)) {
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewEntity.kanbanAggregateOperationFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(kanbanAggregateOperationFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewEntity.kanbanAggregateOperationFieldMetadataId} not found for view ${viewEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let calendarFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewEntity.calendarFieldMetadataId)) {
|
||||
calendarFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewEntity.calendarFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(calendarFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewEntity.calendarFieldMetadataId} not found for view ${viewEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mainGroupByFieldMetadataUniversalIdentifier: string | null = null;
|
||||
|
||||
if (isDefined(viewEntity.mainGroupByFieldMetadataId)) {
|
||||
mainGroupByFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
viewEntity.mainGroupByFieldMetadataId,
|
||||
) ?? null;
|
||||
|
||||
if (!isDefined(mainGroupByFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`FieldMetadata with id ${viewEntity.mainGroupByFieldMetadataId} not found for view ${viewEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'view',
|
||||
...args,
|
||||
});
|
||||
|
||||
const universalOverrides = isDefined(viewEntity.overrides)
|
||||
? fromViewOverridesToUniversalOverrides({
|
||||
@@ -100,22 +33,14 @@ export const fromViewEntityToFlatView = ({
|
||||
: null;
|
||||
|
||||
return {
|
||||
...viewEntityWithoutRelations,
|
||||
createdAt: viewEntity.createdAt.toISOString(),
|
||||
updatedAt: viewEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewEntityWithoutRelations.universalIdentifier,
|
||||
...viewScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
universalOverrides,
|
||||
viewFieldIds: viewEntity.viewFields.map(({ id }) => id),
|
||||
viewFieldGroupIds: viewEntity.viewFieldGroups?.map(({ id }) => id) ?? [],
|
||||
viewFilterIds: viewEntity.viewFilters.map(({ id }) => id),
|
||||
viewGroupIds: viewEntity.viewGroups.map(({ id }) => id),
|
||||
viewFilterGroupIds: viewEntity.viewFilterGroups?.map(({ id }) => id) ?? [],
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
calendarFieldMetadataUniversalIdentifier,
|
||||
mainGroupByFieldMetadataUniversalIdentifier,
|
||||
viewFieldUniversalIdentifiers: viewEntity.viewFields.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
|
||||
+18
-30
@@ -1,38 +1,26 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatWebhook } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromWebhookEntityToFlatWebhook = ({
|
||||
entity: webhookEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'webhook'>): FlatWebhook => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(webhookEntity.applicationId);
|
||||
export const fromWebhookEntityToFlatWebhook = (
|
||||
args: FromEntityToFlatEntityArgs<'webhook'>,
|
||||
): FlatWebhook => {
|
||||
const { entity: webhookEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${webhookEntity.applicationId} not found for webhook ${webhookEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const webhookScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'webhook',
|
||||
entity: webhookEntity,
|
||||
});
|
||||
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'webhook',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
id: webhookEntity.id,
|
||||
targetUrl: webhookEntity.targetUrl,
|
||||
operations: webhookEntity.operations,
|
||||
description: webhookEntity.description,
|
||||
secret: webhookEntity.secret,
|
||||
workspaceId: webhookEntity.workspaceId,
|
||||
universalIdentifier: webhookEntity.universalIdentifier,
|
||||
applicationId: webhookEntity.applicationId,
|
||||
createdAt: webhookEntity.createdAt.toISOString(),
|
||||
updatedAt: webhookEntity.updatedAt.toISOString(),
|
||||
deletedAt: webhookEntity.deletedAt?.toISOString() ?? null,
|
||||
applicationUniversalIdentifier,
|
||||
...webhookScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+17
-30
@@ -1,39 +1,26 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { fromEntityToScalarEntity } from 'src/engine/metadata-modules/flat-entity/utils/from-entity-to-scalar-entity.util';
|
||||
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
export const fromLogicFunctionEntityToFlatLogicFunction = ({
|
||||
entity: logicFunctionEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'logicFunction'>): FlatLogicFunction => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
logicFunctionEntity.applicationId,
|
||||
);
|
||||
export const fromLogicFunctionEntityToFlatLogicFunction = (
|
||||
args: FromEntityToFlatEntityArgs<'logicFunction'>,
|
||||
): FlatLogicFunction => {
|
||||
const { entity: logicFunctionEntity } = args;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${logicFunctionEntity.applicationId} not found for logicFunction ${logicFunctionEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
const logicFunctionScalarEntity = fromEntityToScalarEntity({
|
||||
metadataName: 'logicFunction',
|
||||
entity: logicFunctionEntity,
|
||||
});
|
||||
|
||||
const logicFunctionWithoutRelations = removePropertiesFromRecord(
|
||||
logicFunctionEntity,
|
||||
getMetadataEntityRelationProperties('logicFunction'),
|
||||
);
|
||||
const relationUniversalIdentifiers =
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers({
|
||||
metadataName: 'logicFunction',
|
||||
...args,
|
||||
});
|
||||
|
||||
return {
|
||||
...logicFunctionWithoutRelations,
|
||||
createdAt: logicFunctionEntity.createdAt.toISOString(),
|
||||
updatedAt: logicFunctionEntity.updatedAt.toISOString(),
|
||||
deletedAt: logicFunctionEntity.deletedAt?.toISOString() ?? null,
|
||||
applicationUniversalIdentifier,
|
||||
...logicFunctionScalarEntity,
|
||||
...relationUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { FlatEntityMapsExceptionCode } from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type EntityManyToOneIdByUniversalIdentifierMaps } from 'src/engine/workspace-cache/types/entity-many-to-one-id-by-universal-identifier-maps.type';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { resolveManyToOneRelationIdsToUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-many-to-one-relation-ids-to-universal-identifiers.util';
|
||||
|
||||
const buildArgs = <T extends AllMetadataName>(
|
||||
args: {
|
||||
metadataName: T;
|
||||
entity: Record<string, string | null | undefined>;
|
||||
} & EntityManyToOneIdByUniversalIdentifierMaps<T>,
|
||||
): { metadataName: T } & FromEntityToFlatEntityArgs<T> => ({
|
||||
...args,
|
||||
entity: args.entity as unknown as FromEntityToFlatEntityArgs<T>['entity'],
|
||||
});
|
||||
|
||||
describe('resolveManyToOneRelationIdsToUniversalIdentifiers', () => {
|
||||
describe('application resolution', () => {
|
||||
it('should resolve only the application universal identifier when the entity has no other many-to-one relations', () => {
|
||||
const result = resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'permissionFlag',
|
||||
entity: {
|
||||
id: 'permission-flag-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
applicationUniversalIdentifier: 'app-ui-1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when the applicationId is not present in the map', () => {
|
||||
expect(() =>
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'permissionFlag',
|
||||
entity: {
|
||||
id: 'permission-flag-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map(),
|
||||
}),
|
||||
),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw when the entity has no applicationId', () => {
|
||||
expect(() =>
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'permissionFlag',
|
||||
entity: {
|
||||
id: 'permission-flag-id-1',
|
||||
applicationId: null,
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
}),
|
||||
),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-nullable relations', () => {
|
||||
it('should resolve universal identifiers for application and non-nullable foreign keys', () => {
|
||||
const result = resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'viewField',
|
||||
entity: {
|
||||
id: 'view-field-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
viewFieldGroupId: 'view-field-group-id-1',
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
fieldMetadataIdToUniversalIdentifierMap: new Map([
|
||||
['field-id-1', 'field-ui-1'],
|
||||
]),
|
||||
viewIdToUniversalIdentifierMap: new Map([['view-id-1', 'view-ui-1']]),
|
||||
viewFieldGroupIdToUniversalIdentifierMap: new Map([
|
||||
['view-field-group-id-1', 'view-field-group-ui-1'],
|
||||
]),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
applicationUniversalIdentifier: 'app-ui-1',
|
||||
fieldMetadataUniversalIdentifier: 'field-ui-1',
|
||||
viewUniversalIdentifier: 'view-ui-1',
|
||||
viewFieldGroupUniversalIdentifier: 'view-field-group-ui-1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when a non-nullable foreign key id is missing from the map', () => {
|
||||
expect(() =>
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'viewField',
|
||||
entity: {
|
||||
id: 'view-field-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
fieldMetadataId: 'non-existent-field-id',
|
||||
viewId: 'view-id-1',
|
||||
viewFieldGroupId: null,
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
fieldMetadataIdToUniversalIdentifierMap: new Map(),
|
||||
viewIdToUniversalIdentifierMap: new Map([
|
||||
['view-id-1', 'view-ui-1'],
|
||||
]),
|
||||
viewFieldGroupIdToUniversalIdentifierMap: new Map(),
|
||||
}),
|
||||
),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw a malformed-entity error when a non-nullable foreign key is itself missing', () => {
|
||||
expect(() =>
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'viewField',
|
||||
entity: {
|
||||
id: 'view-field-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
fieldMetadataId: null,
|
||||
viewId: 'view-id-1',
|
||||
viewFieldGroupId: null,
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
fieldMetadataIdToUniversalIdentifierMap: new Map([
|
||||
['field-id-1', 'field-ui-1'],
|
||||
]),
|
||||
viewIdToUniversalIdentifierMap: new Map([
|
||||
['view-id-1', 'view-ui-1'],
|
||||
]),
|
||||
viewFieldGroupIdToUniversalIdentifierMap: new Map(),
|
||||
}),
|
||||
),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nullable relations', () => {
|
||||
it('should resolve a nullable foreign key to null when its id is not defined', () => {
|
||||
const result = resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'viewField',
|
||||
entity: {
|
||||
id: 'view-field-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
viewFieldGroupId: null,
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
fieldMetadataIdToUniversalIdentifierMap: new Map([
|
||||
['field-id-1', 'field-ui-1'],
|
||||
]),
|
||||
viewIdToUniversalIdentifierMap: new Map([['view-id-1', 'view-ui-1']]),
|
||||
viewFieldGroupIdToUniversalIdentifierMap: new Map(),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
applicationUniversalIdentifier: 'app-ui-1',
|
||||
fieldMetadataUniversalIdentifier: 'field-ui-1',
|
||||
viewUniversalIdentifier: 'view-ui-1',
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when a nullable foreign key has an id that is missing from the map', () => {
|
||||
expect(() =>
|
||||
resolveManyToOneRelationIdsToUniversalIdentifiers(
|
||||
buildArgs({
|
||||
metadataName: 'viewField',
|
||||
entity: {
|
||||
id: 'view-field-id-1',
|
||||
applicationId: 'app-id-1',
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
viewFieldGroupId: 'non-existent-view-field-group-id',
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap: new Map([
|
||||
['app-id-1', 'app-ui-1'],
|
||||
]),
|
||||
fieldMetadataIdToUniversalIdentifierMap: new Map([
|
||||
['field-id-1', 'field-ui-1'],
|
||||
]),
|
||||
viewIdToUniversalIdentifierMap: new Map([
|
||||
['view-id-1', 'view-ui-1'],
|
||||
]),
|
||||
viewFieldGroupIdToUniversalIdentifierMap: new Map(),
|
||||
}),
|
||||
),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
|
||||
type ManyToOneRelationsConfig<T extends AllMetadataName> =
|
||||
(typeof ALL_MANY_TO_ONE_METADATA_RELATIONS)[T];
|
||||
|
||||
// Mirrors ResolvedForeignKeyIds from resolveUniversalRelationIdentifiersToIds but
|
||||
// keyed on universalForeignKey, so the resolved record is the many-to-one part of a
|
||||
// flat entity (plus the always-present applicationUniversalIdentifier).
|
||||
export type ResolvedManyToOneRelationUniversalIdentifiers<
|
||||
T extends AllMetadataName,
|
||||
> = {
|
||||
[K in keyof ManyToOneRelationsConfig<T> as ManyToOneRelationsConfig<T>[K] extends {
|
||||
universalForeignKey: infer UniversalForeignKey extends string;
|
||||
}
|
||||
? UniversalForeignKey
|
||||
: never]: ManyToOneRelationsConfig<T>[K] extends { isNullable: true }
|
||||
? string | null
|
||||
: string;
|
||||
} & {
|
||||
applicationUniversalIdentifier: string;
|
||||
};
|
||||
|
||||
export const resolveManyToOneRelationIdsToUniversalIdentifiers = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
metadataName,
|
||||
entity,
|
||||
...idToUniversalIdentifierMaps
|
||||
}: {
|
||||
metadataName: T;
|
||||
} & FromEntityToFlatEntityArgs<T>): ResolvedManyToOneRelationUniversalIdentifiers<T> => {
|
||||
const readEntityForeignKey = (
|
||||
propertyName: string,
|
||||
): string | null | undefined =>
|
||||
entity[propertyName as keyof typeof entity] as string | null | undefined;
|
||||
|
||||
const entityId = readEntityForeignKey('id');
|
||||
const resolvedUniversalIdentifierByForeignKey: Record<string, string | null> =
|
||||
{};
|
||||
|
||||
const applicationId = readEntityForeignKey('applicationId');
|
||||
const applicationUniversalIdentifier = isDefined(applicationId)
|
||||
? idToUniversalIdentifierMaps.applicationIdToUniversalIdentifierMap.get(
|
||||
applicationId,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${applicationId} not found for ${metadataName} ${entityId}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
resolvedUniversalIdentifierByForeignKey.applicationUniversalIdentifier =
|
||||
applicationUniversalIdentifier;
|
||||
|
||||
const relationEntries = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
|
||||
|
||||
for (const relationPropertyName of Object.keys(relationEntries)) {
|
||||
const relationEntry = relationEntries[
|
||||
relationPropertyName as keyof typeof relationEntries
|
||||
] as {
|
||||
foreignKey: string;
|
||||
metadataName: AllMetadataName;
|
||||
isNullable: boolean;
|
||||
universalForeignKey: string;
|
||||
} | null;
|
||||
|
||||
if (!isDefined(relationEntry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const {
|
||||
foreignKey,
|
||||
metadataName: targetMetadataName,
|
||||
universalForeignKey,
|
||||
isNullable,
|
||||
} = relationEntry;
|
||||
const foreignKeyId = readEntityForeignKey(foreignKey);
|
||||
|
||||
if (!isDefined(foreignKeyId)) {
|
||||
if (isNullable) {
|
||||
resolvedUniversalIdentifierByForeignKey[universalForeignKey] = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new FlatEntityMapsException(
|
||||
`Missing non-nullable foreign key ${foreignKey} on ${metadataName} ${entityId} (relation to ${targetMetadataName})`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
);
|
||||
}
|
||||
|
||||
const mapKey = `${targetMetadataName}IdToUniversalIdentifierMap`;
|
||||
const targetIdToUniversalIdentifierMap = idToUniversalIdentifierMaps[
|
||||
mapKey as keyof typeof idToUniversalIdentifierMaps
|
||||
] as unknown as Map<string, string> | undefined;
|
||||
|
||||
if (!isDefined(targetIdToUniversalIdentifierMap)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Missing ${mapKey} when resolving ${metadataName} ${entityId}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const universalIdentifier =
|
||||
targetIdToUniversalIdentifierMap.get(foreignKeyId);
|
||||
|
||||
if (!isDefined(universalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`${capitalize(targetMetadataName)} with id ${foreignKeyId} not found for ${metadataName} ${entityId}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
resolvedUniversalIdentifierByForeignKey[universalForeignKey] =
|
||||
universalIdentifier;
|
||||
}
|
||||
|
||||
return resolvedUniversalIdentifierByForeignKey as ResolvedManyToOneRelationUniversalIdentifiers<T>;
|
||||
};
|
||||
-1
@@ -400,7 +400,6 @@ exports[`syncApplication should delete old field and create equivalent one when
|
||||
"isSystem": false,
|
||||
"isSystemSideEffect": false,
|
||||
"isUIEditable": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"kanbanAggregateOperationViewUniversalIdentifiers": [],
|
||||
|
||||
Reference in New Issue
Block a user