Migrate Views-xxx Index Field Object Skill to be fully universal ( all actions and metadata runner and builder ) + all metadata update actions runner (#17687)
# What this PR does Overall naming `universal` versus `flat` is not always the most updated and so on Will make a big cleaning tour after I've finished the whole migration Migrating all `view` and ( filter fields etc ) `field` `object` `index` to the universal pattern on all `services`, `builder` and `runner` levels ## Universal and flat optimistic tooling `addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow` and its delete counterpart maintain the consistency of `UniversalFlatEntityMaps` when an entity is created or removed. Beyond inserting/removing the entity from its own maps, they walk through `ALL_UNIVERSAL_METADATA_RELATIONS` to update the **aggregator arrays** on related parent entities — the add appends the new entity's `universalIdentifier` to the parent's aggregator (e.g. a new viewField's identifier gets appended to its parent view's `viewFieldUniversalIdentifiers`), and the delete filters it out. This keeps the maps in sync so that diff computations and relation lookups remain accurate throughout the migration building process. ## ALL_UNIVERSAL_METADATA_RELATIONS `ALL_UNIVERSAL_METADATA_RELATIONS` is the universal counterpart of `ALL_METADATA_RELATIONS`. It maps each metadata entity to its many-to-one and one-to-many relations using universal foreign keys (`*UniversalIdentifier`) instead of database IDs (`*Id`). This allows migration actions to reference related entities in a workspace-agnostic way. Relations that are workspace-specific (e.g. `workspace`, `dataSource`, `userWorkspace`) are set to `null` and skipped during resolution. ## `workspaceMigrationCreateIdEnrichment` Reserved to API metadata ( will be able to validate at app installation lvl ) - Workspace migration `create` actions now carry an optional `id` (and `fieldIdByUniversalIdentifier` for object/field actions) so that caller-provided IDs flow through the entire build-validate-run pipeline. - New `enrichCreateWorkspaceMigrationActionsWithIds` utility resolves `universalIdentifier → id` mappings after the builder runs and injects them into the migration actions before the runner persists entities. - Runner action handlers use the provided IDs instead of generating new UUIDs, enabling deterministic entity creation for synchronization workflows. ## `resolveUniversalUpdateRelationIdentifiersToIds` `resolveUniversalUpdateRelationIdentifiersToIds` converts universal identifiers (workspace-agnostic, stable keys) in a migration update payload into concrete database UUIDs, so the update can be applied to a specific workspace. It iterates over the many-to-one relations defined in `ALL_UNIVERSAL_METADATA_RELATIONS` for the given entity type, replaces each `*UniversalIdentifier` property with its corresponding `*Id` by looking up the target entity in `allFlatEntityMaps`, and throws if a non-null identifier can't be resolved. Used by all `update` action handlers in `transpileUniversalActionToFlatAction`, avoiding duplicated resolution logic across handlers. ## What this PR does not - Migrating twenty-standard declaration to universal - Migrating all the inputs transpilers to universal - Migrating all metadata to be fully universal ( we still need to de-scope the type of all of them and refactor their validator very close ) --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+297
@@ -0,0 +1,297 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should match snapshot 1`] = `
|
||||
{
|
||||
"agent": {
|
||||
"propertiesToCompare": [
|
||||
"name",
|
||||
"label",
|
||||
"icon",
|
||||
"description",
|
||||
"prompt",
|
||||
"modelId",
|
||||
"responseFormat",
|
||||
"modelConfiguration",
|
||||
"evaluationInputs",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"responseFormat",
|
||||
"modelConfiguration",
|
||||
"evaluationInputs",
|
||||
],
|
||||
},
|
||||
"commandMenuItem": {
|
||||
"propertiesToCompare": [
|
||||
"label",
|
||||
"icon",
|
||||
"isPinned",
|
||||
"availabilityType",
|
||||
"availabilityObjectMetadataUniversalIdentifier",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"fieldMetadata": {
|
||||
"propertiesToCompare": [
|
||||
"defaultValue",
|
||||
"description",
|
||||
"icon",
|
||||
"isActive",
|
||||
"isLabelSyncedWithName",
|
||||
"isUnique",
|
||||
"label",
|
||||
"name",
|
||||
"options",
|
||||
"standardOverrides",
|
||||
"universalSettings",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"defaultValue",
|
||||
"options",
|
||||
"standardOverrides",
|
||||
"universalSettings",
|
||||
],
|
||||
},
|
||||
"frontComponent": {
|
||||
"propertiesToCompare": [
|
||||
"name",
|
||||
"description",
|
||||
"builtComponentChecksum",
|
||||
"sourceComponentPath",
|
||||
"builtComponentPath",
|
||||
"componentName",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"index": {
|
||||
"propertiesToCompare": [
|
||||
"indexType",
|
||||
"indexWhereClause",
|
||||
"flatIndexFieldMetadatas",
|
||||
"isUnique",
|
||||
"name",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"flatIndexFieldMetadatas",
|
||||
],
|
||||
},
|
||||
"logicFunction": {
|
||||
"propertiesToCompare": [
|
||||
"name",
|
||||
"description",
|
||||
"timeoutSeconds",
|
||||
"checksum",
|
||||
"sourceHandlerPath",
|
||||
"handlerName",
|
||||
"toolInputSchema",
|
||||
"isTool",
|
||||
"deletedAt",
|
||||
"cronTriggerSettings",
|
||||
"databaseEventTriggerSettings",
|
||||
"httpRouteTriggerSettings",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"toolInputSchema",
|
||||
"cronTriggerSettings",
|
||||
"databaseEventTriggerSettings",
|
||||
"httpRouteTriggerSettings",
|
||||
],
|
||||
},
|
||||
"navigationMenuItem": {
|
||||
"propertiesToCompare": [
|
||||
"position",
|
||||
"folderUniversalIdentifier",
|
||||
"name",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"objectMetadata": {
|
||||
"propertiesToCompare": [
|
||||
"description",
|
||||
"icon",
|
||||
"isActive",
|
||||
"isLabelSyncedWithName",
|
||||
"labelPlural",
|
||||
"labelSingular",
|
||||
"namePlural",
|
||||
"nameSingular",
|
||||
"labelIdentifierFieldMetadataUniversalIdentifier",
|
||||
"standardOverrides",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"standardOverrides",
|
||||
],
|
||||
},
|
||||
"pageLayout": {
|
||||
"propertiesToCompare": [
|
||||
"name",
|
||||
"type",
|
||||
"objectMetadataUniversalIdentifier",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"pageLayoutTab": {
|
||||
"propertiesToCompare": [
|
||||
"title",
|
||||
"position",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"pageLayoutWidget": {
|
||||
"propertiesToCompare": [
|
||||
"title",
|
||||
"type",
|
||||
"objectMetadataUniversalIdentifier",
|
||||
"gridPosition",
|
||||
"position",
|
||||
"universalConfiguration",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"gridPosition",
|
||||
"position",
|
||||
"universalConfiguration",
|
||||
],
|
||||
},
|
||||
"role": {
|
||||
"propertiesToCompare": [
|
||||
"label",
|
||||
"description",
|
||||
"icon",
|
||||
"canUpdateAllSettings",
|
||||
"canAccessAllTools",
|
||||
"canReadAllObjectRecords",
|
||||
"canUpdateAllObjectRecords",
|
||||
"canSoftDeleteAllObjectRecords",
|
||||
"canDestroyAllObjectRecords",
|
||||
"canBeAssignedToUsers",
|
||||
"canBeAssignedToAgents",
|
||||
"canBeAssignedToApiKeys",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"roleTarget": {
|
||||
"propertiesToCompare": [
|
||||
"roleUniversalIdentifier",
|
||||
"userWorkspaceId",
|
||||
"apiKeyId",
|
||||
"agentId",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"rowLevelPermissionPredicate": {
|
||||
"propertiesToCompare": [
|
||||
"fieldMetadataUniversalIdentifier",
|
||||
"operand",
|
||||
"value",
|
||||
"rowLevelPermissionPredicateGroupUniversalIdentifier",
|
||||
"positionInRowLevelPermissionPredicateGroup",
|
||||
"subFieldName",
|
||||
"workspaceMemberFieldMetadataUniversalIdentifier",
|
||||
"workspaceMemberSubFieldName",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"value",
|
||||
],
|
||||
},
|
||||
"rowLevelPermissionPredicateGroup": {
|
||||
"propertiesToCompare": [
|
||||
"logicalOperator",
|
||||
"positionInRowLevelPermissionPredicateGroup",
|
||||
"parentRowLevelPermissionPredicateGroupUniversalIdentifier",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"skill": {
|
||||
"propertiesToCompare": [
|
||||
"name",
|
||||
"label",
|
||||
"icon",
|
||||
"description",
|
||||
"content",
|
||||
"isActive",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"view": {
|
||||
"propertiesToCompare": [
|
||||
"key",
|
||||
"deletedAt",
|
||||
"createdByUserWorkspaceId",
|
||||
"name",
|
||||
"type",
|
||||
"icon",
|
||||
"position",
|
||||
"isCompact",
|
||||
"openRecordIn",
|
||||
"kanbanAggregateOperation",
|
||||
"kanbanAggregateOperationFieldMetadataUniversalIdentifier",
|
||||
"anyFieldFilterValue",
|
||||
"calendarLayout",
|
||||
"calendarFieldMetadataUniversalIdentifier",
|
||||
"visibility",
|
||||
"mainGroupByFieldMetadataUniversalIdentifier",
|
||||
"shouldHideEmptyGroups",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"viewField": {
|
||||
"propertiesToCompare": [
|
||||
"isVisible",
|
||||
"size",
|
||||
"position",
|
||||
"aggregateOperation",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"viewFilter": {
|
||||
"propertiesToCompare": [
|
||||
"viewUniversalIdentifier",
|
||||
"deletedAt",
|
||||
"fieldMetadataUniversalIdentifier",
|
||||
"operand",
|
||||
"value",
|
||||
"viewFilterGroupUniversalIdentifier",
|
||||
"positionInViewFilterGroup",
|
||||
"subFieldName",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"value",
|
||||
],
|
||||
},
|
||||
"viewFilterGroup": {
|
||||
"propertiesToCompare": [
|
||||
"viewUniversalIdentifier",
|
||||
"deletedAt",
|
||||
"parentViewFilterGroupUniversalIdentifier",
|
||||
"logicalOperator",
|
||||
"positionInViewFilterGroup",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"viewGroup": {
|
||||
"propertiesToCompare": [
|
||||
"isVisible",
|
||||
"fieldValue",
|
||||
"position",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"webhook": {
|
||||
"propertiesToCompare": [
|
||||
"targetUrl",
|
||||
"operations",
|
||||
"description",
|
||||
"secret",
|
||||
],
|
||||
"propertiesToStringify": [
|
||||
"operations",
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-universal-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
|
||||
describe('ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY', () => {
|
||||
it('should match snapshot', () => {
|
||||
expect(
|
||||
Object.keys(
|
||||
ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY,
|
||||
),
|
||||
).toMatchObject(Object.values(ALL_METADATA_NAME));
|
||||
expect(
|
||||
ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { type MetadataManyToOneJoinColumn } from 'src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type';
|
||||
import { type AllJsonbPropertiesWithSerializedPropertiesForMetadataName } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-jsonb-properties-with-serialized-relation-by-metadata-name.constant';
|
||||
import { type ToUniversalForeignKey } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant';
|
||||
import { type ExtractJsonbProperties } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/extract-jsonb-properties.type';
|
||||
import { type UniversalFlatEntityExtraProperties } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
type HasObjectInUnion<T> = T extends unknown
|
||||
? T extends object
|
||||
? true
|
||||
: false
|
||||
: never;
|
||||
|
||||
type MetadataEntityPropertyConfiguration<
|
||||
TMetadataName extends AllMetadataName,
|
||||
> = {
|
||||
[K in keyof Omit<
|
||||
MetadataFlatEntity<TMetadataName>,
|
||||
| Extract<
|
||||
keyof MetadataFlatEntity<TMetadataName>,
|
||||
keyof UniversalFlatEntityExtraProperties<
|
||||
MetadataEntity<TMetadataName>,
|
||||
TMetadataName
|
||||
>
|
||||
>
|
||||
| '__universal'
|
||||
>]?: {
|
||||
universalProperty: K extends AllJsonbPropertiesWithSerializedPropertiesForMetadataName<TMetadataName> &
|
||||
string
|
||||
? `universal${Capitalize<K>}`
|
||||
: K extends MetadataManyToOneJoinColumn<TMetadataName> & string
|
||||
? ToUniversalForeignKey<K>
|
||||
: undefined;
|
||||
toStringify: K extends ExtractJsonbProperties<MetadataEntity<TMetadataName>>
|
||||
? true
|
||||
: K extends keyof MetadataEntity<TMetadataName>
|
||||
? HasObjectInUnion<MetadataEntity<TMetadataName>[K]>
|
||||
: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
fieldMetadata: {
|
||||
defaultValue: { toStringify: true, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
isActive: { toStringify: false, universalProperty: undefined },
|
||||
isLabelSyncedWithName: { toStringify: false, universalProperty: undefined },
|
||||
isUnique: { toStringify: false, universalProperty: undefined },
|
||||
label: { toStringify: false, universalProperty: undefined },
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
options: { toStringify: true, universalProperty: undefined },
|
||||
standardOverrides: { toStringify: true, universalProperty: undefined },
|
||||
settings: { toStringify: true, universalProperty: 'universalSettings' },
|
||||
},
|
||||
objectMetadata: {
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
isActive: { toStringify: false, universalProperty: undefined },
|
||||
isLabelSyncedWithName: { toStringify: false, universalProperty: undefined },
|
||||
labelPlural: { toStringify: false, universalProperty: undefined },
|
||||
labelSingular: { toStringify: false, universalProperty: undefined },
|
||||
namePlural: { toStringify: false, universalProperty: undefined },
|
||||
nameSingular: { toStringify: false, universalProperty: undefined },
|
||||
labelIdentifierFieldMetadataId: {
|
||||
toStringify: false,
|
||||
// @ts-expect-error remove once https://github.com/twentyhq/core-team-issues/issues/2172 has been resolved
|
||||
universalProperty: 'labelIdentifierFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
standardOverrides: { toStringify: true, universalProperty: undefined },
|
||||
},
|
||||
view: {
|
||||
key: { toStringify: false, universalProperty: undefined },
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
createdByUserWorkspaceId: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
type: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
position: { toStringify: false, universalProperty: undefined },
|
||||
isCompact: { toStringify: false, universalProperty: undefined },
|
||||
openRecordIn: { toStringify: false, universalProperty: undefined },
|
||||
kanbanAggregateOperation: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
kanbanAggregateOperationFieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty:
|
||||
'kanbanAggregateOperationFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
anyFieldFilterValue: { toStringify: false, universalProperty: undefined },
|
||||
calendarLayout: { toStringify: false, universalProperty: undefined },
|
||||
calendarFieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'calendarFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
visibility: { toStringify: false, universalProperty: undefined },
|
||||
mainGroupByFieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'mainGroupByFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
shouldHideEmptyGroups: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
viewField: {
|
||||
isVisible: { toStringify: false, universalProperty: undefined },
|
||||
size: { toStringify: false, universalProperty: undefined },
|
||||
position: { toStringify: false, universalProperty: undefined },
|
||||
aggregateOperation: { toStringify: false, universalProperty: undefined },
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
viewGroup: {
|
||||
isVisible: { toStringify: false, universalProperty: undefined },
|
||||
fieldValue: { toStringify: false, universalProperty: undefined },
|
||||
position: { toStringify: false, universalProperty: undefined },
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
index: {
|
||||
indexType: { toStringify: false, universalProperty: undefined },
|
||||
indexWhereClause: { toStringify: false, universalProperty: undefined },
|
||||
flatIndexFieldMetadatas: {
|
||||
toStringify: true,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
isUnique: { toStringify: false, universalProperty: undefined },
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
logicFunction: {
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
timeoutSeconds: { toStringify: false, universalProperty: undefined },
|
||||
checksum: { toStringify: false, universalProperty: undefined },
|
||||
sourceHandlerPath: { toStringify: false, universalProperty: undefined },
|
||||
handlerName: { toStringify: false, universalProperty: undefined },
|
||||
toolInputSchema: { toStringify: true, universalProperty: undefined },
|
||||
isTool: { toStringify: false, universalProperty: undefined },
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
cronTriggerSettings: { toStringify: true, universalProperty: undefined },
|
||||
databaseEventTriggerSettings: {
|
||||
toStringify: true,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
httpRouteTriggerSettings: {
|
||||
toStringify: true,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
},
|
||||
viewFilter: {
|
||||
viewId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'viewUniversalIdentifier',
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
fieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'fieldMetadataUniversalIdentifier',
|
||||
},
|
||||
operand: { toStringify: false, universalProperty: undefined },
|
||||
value: { toStringify: true, universalProperty: undefined },
|
||||
viewFilterGroupId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'viewFilterGroupUniversalIdentifier',
|
||||
},
|
||||
positionInViewFilterGroup: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
subFieldName: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
role: {
|
||||
label: { toStringify: false, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
canUpdateAllSettings: { toStringify: false, universalProperty: undefined },
|
||||
canAccessAllTools: { toStringify: false, universalProperty: undefined },
|
||||
canReadAllObjectRecords: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
canUpdateAllObjectRecords: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
canSoftDeleteAllObjectRecords: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
canDestroyAllObjectRecords: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
canBeAssignedToUsers: { toStringify: false, universalProperty: undefined },
|
||||
canBeAssignedToAgents: { toStringify: false, universalProperty: undefined },
|
||||
canBeAssignedToApiKeys: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
},
|
||||
roleTarget: {
|
||||
roleId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'roleUniversalIdentifier',
|
||||
},
|
||||
userWorkspaceId: { toStringify: false, universalProperty: undefined },
|
||||
apiKeyId: { toStringify: false, universalProperty: undefined },
|
||||
agentId: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
agent: {
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
label: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
prompt: { toStringify: false, universalProperty: undefined },
|
||||
modelId: { toStringify: false, universalProperty: undefined },
|
||||
responseFormat: { toStringify: true, universalProperty: undefined },
|
||||
modelConfiguration: { toStringify: true, universalProperty: undefined },
|
||||
evaluationInputs: { toStringify: true, universalProperty: undefined },
|
||||
},
|
||||
pageLayout: {
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
type: { toStringify: false, universalProperty: undefined },
|
||||
objectMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'objectMetadataUniversalIdentifier',
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
pageLayoutWidget: {
|
||||
title: { toStringify: false, universalProperty: undefined },
|
||||
type: { toStringify: false, universalProperty: undefined },
|
||||
objectMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'objectMetadataUniversalIdentifier',
|
||||
},
|
||||
gridPosition: { toStringify: true, universalProperty: undefined },
|
||||
position: { toStringify: true, universalProperty: undefined },
|
||||
configuration: {
|
||||
toStringify: true,
|
||||
universalProperty: 'universalConfiguration',
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
pageLayoutTab: {
|
||||
title: { toStringify: false, universalProperty: undefined },
|
||||
position: { toStringify: false, universalProperty: undefined },
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
skill: {
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
label: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
content: { toStringify: false, universalProperty: undefined },
|
||||
isActive: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
commandMenuItem: {
|
||||
label: { toStringify: false, universalProperty: undefined },
|
||||
icon: { toStringify: false, universalProperty: undefined },
|
||||
isPinned: { toStringify: false, universalProperty: undefined },
|
||||
availabilityType: { toStringify: false, universalProperty: undefined },
|
||||
availabilityObjectMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'availabilityObjectMetadataUniversalIdentifier',
|
||||
},
|
||||
},
|
||||
navigationMenuItem: {
|
||||
position: { toStringify: false, universalProperty: undefined },
|
||||
folderId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'folderUniversalIdentifier',
|
||||
},
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
fieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'fieldMetadataUniversalIdentifier',
|
||||
},
|
||||
operand: { toStringify: false, universalProperty: undefined },
|
||||
value: { toStringify: true, universalProperty: undefined },
|
||||
rowLevelPermissionPredicateGroupId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'rowLevelPermissionPredicateGroupUniversalIdentifier',
|
||||
},
|
||||
positionInRowLevelPermissionPredicateGroup: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
subFieldName: { toStringify: false, universalProperty: undefined },
|
||||
workspaceMemberFieldMetadataId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'workspaceMemberFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
workspaceMemberSubFieldName: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
logicalOperator: { toStringify: false, universalProperty: undefined },
|
||||
positionInRowLevelPermissionPredicateGroup: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
parentRowLevelPermissionPredicateGroupId: {
|
||||
toStringify: false,
|
||||
universalProperty:
|
||||
'parentRowLevelPermissionPredicateGroupUniversalIdentifier',
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
viewFilterGroup: {
|
||||
viewId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'viewUniversalIdentifier',
|
||||
},
|
||||
deletedAt: { toStringify: false, universalProperty: undefined },
|
||||
parentViewFilterGroupId: {
|
||||
toStringify: false,
|
||||
universalProperty: 'parentViewFilterGroupUniversalIdentifier',
|
||||
},
|
||||
logicalOperator: { toStringify: false, universalProperty: undefined },
|
||||
positionInViewFilterGroup: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
},
|
||||
frontComponent: {
|
||||
name: { toStringify: false, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
builtComponentChecksum: {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
sourceComponentPath: { toStringify: false, universalProperty: undefined },
|
||||
builtComponentPath: { toStringify: false, universalProperty: undefined },
|
||||
componentName: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
webhook: {
|
||||
targetUrl: { toStringify: false, universalProperty: undefined },
|
||||
operations: { toStringify: true, universalProperty: undefined },
|
||||
description: { toStringify: false, universalProperty: undefined },
|
||||
secret: { toStringify: false, universalProperty: undefined },
|
||||
},
|
||||
} as const satisfies {
|
||||
[P in AllMetadataName]: MetadataEntityPropertyConfiguration<P>;
|
||||
};
|
||||
|
||||
export type MetadataEntityPropertyName<T extends AllMetadataName> =
|
||||
keyof (typeof ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME)[T];
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { FLAT_AGENT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-agent/constants/flat-agent-editable-properties.constant';
|
||||
import { FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-command-menu-item/constants/flat-command-menu-item-editable-properties.constant';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { FLAT_FIELD_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-editable-properties.constant';
|
||||
import { FLAT_FRONT_COMPONENT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-front-component/constants/flat-front-component-editable-properties.constant';
|
||||
import { FLAT_NAVIGATION_MENU_ITEM_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-navigation-menu-item/constants/flat-navigation-menu-item-editable-properties.constant';
|
||||
import { FLAT_OBJECT_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-object-metadata/constants/flat-object-metadata-editable-properties.constant';
|
||||
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
|
||||
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
|
||||
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
|
||||
import { FLAT_ROLE_TARGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role-target/constants/flat-role-target-editable-properties.constant';
|
||||
import { FLAT_ROLE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role/constants/flat-role-editable-properties.constant';
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
|
||||
import { FLAT_SKILL_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-skill/constants/flat-skill-editable-properties.constant';
|
||||
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
|
||||
import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter-group/constants/flat-view-filter-group-editable-properties.constant';
|
||||
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
|
||||
import { FLAT_VIEW_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-group/constants/flat-view-group-editable-properties.constant';
|
||||
import { FLAT_VIEW_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view/constants/flat-view-editable-properties.constant';
|
||||
import { FLAT_LOGIC_FUNCTION_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/logic-function/constants/flat-logic-function-editable-properties.constant';
|
||||
|
||||
type OneFlatEntityConfiguration<T extends AllMetadataName> = {
|
||||
propertiesToCompare: (keyof MetadataFlatEntity<T>)[];
|
||||
propertiesToStringify: (keyof MetadataFlatEntity<T>)[];
|
||||
};
|
||||
export const ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY = {
|
||||
fieldMetadata: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_FIELD_METADATA_EDITABLE_PROPERTIES.custom,
|
||||
'standardOverrides',
|
||||
],
|
||||
propertiesToStringify: [
|
||||
'options',
|
||||
'settings',
|
||||
'standardOverrides',
|
||||
'defaultValue',
|
||||
],
|
||||
},
|
||||
objectMetadata: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_OBJECT_METADATA_EDITABLE_PROPERTIES.custom,
|
||||
'standardOverrides',
|
||||
],
|
||||
propertiesToStringify: ['standardOverrides'],
|
||||
},
|
||||
view: {
|
||||
propertiesToCompare: [
|
||||
'key',
|
||||
'deletedAt',
|
||||
'createdByUserWorkspaceId',
|
||||
...FLAT_VIEW_EDITABLE_PROPERTIES,
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
viewField: {
|
||||
propertiesToCompare: [...FLAT_VIEW_FIELD_EDITABLE_PROPERTIES, 'deletedAt'],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
viewGroup: {
|
||||
propertiesToCompare: [...FLAT_VIEW_GROUP_EDITABLE_PROPERTIES, 'deletedAt'],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
index: {
|
||||
propertiesToCompare: [
|
||||
'indexType',
|
||||
'indexWhereClause',
|
||||
'flatIndexFieldMetadatas',
|
||||
'isUnique',
|
||||
'name',
|
||||
],
|
||||
propertiesToStringify: ['flatIndexFieldMetadatas'],
|
||||
},
|
||||
logicFunction: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_LOGIC_FUNCTION_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: ['toolInputSchema'],
|
||||
},
|
||||
viewFilter: {
|
||||
propertiesToCompare: [
|
||||
'viewId',
|
||||
'deletedAt',
|
||||
...FLAT_VIEW_FILTER_EDITABLE_PROPERTIES,
|
||||
],
|
||||
propertiesToStringify: ['value'],
|
||||
},
|
||||
role: {
|
||||
propertiesToCompare: [...FLAT_ROLE_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
roleTarget: {
|
||||
propertiesToCompare: [...FLAT_ROLE_TARGET_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
agent: {
|
||||
propertiesToCompare: [...FLAT_AGENT_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [
|
||||
'responseFormat',
|
||||
'modelConfiguration',
|
||||
'evaluationInputs',
|
||||
],
|
||||
},
|
||||
pageLayout: {
|
||||
propertiesToCompare: [...FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES, 'deletedAt'],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
pageLayoutWidget: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: ['gridPosition', 'configuration'],
|
||||
},
|
||||
pageLayoutTab: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
skill: {
|
||||
propertiesToCompare: [...FLAT_SKILL_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
commandMenuItem: {
|
||||
propertiesToCompare: [...FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
navigationMenuItem: {
|
||||
propertiesToCompare: [...FLAT_NAVIGATION_MENU_ITEM_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: ['value'],
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
viewFilterGroup: {
|
||||
propertiesToCompare: [
|
||||
'viewId',
|
||||
'deletedAt',
|
||||
...FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES,
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
frontComponent: {
|
||||
propertiesToCompare: [...FLAT_FRONT_COMPONENT_EDITABLE_PROPERTIES],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
webhook: {
|
||||
propertiesToCompare: ['targetUrl', 'operations', 'description', 'secret'],
|
||||
propertiesToStringify: ['operations'],
|
||||
},
|
||||
} as const satisfies {
|
||||
[P in AllMetadataName]: OneFlatEntityConfiguration<P>;
|
||||
};
|
||||
+28
-13
@@ -9,8 +9,9 @@ import { type ExtractEntityOneToManyEntityRelationProperties } from 'src/engine/
|
||||
import { type FromMetadataEntityToMetadataName } from 'src/engine/metadata-modules/flat-entity/types/from-metadata-entity-to-metadata-name.type';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { type AllJsonbPropertiesWithSerializedPropertiesForMetadataName } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-jsonb-properties-with-serialized-relation-by-metadata-name.constant';
|
||||
|
||||
export type ManyToOneRelationValue<
|
||||
export type MetadataManyToOneRelationConfiguration<
|
||||
TSourceMetadataName extends AllMetadataName,
|
||||
TRelationProperty extends ExtractEntityManyToOneEntityRelationProperties<
|
||||
MetadataEntity<TSourceMetadataName>
|
||||
@@ -24,7 +25,6 @@ export type ManyToOneRelationValue<
|
||||
flatEntityForeignKeyAggregator:
|
||||
| keyof AddSuffixToEntityOneToManyProperties<TTargetEntity, 'ids'>
|
||||
| null;
|
||||
// Note: In the best of the world should not be nullable, entities should always declare inverside keys
|
||||
foreignKey: ExtractPropertiesThatEndsWithId<
|
||||
MetadataEntity<TSourceMetadataName>,
|
||||
'id' | 'workspaceId'
|
||||
@@ -33,35 +33,44 @@ export type ManyToOneRelationValue<
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
: null;
|
||||
: // Note: In the best of the world should not be nullable, entities should always declare inverside keys
|
||||
null;
|
||||
|
||||
type OneToManyRelationValue<
|
||||
TSourceMetadataName extends AllMetadataName,
|
||||
TRelationProperty extends ExtractEntityOneToManyEntityRelationProperties<
|
||||
MetadataEntity<TSourceMetadataName>
|
||||
>,
|
||||
> =
|
||||
MetadataEntity<TSourceMetadataName>[TRelationProperty] extends Relation<
|
||||
(infer TTargetEntity extends SyncableEntity)[]
|
||||
>
|
||||
? {
|
||||
metadataName: FromMetadataEntityToMetadataName<TTargetEntity>;
|
||||
}
|
||||
: null;
|
||||
> = MetadataEntity<TSourceMetadataName>[TRelationProperty] extends (infer TTargetEntity extends
|
||||
SyncableEntity)[]
|
||||
? {
|
||||
metadataName: FromMetadataEntityToMetadataName<TTargetEntity>;
|
||||
}
|
||||
: null;
|
||||
|
||||
type MetadataRelationsProperties = {
|
||||
[TSourceMetadataName in AllMetadataName]: {
|
||||
manyToOne: {
|
||||
[TRelationProperty in ExtractEntityManyToOneEntityRelationProperties<
|
||||
MetadataEntity<TSourceMetadataName>
|
||||
>]: ManyToOneRelationValue<TSourceMetadataName, TRelationProperty>;
|
||||
>]: MetadataManyToOneRelationConfiguration<
|
||||
TSourceMetadataName,
|
||||
TRelationProperty
|
||||
>;
|
||||
};
|
||||
oneToMany: {
|
||||
[TRelationProperty in ExtractEntityOneToManyEntityRelationProperties<
|
||||
MetadataEntity<TSourceMetadataName>
|
||||
>]: OneToManyRelationValue<TSourceMetadataName, TRelationProperty>;
|
||||
};
|
||||
};
|
||||
} & ([
|
||||
AllJsonbPropertiesWithSerializedPropertiesForMetadataName<TSourceMetadataName>,
|
||||
] extends [never]
|
||||
? // eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
{}
|
||||
: {
|
||||
serializedRelations: Partial<Record<AllMetadataName, true>>;
|
||||
});
|
||||
};
|
||||
|
||||
export const ALL_METADATA_RELATIONS = {
|
||||
@@ -156,6 +165,9 @@ export const ALL_METADATA_RELATIONS = {
|
||||
calendarViews: { metadataName: 'view' },
|
||||
mainGroupByFieldMetadataViews: { metadataName: 'view' },
|
||||
},
|
||||
serializedRelations: {
|
||||
fieldMetadata: true,
|
||||
},
|
||||
},
|
||||
objectMetadata: {
|
||||
manyToOne: {
|
||||
@@ -378,6 +390,9 @@ export const ALL_METADATA_RELATIONS = {
|
||||
application: null,
|
||||
},
|
||||
oneToMany: {},
|
||||
serializedRelations: {
|
||||
fieldMetadata: true,
|
||||
},
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
manyToOne: {
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ type MetadataRequiredForValidation = {
|
||||
};
|
||||
};
|
||||
|
||||
// TODO deprecate in favor of ALL_METADATA_RELATIONS
|
||||
export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
fieldMetadata: {
|
||||
objectMetadata: true,
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
ALL_METADATA_NAME,
|
||||
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 MetadataUniversalFlatEntityPropertiesToCompare } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-properties-to-compare.type';
|
||||
import { type MetadataUniversalFlatEntityPropertiesToStringify } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-properties-to-stringify.type';
|
||||
|
||||
type UniversalFlatEntityPropertiesToCompareAndStringify<
|
||||
T extends AllMetadataName,
|
||||
> = {
|
||||
propertiesToCompare: MetadataUniversalFlatEntityPropertiesToCompare<T>[];
|
||||
propertiesToStringify: MetadataUniversalFlatEntityPropertiesToStringify<T>[];
|
||||
};
|
||||
const computeUniversalFlatEntityPropertiesToCompareAndStringify = <
|
||||
T extends AllMetadataName,
|
||||
>(
|
||||
metadataName: T,
|
||||
): UniversalFlatEntityPropertiesToCompareAndStringify<T> => {
|
||||
const entries = Object.entries(
|
||||
ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME[metadataName],
|
||||
) as [
|
||||
string,
|
||||
{ universalProperty: string | undefined; toStringify: boolean },
|
||||
][];
|
||||
const accumulator: UniversalFlatEntityPropertiesToCompareAndStringify<T> = {
|
||||
propertiesToCompare: [],
|
||||
propertiesToStringify: [],
|
||||
};
|
||||
|
||||
for (const [property, configuration] of entries) {
|
||||
const comparedProperty = configuration.universalProperty ?? property;
|
||||
|
||||
accumulator.propertiesToCompare.push(
|
||||
comparedProperty as MetadataUniversalFlatEntityPropertiesToCompare<T>,
|
||||
);
|
||||
if (configuration.toStringify === true) {
|
||||
accumulator.propertiesToStringify.push(
|
||||
comparedProperty as MetadataUniversalFlatEntityPropertiesToStringify<T>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
};
|
||||
|
||||
export const ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY =
|
||||
Object.values(ALL_METADATA_NAME).reduce(
|
||||
(acc, metadataName) => ({
|
||||
...acc,
|
||||
[metadataName]:
|
||||
computeUniversalFlatEntityPropertiesToCompareAndStringify(metadataName),
|
||||
}),
|
||||
{} as {
|
||||
[P in AllMetadataName]: UniversalFlatEntityPropertiesToCompareAndStringify<P>;
|
||||
},
|
||||
);
|
||||
+2
-1
@@ -18,7 +18,8 @@ type ExpectedGenericFlatEntityInformation = {
|
||||
[P in WorkspaceMigrationActionType]: unknown;
|
||||
};
|
||||
flatEntity: SyncableFlatEntity;
|
||||
universalFlatEntity: UniversalSyncableFlatEntity;
|
||||
// TODO remove SyncableFlatEntity once every metadata has been universal migrated
|
||||
universalFlatEntity: UniversalSyncableFlatEntity | SyncableFlatEntity;
|
||||
entity: unknown;
|
||||
};
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
type HasAllProperties,
|
||||
type Equal,
|
||||
type Expect,
|
||||
} from 'twenty-shared/testing';
|
||||
|
||||
import { type FlatEntityUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-update.type';
|
||||
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type Assertions = [
|
||||
Expect<
|
||||
Equal<
|
||||
keyof FlatEntityUpdate<'fieldMetadata'>,
|
||||
| 'name'
|
||||
| 'label'
|
||||
| 'icon'
|
||||
| 'description'
|
||||
| 'isActive'
|
||||
| 'defaultValue'
|
||||
| 'standardOverrides'
|
||||
| 'options'
|
||||
| 'settings'
|
||||
| 'isUnique'
|
||||
| 'isLabelSyncedWithName'
|
||||
| 'universalSettings'
|
||||
>
|
||||
>,
|
||||
Expect<
|
||||
HasAllProperties<
|
||||
FlatEntityUpdate<'fieldMetadata'>,
|
||||
{
|
||||
universalSettings?: never;
|
||||
}
|
||||
>
|
||||
>,
|
||||
|
||||
Expect<
|
||||
Equal<
|
||||
keyof FlatEntityUpdate<'objectMetadata'>,
|
||||
| 'icon'
|
||||
| 'description'
|
||||
| 'isActive'
|
||||
| 'standardOverrides'
|
||||
| 'isLabelSyncedWithName'
|
||||
| 'nameSingular'
|
||||
| 'namePlural'
|
||||
| 'labelSingular'
|
||||
| 'labelPlural'
|
||||
| 'labelIdentifierFieldMetadataId'
|
||||
| 'labelIdentifierFieldMetadataUniversalIdentifier'
|
||||
>
|
||||
>,
|
||||
|
||||
Expect<
|
||||
HasAllProperties<
|
||||
FlatEntityUpdate<'objectMetadata'>,
|
||||
{
|
||||
labelIdentifierFieldMetadataUniversalIdentifier?: never;
|
||||
}
|
||||
>
|
||||
>,
|
||||
];
|
||||
+81
-69
@@ -1,5 +1,3 @@
|
||||
import { type AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
|
||||
import { type CommandMenuItemEntity } from 'src/engine/metadata-modules/command-menu-item/entities/command-menu-item.entity';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatAgentMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-agent-maps.type';
|
||||
import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/flat-agent.type';
|
||||
@@ -37,42 +35,34 @@ import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/f
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { type FlatWebhookMaps } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook-maps.type';
|
||||
import { type FlatWebhook } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook.type';
|
||||
import { type FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
|
||||
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { type LogicFunctionEntity } from 'src/engine/metadata-modules/logic-function/logic-function.entity';
|
||||
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { type NavigationMenuItemEntity } from 'src/engine/metadata-modules/navigation-menu-item/entities/navigation-menu-item.entity';
|
||||
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { type RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { type RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { type SkillEntity } from 'src/engine/metadata-modules/skill/entities/skill.entity';
|
||||
import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { type ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
|
||||
import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { type ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { type WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
|
||||
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatIndexMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-index-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
import { type UniversalFlatSkill } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-skill.type';
|
||||
import { type UniversalFlatViewField } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-field.type';
|
||||
import { type UniversalFlatViewFilterGroup } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-filter-group.type';
|
||||
import { type UniversalFlatViewFilter } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-filter.type';
|
||||
import { type UniversalFlatViewGroup } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-group.type';
|
||||
import { type UniversalFlatView } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view.type';
|
||||
import {
|
||||
type FlatCreateAgentAction,
|
||||
type FlatDeleteAgentAction,
|
||||
type FlatUpdateAgentAction,
|
||||
type UniversalDeleteAgentAction,
|
||||
type UniversalUpdateAgentAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/types/workspace-migration-agent-action-builder.service';
|
||||
import {
|
||||
type FlatCreateCommandMenuItemAction,
|
||||
type FlatDeleteCommandMenuItemAction,
|
||||
type FlatUpdateCommandMenuItemAction,
|
||||
type UniversalDeleteCommandMenuItemAction,
|
||||
type UniversalUpdateCommandMenuItemAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/command-menu-item/types/workspace-migration-command-menu-item-action.type';
|
||||
import {
|
||||
type FlatCreateFieldAction,
|
||||
@@ -87,24 +77,29 @@ import {
|
||||
type FlatDeleteFrontComponentAction,
|
||||
type FlatUpdateFrontComponentAction,
|
||||
type UniversalDeleteFrontComponentAction,
|
||||
type UniversalUpdateFrontComponentAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/front-component/types/workspace-migration-front-component-action.type';
|
||||
import {
|
||||
type UniversalCreateIndexAction,
|
||||
type FlatCreateIndexAction,
|
||||
type FlatDeleteIndexAction,
|
||||
type FlatUpdateIndexAction,
|
||||
type UniversalDeleteIndexAction,
|
||||
type UniversalUpdateIndexAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/index/types/workspace-migration-index-action';
|
||||
import {
|
||||
type FlatCreateLogicFunctionAction,
|
||||
type FlatDeleteLogicFunctionAction,
|
||||
type FlatUpdateLogicFunctionAction,
|
||||
type UniversalDeleteLogicFunctionAction,
|
||||
type UniversalUpdateLogicFunctionAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/logic-function/types/workspace-migration-logic-function-action.type';
|
||||
import {
|
||||
type FlatCreateNavigationMenuItemAction,
|
||||
type FlatDeleteNavigationMenuItemAction,
|
||||
type FlatUpdateNavigationMenuItemAction,
|
||||
type UniversalDeleteNavigationMenuItemAction,
|
||||
type UniversalUpdateNavigationMenuItemAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/navigation-menu-item/types/workspace-migration-navigation-menu-item-action.type';
|
||||
import {
|
||||
type FlatCreateObjectAction,
|
||||
@@ -119,84 +114,104 @@ import {
|
||||
type FlatDeletePageLayoutTabAction,
|
||||
type FlatUpdatePageLayoutTabAction,
|
||||
type UniversalDeletePageLayoutTabAction,
|
||||
type UniversalUpdatePageLayoutTabAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action.type';
|
||||
import {
|
||||
type FlatCreatePageLayoutWidgetAction,
|
||||
type FlatDeletePageLayoutWidgetAction,
|
||||
type FlatUpdatePageLayoutWidgetAction,
|
||||
type UniversalDeletePageLayoutWidgetAction,
|
||||
type UniversalUpdatePageLayoutWidgetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
|
||||
import {
|
||||
type FlatCreatePageLayoutAction,
|
||||
type FlatDeletePageLayoutAction,
|
||||
type FlatUpdatePageLayoutAction,
|
||||
type UniversalDeletePageLayoutAction,
|
||||
type UniversalUpdatePageLayoutAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout/types/workspace-migration-page-layout-action.type';
|
||||
import {
|
||||
type FlatCreateRoleTargetAction,
|
||||
type FlatDeleteRoleTargetAction,
|
||||
type FlatUpdateRoleTargetAction,
|
||||
type UniversalDeleteRoleTargetAction,
|
||||
type UniversalUpdateRoleTargetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-target/types/workspace-migration-role-target-action.type';
|
||||
import {
|
||||
type FlatCreateRoleAction,
|
||||
type FlatDeleteRoleAction,
|
||||
type FlatUpdateRoleAction,
|
||||
type UniversalDeleteRoleAction,
|
||||
type UniversalUpdateRoleAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role/types/workspace-migration-role-action.type';
|
||||
import {
|
||||
type FlatCreateRowLevelPermissionPredicateGroupAction,
|
||||
type FlatDeleteRowLevelPermissionPredicateGroupAction,
|
||||
type FlatUpdateRowLevelPermissionPredicateGroupAction,
|
||||
type UniversalDeleteRowLevelPermissionPredicateGroupAction,
|
||||
type UniversalUpdateRowLevelPermissionPredicateGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action.type';
|
||||
import {
|
||||
type FlatCreateRowLevelPermissionPredicateAction,
|
||||
type FlatDeleteRowLevelPermissionPredicateAction,
|
||||
type FlatUpdateRowLevelPermissionPredicateAction,
|
||||
type UniversalDeleteRowLevelPermissionPredicateAction,
|
||||
type UniversalUpdateRowLevelPermissionPredicateAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action.type';
|
||||
import {
|
||||
type FlatCreateSkillAction,
|
||||
type FlatDeleteSkillAction,
|
||||
type FlatUpdateSkillAction,
|
||||
type UniversalCreateSkillAction,
|
||||
type UniversalDeleteSkillAction,
|
||||
type UniversalUpdateSkillAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/skill/types/workspace-migration-skill-action.type';
|
||||
import {
|
||||
type FlatCreateViewFieldAction,
|
||||
type FlatDeleteViewFieldAction,
|
||||
type FlatUpdateViewFieldAction,
|
||||
type UniversalCreateViewFieldAction,
|
||||
type UniversalDeleteViewFieldAction,
|
||||
type UniversalUpdateViewFieldAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-field/types/workspace-migration-view-field-action.type';
|
||||
import {
|
||||
type FlatCreateViewFilterGroupAction,
|
||||
type FlatDeleteViewFilterGroupAction,
|
||||
type FlatUpdateViewFilterGroupAction,
|
||||
type UniversalCreateViewFilterGroupAction,
|
||||
type UniversalDeleteViewFilterGroupAction,
|
||||
type UniversalUpdateViewFilterGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter-group/types/workspace-migration-view-filter-group-action.type';
|
||||
import {
|
||||
type FlatCreateViewFilterAction,
|
||||
type FlatDeleteViewFilterAction,
|
||||
type FlatUpdateViewFilterAction,
|
||||
type UniversalCreateViewFilterAction,
|
||||
type UniversalDeleteViewFilterAction,
|
||||
type UniversalUpdateViewFilterAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter/types/workspace-migration-view-filter-action.type';
|
||||
import {
|
||||
type FlatCreateViewGroupAction,
|
||||
type FlatDeleteViewGroupAction,
|
||||
type FlatUpdateViewGroupAction,
|
||||
type UniversalCreateViewGroupAction,
|
||||
type UniversalDeleteViewGroupAction,
|
||||
type UniversalUpdateViewGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-group/types/workspace-migration-view-group-action.type';
|
||||
import {
|
||||
type FlatCreateViewAction,
|
||||
type FlatDeleteViewAction,
|
||||
type FlatUpdateViewAction,
|
||||
type UniversalCreateViewAction,
|
||||
type UniversalDeleteViewAction,
|
||||
type UniversalUpdateViewAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view/types/workspace-migration-view-action.type';
|
||||
import {
|
||||
type FlatCreateWebhookAction,
|
||||
type FlatDeleteWebhookAction,
|
||||
type FlatUpdateWebhookAction,
|
||||
type UniversalDeleteWebhookAction,
|
||||
type UniversalUpdateWebhookAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/webhook/types/workspace-migration-webhook-action.type';
|
||||
|
||||
export type AllFlatEntityTypesByMetadataName = {
|
||||
@@ -238,8 +253,8 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
view: {
|
||||
flatEntityMaps: FlatViewMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewAction;
|
||||
update: FlatUpdateViewAction;
|
||||
create: UniversalCreateViewAction;
|
||||
update: UniversalUpdateViewAction;
|
||||
delete: UniversalDeleteViewAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -248,14 +263,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteViewAction;
|
||||
};
|
||||
flatEntity: FlatView;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewEntity>;
|
||||
universalFlatEntity: UniversalFlatView;
|
||||
entity: MetadataEntity<'view'>;
|
||||
};
|
||||
viewField: {
|
||||
flatEntityMaps: FlatViewFieldMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFieldAction;
|
||||
update: FlatUpdateViewFieldAction;
|
||||
create: UniversalCreateViewFieldAction;
|
||||
update: UniversalUpdateViewFieldAction;
|
||||
delete: UniversalDeleteViewFieldAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -264,14 +279,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteViewFieldAction;
|
||||
};
|
||||
flatEntity: FlatViewField;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFieldEntity>;
|
||||
universalFlatEntity: UniversalFlatViewField;
|
||||
entity: MetadataEntity<'viewField'>;
|
||||
};
|
||||
viewGroup: {
|
||||
flatEntityMaps: FlatViewGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewGroupAction;
|
||||
update: FlatUpdateViewGroupAction;
|
||||
create: UniversalCreateViewGroupAction;
|
||||
update: UniversalUpdateViewGroupAction;
|
||||
delete: UniversalDeleteViewGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -280,14 +295,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteViewGroupAction;
|
||||
};
|
||||
flatEntity: FlatViewGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewGroupEntity>;
|
||||
universalFlatEntity: UniversalFlatViewGroup;
|
||||
entity: MetadataEntity<'viewGroup'>;
|
||||
};
|
||||
rowLevelPermissionPredicate: {
|
||||
flatEntityMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateAction;
|
||||
update: UniversalUpdateRowLevelPermissionPredicateAction;
|
||||
delete: UniversalDeleteRowLevelPermissionPredicateAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -296,14 +311,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteRowLevelPermissionPredicateAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicate;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RowLevelPermissionPredicateEntity>;
|
||||
universalFlatEntity: FlatRowLevelPermissionPredicate;
|
||||
entity: MetadataEntity<'rowLevelPermissionPredicate'>;
|
||||
};
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
flatEntityMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateGroupAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateGroupAction;
|
||||
update: UniversalUpdateRowLevelPermissionPredicateGroupAction;
|
||||
delete: UniversalDeleteRowLevelPermissionPredicateGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -312,14 +327,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteRowLevelPermissionPredicateGroupAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicateGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RowLevelPermissionPredicateGroupEntity>;
|
||||
universalFlatEntity: FlatRowLevelPermissionPredicateGroup;
|
||||
entity: MetadataEntity<'rowLevelPermissionPredicateGroup'>;
|
||||
};
|
||||
viewFilterGroup: {
|
||||
flatEntityMaps: FlatViewFilterGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFilterGroupAction;
|
||||
update: FlatUpdateViewFilterGroupAction;
|
||||
create: UniversalCreateViewFilterGroupAction;
|
||||
update: UniversalUpdateViewFilterGroupAction;
|
||||
delete: UniversalDeleteViewFilterGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -328,14 +343,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteViewFilterGroupAction;
|
||||
};
|
||||
flatEntity: FlatViewFilterGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFilterGroupEntity>;
|
||||
universalFlatEntity: UniversalFlatViewFilterGroup;
|
||||
entity: MetadataEntity<'viewFilterGroup'>;
|
||||
};
|
||||
index: {
|
||||
flatEntityMaps: FlatEntityMaps<FlatIndexMetadata>;
|
||||
universalActions: {
|
||||
create: FlatCreateIndexAction;
|
||||
update: FlatUpdateIndexAction;
|
||||
create: UniversalCreateIndexAction;
|
||||
update: UniversalUpdateIndexAction;
|
||||
delete: UniversalDeleteIndexAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -344,14 +359,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteIndexAction;
|
||||
};
|
||||
flatEntity: FlatIndexMetadata;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<IndexMetadataEntity>;
|
||||
universalFlatEntity: UniversalFlatIndexMetadata;
|
||||
entity: MetadataEntity<'index'>;
|
||||
};
|
||||
logicFunction: {
|
||||
flatEntityMaps: FlatEntityMaps<FlatLogicFunction>;
|
||||
universalActions: {
|
||||
create: FlatCreateLogicFunctionAction;
|
||||
update: FlatUpdateLogicFunctionAction;
|
||||
update: UniversalUpdateLogicFunctionAction;
|
||||
delete: UniversalDeleteLogicFunctionAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -360,14 +375,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteLogicFunctionAction;
|
||||
};
|
||||
flatEntity: FlatLogicFunction;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<LogicFunctionEntity>;
|
||||
universalFlatEntity: FlatLogicFunction;
|
||||
entity: MetadataEntity<'logicFunction'>;
|
||||
};
|
||||
viewFilter: {
|
||||
flatEntityMaps: FlatViewFilterMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFilterAction;
|
||||
update: FlatUpdateViewFilterAction;
|
||||
create: UniversalCreateViewFilterAction;
|
||||
update: UniversalUpdateViewFilterAction;
|
||||
delete: UniversalDeleteViewFilterAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -376,14 +391,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteViewFilterAction;
|
||||
};
|
||||
flatEntity: FlatViewFilter;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFilterEntity>;
|
||||
universalFlatEntity: UniversalFlatViewFilter;
|
||||
entity: MetadataEntity<'viewFilter'>;
|
||||
};
|
||||
role: {
|
||||
flatEntityMaps: FlatEntityMaps<FlatRole>;
|
||||
universalActions: {
|
||||
create: FlatCreateRoleAction;
|
||||
update: FlatUpdateRoleAction;
|
||||
update: UniversalUpdateRoleAction;
|
||||
delete: UniversalDeleteRoleAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -392,14 +407,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteRoleAction;
|
||||
};
|
||||
flatEntity: FlatRole;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RoleEntity>;
|
||||
universalFlatEntity: FlatRole;
|
||||
entity: MetadataEntity<'role'>;
|
||||
};
|
||||
roleTarget: {
|
||||
flatEntityMaps: FlatRoleTargetMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRoleTargetAction;
|
||||
update: FlatUpdateRoleTargetAction;
|
||||
update: UniversalUpdateRoleTargetAction;
|
||||
delete: UniversalDeleteRoleTargetAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -408,14 +423,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteRoleTargetAction;
|
||||
};
|
||||
flatEntity: FlatRoleTarget;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RoleTargetEntity>;
|
||||
universalFlatEntity: FlatRoleTarget;
|
||||
entity: MetadataEntity<'roleTarget'>;
|
||||
};
|
||||
agent: {
|
||||
flatEntityMaps: FlatAgentMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateAgentAction;
|
||||
update: FlatUpdateAgentAction;
|
||||
update: UniversalUpdateAgentAction;
|
||||
delete: UniversalDeleteAgentAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -424,14 +439,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteAgentAction;
|
||||
};
|
||||
flatEntity: FlatAgent;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<AgentEntity>;
|
||||
universalFlatEntity: FlatAgent;
|
||||
entity: MetadataEntity<'agent'>;
|
||||
};
|
||||
skill: {
|
||||
flatEntityMaps: FlatSkillMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateSkillAction;
|
||||
update: FlatUpdateSkillAction;
|
||||
create: UniversalCreateSkillAction;
|
||||
update: UniversalUpdateSkillAction;
|
||||
delete: UniversalDeleteSkillAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -440,14 +455,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteSkillAction;
|
||||
};
|
||||
flatEntity: FlatSkill;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<SkillEntity>;
|
||||
universalFlatEntity: UniversalFlatSkill;
|
||||
entity: MetadataEntity<'skill'>;
|
||||
};
|
||||
commandMenuItem: {
|
||||
flatEntityMaps: FlatCommandMenuItemMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateCommandMenuItemAction;
|
||||
update: FlatUpdateCommandMenuItemAction;
|
||||
update: UniversalUpdateCommandMenuItemAction;
|
||||
delete: UniversalDeleteCommandMenuItemAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -456,14 +471,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteCommandMenuItemAction;
|
||||
};
|
||||
flatEntity: FlatCommandMenuItem;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<CommandMenuItemEntity>;
|
||||
universalFlatEntity: FlatCommandMenuItem;
|
||||
entity: MetadataEntity<'commandMenuItem'>;
|
||||
};
|
||||
navigationMenuItem: {
|
||||
flatEntityMaps: FlatNavigationMenuItemMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateNavigationMenuItemAction;
|
||||
update: FlatUpdateNavigationMenuItemAction;
|
||||
update: UniversalUpdateNavigationMenuItemAction;
|
||||
delete: UniversalDeleteNavigationMenuItemAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -472,14 +487,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteNavigationMenuItemAction;
|
||||
};
|
||||
flatEntity: FlatNavigationMenuItem;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<NavigationMenuItemEntity>;
|
||||
universalFlatEntity: FlatNavigationMenuItem;
|
||||
entity: NavigationMenuItemEntity;
|
||||
};
|
||||
pageLayout: {
|
||||
flatEntityMaps: FlatPageLayoutMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutAction;
|
||||
update: FlatUpdatePageLayoutAction;
|
||||
update: UniversalUpdatePageLayoutAction;
|
||||
delete: UniversalDeletePageLayoutAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -488,14 +503,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeletePageLayoutAction;
|
||||
};
|
||||
flatEntity: FlatPageLayout;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<PageLayoutEntity>;
|
||||
universalFlatEntity: FlatPageLayout;
|
||||
entity: MetadataEntity<'pageLayout'>;
|
||||
};
|
||||
pageLayoutWidget: {
|
||||
flatEntityMaps: FlatPageLayoutWidgetMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutWidgetAction;
|
||||
update: FlatUpdatePageLayoutWidgetAction;
|
||||
update: UniversalUpdatePageLayoutWidgetAction;
|
||||
delete: UniversalDeletePageLayoutWidgetAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -504,17 +519,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeletePageLayoutWidgetAction;
|
||||
};
|
||||
flatEntity: FlatPageLayoutWidget;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<
|
||||
PageLayoutWidgetEntity,
|
||||
'pageLayoutWidget'
|
||||
>;
|
||||
universalFlatEntity: FlatPageLayoutWidget;
|
||||
entity: MetadataEntity<'pageLayoutWidget'>;
|
||||
};
|
||||
pageLayoutTab: {
|
||||
flatEntityMaps: FlatPageLayoutTabMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutTabAction;
|
||||
update: FlatUpdatePageLayoutTabAction;
|
||||
update: UniversalUpdatePageLayoutTabAction;
|
||||
delete: UniversalDeletePageLayoutTabAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -523,14 +535,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeletePageLayoutTabAction;
|
||||
};
|
||||
flatEntity: FlatPageLayoutTab;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<PageLayoutTabEntity>;
|
||||
universalFlatEntity: FlatPageLayoutTab;
|
||||
entity: MetadataEntity<'pageLayoutTab'>;
|
||||
};
|
||||
frontComponent: {
|
||||
flatEntityMaps: FlatFrontComponentMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateFrontComponentAction;
|
||||
update: FlatUpdateFrontComponentAction;
|
||||
update: UniversalUpdateFrontComponentAction;
|
||||
delete: UniversalDeleteFrontComponentAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -539,14 +551,14 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteFrontComponentAction;
|
||||
};
|
||||
flatEntity: FlatFrontComponent;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<FrontComponentEntity>;
|
||||
universalFlatEntity: FlatFrontComponent;
|
||||
entity: MetadataEntity<'frontComponent'>;
|
||||
};
|
||||
webhook: {
|
||||
flatEntityMaps: FlatWebhookMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateWebhookAction;
|
||||
update: FlatUpdateWebhookAction;
|
||||
update: UniversalUpdateWebhookAction;
|
||||
delete: UniversalDeleteWebhookAction;
|
||||
};
|
||||
flatActions: {
|
||||
@@ -555,7 +567,7 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
delete: FlatDeleteWebhookAction;
|
||||
};
|
||||
flatEntity: FlatWebhook;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<WebhookEntity>;
|
||||
universalFlatEntity: FlatWebhook;
|
||||
entity: MetadataEntity<'webhook'>;
|
||||
};
|
||||
};
|
||||
|
||||
+6
-8
@@ -1,10 +1,8 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export type FlatEntityMaps<
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
> = {
|
||||
byUniversalIdentifier: Partial<Record<string, T>>;
|
||||
universalIdentifierById: Partial<Record<string, string>>;
|
||||
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
|
||||
};
|
||||
export type FlatEntityMaps<T extends SyncableFlatEntity> =
|
||||
UniversalFlatEntityMaps<T> & {
|
||||
universalIdentifierById: Partial<Record<string, string>>;
|
||||
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
|
||||
};
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
|
||||
export type FlatEntityPropertiesToCompare<T extends AllMetadataName> =
|
||||
(typeof ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY)[T]['propertiesToCompare'][number];
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
|
||||
export type FlatEntityPropertiesToStringify<T extends AllMetadataName> =
|
||||
(typeof ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY)[T]['propertiesToStringify'][number];
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
|
||||
export type MetadataFlatEntityComparableProperties<T extends AllMetadataName> =
|
||||
Extract<FlatEntityPropertiesToCompare<T>, keyof MetadataFlatEntity<T>>;
|
||||
|
||||
export type FlatEntityUpdate<T extends AllMetadataName> = Partial<
|
||||
Pick<MetadataFlatEntity<T>, MetadataFlatEntityComparableProperties<T>>
|
||||
>;
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { type MetadataUniversalFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-universal-flat-entity.type';
|
||||
|
||||
export type FlatEntityToCreateDeleteUpdate<T extends AllMetadataName> = {
|
||||
flatEntityToUpdate: MetadataFlatEntity<T>[];
|
||||
flatEntityToCreate: MetadataFlatEntity<T>[];
|
||||
flatEntityToDelete: MetadataFlatEntity<T>[];
|
||||
flatEntityToUpdate: MetadataUniversalFlatEntity<T>[];
|
||||
flatEntityToCreate: (MetadataUniversalFlatEntity<T> & { id?: string })[];
|
||||
flatEntityToDelete: MetadataUniversalFlatEntity<T>[];
|
||||
};
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type 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 MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
|
||||
type IsUniversalMappedProperty<
|
||||
MetadataConfig,
|
||||
P extends keyof MetadataConfig,
|
||||
> = MetadataConfig[P] extends { universalProperty: string }
|
||||
? MetadataConfig[P]['universalProperty']
|
||||
: never;
|
||||
|
||||
export type FlatEntityUpdate<
|
||||
T extends AllMetadataName,
|
||||
MetadataPropertyConfig = (typeof ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME)[T],
|
||||
> = Partial<
|
||||
Pick<
|
||||
MetadataFlatEntity<T>,
|
||||
Extract<keyof MetadataFlatEntity<T>, keyof MetadataPropertyConfig>
|
||||
>
|
||||
> & {
|
||||
[K in keyof MetadataPropertyConfig as [
|
||||
never,
|
||||
] extends IsUniversalMappedProperty<MetadataPropertyConfig, K>
|
||||
? never
|
||||
: IsUniversalMappedProperty<MetadataPropertyConfig, K>]?: never;
|
||||
};
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-flat-entity-maps-keys.type';
|
||||
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { type MetadataValidationRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/types/metadata-validation-related-metadata-names.type';
|
||||
import { type AllUniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/all-universal-flat-entity-maps.type';
|
||||
|
||||
export type MetadataFlatEntityAndRelatedFlatEntityMapsForValidation<
|
||||
export type MetadataUniversalFlatEntityAndRelatedFlatEntityMapsForValidation<
|
||||
T extends AllMetadataName,
|
||||
> = Pick<
|
||||
AllFlatEntityMaps,
|
||||
AllUniversalFlatEntityMaps,
|
||||
| MetadataRelatedFlatEntityMapsKeys<T>
|
||||
| MetadataToFlatEntityMapsKey<T>
|
||||
| MetadataToFlatEntityMapsKey<MetadataValidationRelatedMetadataNames<T>>
|
||||
|
||||
+12
-2
@@ -4,6 +4,14 @@ import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/
|
||||
import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-flat-entity-maps-keys.type';
|
||||
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { type MetadataValidationRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/types/metadata-validation-related-metadata-names.type';
|
||||
import { type AllUniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/all-universal-flat-entity-maps.type';
|
||||
|
||||
export type MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps<
|
||||
T extends AllMetadataName,
|
||||
> = Pick<
|
||||
AllUniversalFlatEntityMaps,
|
||||
MetadataRelatedFlatEntityMapsKeys<T> | MetadataToFlatEntityMapsKey<T>
|
||||
>;
|
||||
|
||||
export type MetadataFlatEntityAndRelatedFlatEntityMaps<
|
||||
T extends AllMetadataName,
|
||||
@@ -12,11 +20,13 @@ export type MetadataFlatEntityAndRelatedFlatEntityMaps<
|
||||
MetadataRelatedFlatEntityMapsKeys<T> | MetadataToFlatEntityMapsKey<T>
|
||||
>;
|
||||
|
||||
export type MetadataValidationRelatedFlatEntityMaps<T extends AllMetadataName> =
|
||||
export type MetadataValidationRelatedUniversalFlatEntityMaps<
|
||||
T extends AllMetadataName,
|
||||
> =
|
||||
MetadataValidationRelatedMetadataNames<T> extends undefined
|
||||
? undefined
|
||||
: Pick<
|
||||
AllFlatEntityMaps,
|
||||
AllUniversalFlatEntityMaps,
|
||||
MetadataToFlatEntityMapsKey<
|
||||
NonNullable<MetadataValidationRelatedMetadataNames<T>>
|
||||
>
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 1`] = `
|
||||
{
|
||||
"isActive": false,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 2`] = `
|
||||
{
|
||||
"isActive": true,
|
||||
}
|
||||
`;
|
||||
+19
-11
@@ -4,7 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -12,14 +12,18 @@ import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow', () => {
|
||||
it('should add a view and update related objectMetadata with viewId', () => {
|
||||
it('should add a view and update related objectMetadata and fieldMetadata with both id and universal identifier aggregators', () => {
|
||||
const objectMetadataId = 'object-1';
|
||||
const viewId = 'view-1';
|
||||
const applicationId = '20202020-f3ad-452e-b5b6-2d49d3ea88b1';
|
||||
const workspaceId = '20202020-bc64-4148-8a79-b3144f743694';
|
||||
const objectUniversalIdentifier = 'object-universal-1';
|
||||
const fieldUniversalIdentifier = 'field-universal-1';
|
||||
const viewUniversalIdentifier = 'view-universal-1';
|
||||
|
||||
const mockObjectMetadata = getFlatObjectMetadataMock({
|
||||
id: objectMetadataId,
|
||||
universalIdentifier: 'object-universal-1',
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
viewIds: [],
|
||||
fieldIds: [],
|
||||
workspaceId,
|
||||
@@ -34,7 +38,7 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
type: FieldMetadataType.DATE,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
universalIdentifier: 'field-universal-1',
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
calendarViewIds: [],
|
||||
@@ -44,13 +48,15 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
const mockView: Pick<FlatView, 'id'> & Partial<FlatView> = {
|
||||
id: viewId,
|
||||
workspaceId,
|
||||
universalIdentifier: 'view-universal-1',
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
objectMetadataId: objectMetadataId,
|
||||
objectMetadataUniversalIdentifier: objectUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
applicationId,
|
||||
calendarFieldMetadataId: mockFieldMetadata.id,
|
||||
calendarFieldMetadataUniversalIdentifier: fieldUniversalIdentifier,
|
||||
};
|
||||
|
||||
const flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<'view'> =
|
||||
@@ -73,28 +79,30 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockView.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toMatchObject(mockView);
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: [mockView.id],
|
||||
viewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [mockView.id],
|
||||
calendarViewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
|
||||
type TestContext<T extends AllMetadataName = AllMetadataName> = FromTo<
|
||||
MetadataFlatEntity<T>,
|
||||
'flatEntity'
|
||||
> & { metadataName: T };
|
||||
|
||||
describe('compareTwoFlatEntity', () => {
|
||||
const testCases = [
|
||||
{
|
||||
title:
|
||||
'It should detect flat field metadata isActive diff from true to false',
|
||||
context: {
|
||||
fromFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: true,
|
||||
}),
|
||||
metadataName: 'fieldMetadata',
|
||||
toFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'It should detect flat field metadata isActive diff from true to false',
|
||||
context: {
|
||||
fromFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: false,
|
||||
}),
|
||||
metadataName: 'fieldMetadata',
|
||||
toFlatEntity: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier',
|
||||
isActive: true,
|
||||
}),
|
||||
},
|
||||
},
|
||||
] as const satisfies EachTestingContext<TestContext>[];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { metadataName, fromFlatEntity, toFlatEntity } }) => {
|
||||
const result = compareTwoFlatEntity({
|
||||
fromFlatEntity,
|
||||
propertiesToCompare:
|
||||
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName]
|
||||
.propertiesToCompare as any,
|
||||
propertiesToStringify:
|
||||
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName]
|
||||
.propertiesToStringify as any,
|
||||
toFlatEntity,
|
||||
});
|
||||
|
||||
expect(result).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny({ ...result }),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
+20
-11
@@ -4,7 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -12,16 +12,20 @@ import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow', () => {
|
||||
it('should delete a view and update related objectMetadata and fieldMetadata by removing viewId', () => {
|
||||
it('should delete a view and update related objectMetadata and fieldMetadata by removing both id and universal identifier aggregators', () => {
|
||||
const objectMetadataId = 'object-1';
|
||||
const viewId = 'view-1';
|
||||
const applicationId = '20202020-f3ad-452e-b5b6-2d49d3ea88b1';
|
||||
const workspaceId = '20202020-bc64-4148-8a79-b3144f743694';
|
||||
const objectUniversalIdentifier = 'object-universal-1';
|
||||
const fieldUniversalIdentifier = 'field-universal-1';
|
||||
const viewUniversalIdentifier = 'view-universal-1';
|
||||
|
||||
const mockObjectMetadata = getFlatObjectMetadataMock({
|
||||
id: objectMetadataId,
|
||||
universalIdentifier: 'object-universal-1',
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
viewIds: [viewId, 'something-else'],
|
||||
viewUniversalIdentifiers: [viewUniversalIdentifier, 'something-else-ui'],
|
||||
fieldIds: [],
|
||||
workspaceId,
|
||||
imageIdentifierFieldMetadataId: '20202020-9d65-415f-b0e1-216a2e257ea4',
|
||||
@@ -33,24 +37,27 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
|
||||
objectMetadataId,
|
||||
id: '20202020-4087-423b-852a-91f91acf2df2',
|
||||
type: FieldMetadataType.DATE,
|
||||
universalIdentifier: 'field-universal-1',
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
workspaceId,
|
||||
calendarViewIds: [viewId],
|
||||
calendarViewUniversalIdentifiers: [viewUniversalIdentifier],
|
||||
mainGroupByFieldMetadataViewIds: [],
|
||||
applicationId,
|
||||
});
|
||||
|
||||
const mockView: Partial<FlatView> = {
|
||||
id: viewId,
|
||||
universalIdentifier: 'view-universal-1',
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
objectMetadataId: objectMetadataId,
|
||||
objectMetadataUniversalIdentifier: objectUniversalIdentifier,
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
workspaceId,
|
||||
calendarFieldMetadataId: mockFieldMetadata.id,
|
||||
calendarFieldMetadataUniversalIdentifier: fieldUniversalIdentifier,
|
||||
createdAt: new Date('2024-01-01').toISOString(),
|
||||
updatedAt: new Date('2024-01-01').toISOString(),
|
||||
icon: 'icon',
|
||||
@@ -83,28 +90,30 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: objectUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: ['something-else'],
|
||||
viewUniversalIdentifiers: ['something-else-ui'],
|
||||
});
|
||||
|
||||
expect(
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: fieldUniversalIdentifier,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+21
-11
@@ -12,7 +12,7 @@ import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modu
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
type AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
@@ -22,21 +22,30 @@ type AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
<T extends AllMetadataName>({
|
||||
metadataName,
|
||||
flatEntity,
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
}: AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow(
|
||||
{
|
||||
metadataName,
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
const selfFlatEntityMaps =
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey];
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey],
|
||||
});
|
||||
selfFlatEntityMaps.universalIdentifierById[flatEntity.id] =
|
||||
flatEntity.universalIdentifier;
|
||||
|
||||
const manyToOneRelations = Object.values(
|
||||
const idBasedManyToOneRelations = Object.values(
|
||||
ALL_METADATA_RELATIONS[metadataName].manyToOne,
|
||||
) as Array<{
|
||||
metadataName: AllMetadataName;
|
||||
@@ -44,8 +53,8 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
foreignKey: keyof MetadataFlatEntity<T>;
|
||||
} | null>;
|
||||
|
||||
for (const relation of manyToOneRelations) {
|
||||
if (!isDefined(relation)) {
|
||||
for (const idBasedRelation of idBasedManyToOneRelations) {
|
||||
if (!isDefined(idBasedRelation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -53,7 +62,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
metadataName: relatedMetadataName,
|
||||
flatEntityForeignKeyAggregator,
|
||||
foreignKey,
|
||||
} = relation;
|
||||
} = idBasedRelation;
|
||||
|
||||
if (!isDefined(flatEntityForeignKeyAggregator)) {
|
||||
continue;
|
||||
@@ -61,6 +70,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
|
||||
const relatedFlatEntityMapsKey =
|
||||
getMetadataFlatEntityMapsKey(relatedMetadataName);
|
||||
|
||||
const relatedFlatEntityMetadataMaps = flatEntityAndRelatedMapsToMutate[
|
||||
relatedFlatEntityMapsKey as MetadataRelatedFlatEntityMapsKeys<T>
|
||||
] as FlatEntityMaps<MetadataFlatEntity<typeof relatedMetadataName>>;
|
||||
@@ -85,7 +95,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Should never occur, invalid flat entity typing. flat ${metadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
`Should never occur, invalid flat entity typing. flat ${relatedMetadataName} should contain ${String(flatEntityForeignKeyAggregator)}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
);
|
||||
}
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
import diff from 'microdiff';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { parseJson } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { transformFlatEntityForComparison } from 'src/engine/metadata-modules/flat-entity/utils/transform-flat-entity-for-comparison.util';
|
||||
|
||||
export const compareTwoFlatEntity = <
|
||||
T extends AllMetadataName,
|
||||
PToCompare extends Extract<
|
||||
FlatEntityPropertiesToCompare<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>,
|
||||
PJsonB extends PToCompare = PToCompare,
|
||||
>({
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}: FromTo<MetadataFlatEntity<T>, 'flatEntity'> & {
|
||||
propertiesToCompare: readonly PToCompare[];
|
||||
propertiesToStringify: readonly PJsonB[];
|
||||
}): FlatEntityUpdate<T> | undefined => {
|
||||
const [transformedFromFlatEntity, transformedToFlatEntity] = [
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
].map((flatEntity) =>
|
||||
transformFlatEntityForComparison({
|
||||
flatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}),
|
||||
);
|
||||
|
||||
const flatEntityDifferences = diff(
|
||||
transformedFromFlatEntity,
|
||||
transformedToFlatEntity,
|
||||
);
|
||||
|
||||
if (flatEntityDifferences.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const initialAccumulator: FlatEntityUpdate<T> = {};
|
||||
|
||||
return flatEntityDifferences.reduce((accumulator, difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { path, value } = difference;
|
||||
const property = path[0] as PToCompare;
|
||||
const isJsonb = propertiesToStringify.includes(
|
||||
property as unknown as PJsonB,
|
||||
);
|
||||
|
||||
if (isJsonb) {
|
||||
return {
|
||||
...accumulator,
|
||||
[property]: parseJson(value),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...accumulator,
|
||||
[property]: value,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occur, we should only provide null never undefined and so on
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
}, initialAccumulator);
|
||||
};
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityToCreateDeleteUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-to-create-delete-update.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityByIdsMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-by-ids-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
|
||||
export type ComputeFlatEntityMapsFromToArgs<T extends AllMetadataName> = {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
} & FlatEntityToCreateDeleteUpdate<T>;
|
||||
export const computeFlatEntityMapsFromTo = <T extends AllMetadataName>({
|
||||
flatEntityMaps,
|
||||
flatEntityToCreate,
|
||||
flatEntityToDelete,
|
||||
flatEntityToUpdate,
|
||||
}: ComputeFlatEntityMapsFromToArgs<T>): {
|
||||
from: MetadataFlatEntityMaps<T>;
|
||||
to: MetadataFlatEntityMaps<T>;
|
||||
} => {
|
||||
const fromFlatEntityMaps =
|
||||
flatEntityToDelete.length > 0
|
||||
? getSubFlatEntityByIdsMapsOrThrow({
|
||||
flatEntityIds: [...flatEntityToDelete, ...flatEntityToUpdate].map(
|
||||
({ id }) => id,
|
||||
),
|
||||
flatEntityMaps,
|
||||
})
|
||||
: flatEntityMaps;
|
||||
|
||||
const toFlatEntityMapsWithDeleted = flatEntityToDelete.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
entityToDeleteId: flatEntity.id,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
fromFlatEntityMaps,
|
||||
);
|
||||
|
||||
const toFlatEntityMapsWithUpdated = flatEntityToUpdate.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
toFlatEntityMapsWithDeleted,
|
||||
);
|
||||
|
||||
const toFlatEntityMaps = flatEntityToCreate.reduce(
|
||||
(flatEntityMaps, flatEntity) =>
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
toFlatEntityMapsWithUpdated,
|
||||
);
|
||||
|
||||
return {
|
||||
from: fromFlatEntityMaps,
|
||||
to: toFlatEntityMaps,
|
||||
};
|
||||
};
|
||||
+15
-15
@@ -12,7 +12,7 @@ import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modu
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { deleteUniversalFlatEntityFromUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
type DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
@@ -22,23 +22,23 @@ type DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArg
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
<T extends AllMetadataName>({
|
||||
metadataName,
|
||||
flatEntity,
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
}: DeleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
deleteUniversalFlatEntityFromUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow(
|
||||
{
|
||||
metadataName,
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
},
|
||||
);
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow<
|
||||
MetadataFlatEntity<T>
|
||||
>({
|
||||
entityToDeleteId: flatEntity.id,
|
||||
flatEntityMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate[flatEntityMapsKey],
|
||||
});
|
||||
|
||||
const manyToOneRelations = Object.values(
|
||||
const idBasedManyToOneRelations = Object.values(
|
||||
ALL_METADATA_RELATIONS[metadataName].manyToOne,
|
||||
) as Array<{
|
||||
metadataName: AllMetadataName;
|
||||
@@ -46,8 +46,8 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
foreignKey: keyof MetadataFlatEntity<T>;
|
||||
} | null>;
|
||||
|
||||
for (const relation of manyToOneRelations) {
|
||||
if (!isDefined(relation)) {
|
||||
for (const idBasedRelation of idBasedManyToOneRelations) {
|
||||
if (!isDefined(idBasedRelation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
metadataName: relatedMetadataName,
|
||||
flatEntityForeignKeyAggregator,
|
||||
foreignKey,
|
||||
} = relation;
|
||||
} = idBasedRelation;
|
||||
|
||||
if (!isDefined(flatEntityForeignKeyAggregator)) {
|
||||
continue;
|
||||
@@ -92,7 +92,7 @@ export const deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOr
|
||||
)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Should never occur, invalid flat entity typing. flat ${metadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
`Should never occur, invalid flat entity typing. flat ${relatedMetadataName} should contain ${flatEntityForeignKeyAggregator}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_MALFORMED,
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ import {
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
@@ -15,7 +15,7 @@ export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T => {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifier({
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifier = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
@@ -8,7 +8,7 @@ export const findFlatEntityByUniversalIdentifier = <
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T | undefined => {
|
||||
return flatEntityMaps.byUniversalIdentifier[universalIdentifier];
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
|
||||
export type FindManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrowArgs<
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
> = {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifiers: string[];
|
||||
};
|
||||
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { ALL_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
|
||||
|
||||
export const getMetadataSerializedRelationNames = (
|
||||
metadataName: AllMetadataName,
|
||||
): AllMetadataName[] => {
|
||||
const relations = ALL_METADATA_RELATIONS[metadataName];
|
||||
|
||||
if (!('serializedRelations' in relations)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.keys(relations.serializedRelations) as AllMetadataName[];
|
||||
};
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
export const getSubUniversalFlatEntityByUniversalIdentifiersMapsOrThrow = <
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
>({
|
||||
universalIdentifiers,
|
||||
universalFlatEntityMaps,
|
||||
}: {
|
||||
universalFlatEntityMaps: UniversalFlatEntityMaps<T>;
|
||||
universalIdentifiers: string[];
|
||||
}): UniversalFlatEntityMaps<T> => {
|
||||
const subUniversalFlatEntityMaps: UniversalFlatEntityMaps<T> = {
|
||||
byUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
for (const universalIdentifier of universalIdentifiers) {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: universalFlatEntityMaps,
|
||||
universalIdentifier,
|
||||
});
|
||||
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityMapsToMutate: subUniversalFlatEntityMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return subUniversalFlatEntityMaps;
|
||||
};
|
||||
+4
-2
@@ -4,7 +4,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
ALL_METADATA_RELATIONS,
|
||||
type ManyToOneRelationValue,
|
||||
type MetadataManyToOneRelationConfiguration,
|
||||
} from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
@@ -76,7 +76,9 @@ export const resolveEntityRelationUniversalIdentifiers = <
|
||||
const relations = ALL_METADATA_RELATIONS[metadataName].manyToOne;
|
||||
const result: Record<string, string | null> = {};
|
||||
|
||||
for (const relation of Object.values(relations) as ManyToOneRelationValue<
|
||||
for (const relation of Object.values(
|
||||
relations,
|
||||
) as MetadataManyToOneRelationConfiguration<
|
||||
T,
|
||||
ExtractEntityManyToOneEntityRelationProperties<MetadataEntity<T>>
|
||||
>[]) {
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveUniversalIdentifierFromFlatEntityIdOrThrow = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string;
|
||||
metadataName: T;
|
||||
}): string => {
|
||||
const flatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
});
|
||||
|
||||
if (!isDefined(flatEntity)) {
|
||||
throw new FlatEntityMapsException(
|
||||
t`Could not find ${metadataName}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return flatEntity.universalIdentifier;
|
||||
};
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveNullableUniversalIdentifierFromFlatEntityId = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string | null | undefined;
|
||||
metadataName: T;
|
||||
}): string | null => {
|
||||
if (!isDefined(flatEntityId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveUniversalIdentifierFromFlatEntityIdOrThrow({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
});
|
||||
};
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { orderObjectProperties } from 'src/engine/metadata-modules/flat-entity/utils/order-object-properties.util';
|
||||
|
||||
export function transformFlatEntityForComparison<
|
||||
TFlatEntity extends SyncableFlatEntity,
|
||||
PToCompare extends keyof TFlatEntity,
|
||||
PJsonB extends PToCompare,
|
||||
>({
|
||||
flatEntity,
|
||||
propertiesToCompare,
|
||||
propertiesToStringify,
|
||||
}: {
|
||||
flatEntity: TFlatEntity;
|
||||
propertiesToCompare: readonly PToCompare[];
|
||||
propertiesToStringify: readonly PJsonB[];
|
||||
}): Pick<TFlatEntity, PToCompare> {
|
||||
return propertiesToCompare.reduce(
|
||||
(flatEntityAccumulator, propertyToCompare) => {
|
||||
const currentValue = flatEntity[propertyToCompare];
|
||||
|
||||
if (propertiesToStringify.includes(propertyToCompare as PJsonB)) {
|
||||
const orderedValue = orderObjectProperties(currentValue);
|
||||
|
||||
return {
|
||||
...flatEntityAccumulator,
|
||||
[propertyToCompare]: JSON.stringify(orderedValue),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...flatEntityAccumulator,
|
||||
[propertyToCompare]: currentValue,
|
||||
};
|
||||
},
|
||||
{} as Pick<TFlatEntity, PToCompare>,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user