Compare commits

...
Author SHA1 Message Date
prastoin 5b60e5fbe3 revert rls transpiler as tunnel prone 2026-02-17 11:51:23 +01:00
prastoin c83d6f90e1 restore input 2026-02-17 11:24:09 +01:00
prastoin 53101cc78a restore field appId and universalIdentifier 2026-02-17 11:20:43 +01:00
prastoin 79a6cc40cc chore 2026-02-16 18:58:39 +01:00
prastoin d09d6c8119 lint 2026-02-16 18:47:23 +01:00
prastoin 4a95e018ad refactor(server): duplicate page layout 2026-02-16 18:46:22 +01:00
prastoin 7791053829 chore 2026-02-16 18:36:45 +01:00
prastoin cf6c1c1ca0 fix 2026-02-16 18:23:02 +01:00
prastoin 5c6c24b253 refactor(server): remove dynamic app assignation 2026-02-13 15:43:57 +01:00
prastoin d51ec103da refactor(server): inputs 2026-02-13 15:43:37 +01:00
24 changed files with 211 additions and 281 deletions
@@ -17,6 +17,7 @@ import { fromFlatCommandMenuItemToCommandMenuItemDto } from 'src/engine/metadata
import { fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow } from 'src/engine/metadata-modules/flat-command-menu-item/utils/from-update-command-menu-item-input-to-flat-command-menu-item-to-update-or-throw.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@@ -104,7 +105,6 @@ export class CommandMenuItemService {
const flatCommandMenuItemToCreate =
fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate({
createCommandMenuItemInput: input,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatObjectMetadataMaps,
flatFrontComponentMaps,
@@ -143,8 +143,8 @@ export class CommandMenuItemService {
);
return fromFlatCommandMenuItemToCommandMenuItemDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatCommandMenuItemToCreate.id,
findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatCommandMenuItemToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatCommandMenuItemMaps,
}),
);
@@ -8,24 +8,22 @@ import {
} from 'src/engine/metadata-modules/command-menu-item/command-menu-item.exception';
import { type CreateCommandMenuItemInput } from 'src/engine/metadata-modules/command-menu-item/dtos/create-command-menu-item.input';
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/entities/command-menu-item.entity';
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
import { type UniversalFlatCommandMenuItem } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-command-menu-item.type';
export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
createCommandMenuItemInput,
workspaceId,
flatApplication,
flatObjectMetadataMaps,
flatFrontComponentMaps,
}: {
createCommandMenuItemInput: CreateCommandMenuItemInput;
workspaceId: string;
flatApplication: FlatApplication;
} & Pick<
AllFlatEntityMaps,
'flatObjectMetadataMaps' | 'flatFrontComponentMaps'
>): FlatCommandMenuItem => {
>): UniversalFlatCommandMenuItem => {
const hasWorkflowVersionId = isDefined(
createCommandMenuItemInput.workflowVersionId,
);
@@ -40,7 +38,6 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
);
}
const id = uuidv4();
const now = new Date().toISOString();
const {
@@ -57,10 +54,8 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
});
return {
id,
universalIdentifier: id,
universalIdentifier: uuidv4(),
workflowVersionId: createCommandMenuItemInput.workflowVersionId ?? null,
frontComponentId: createCommandMenuItemInput.frontComponentId ?? null,
frontComponentUniversalIdentifier,
label: createCommandMenuItemInput.label,
icon: createCommandMenuItemInput.icon ?? null,
@@ -68,11 +63,7 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
availabilityType:
createCommandMenuItemInput.availabilityType ??
CommandMenuItemAvailabilityType.GLOBAL,
availabilityObjectMetadataId:
createCommandMenuItemInput.availabilityObjectMetadataId ?? null,
availabilityObjectMetadataUniversalIdentifier,
workspaceId,
applicationId: flatApplication.id,
applicationUniversalIdentifier: flatApplication.universalIdentifier,
createdAt: now,
updatedAt: now,
@@ -2,18 +2,16 @@ import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'tw
import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
import { type CreateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/create-front-component.input';
import { type UniversalFlatFrontComponent } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-front-component.type';
export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
createFrontComponentInput,
workspaceId,
flatApplication,
}: {
createFrontComponentInput: CreateFrontComponentInput;
workspaceId: string;
flatApplication: FlatApplication;
}): FlatFrontComponent => {
}): UniversalFlatFrontComponent => {
const now = new Date().toISOString();
const { name } = trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
@@ -21,23 +19,16 @@ export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
['name'],
);
const id = createFrontComponentInput.id ?? v4();
const universalIdentifier =
createFrontComponentInput.universalIdentifier ?? v4();
return {
id,
name: name ?? createFrontComponentInput.componentName,
description: createFrontComponentInput.description ?? null,
sourceComponentPath: createFrontComponentInput.sourceComponentPath,
builtComponentPath: createFrontComponentInput.builtComponentPath,
componentName: createFrontComponentInput.componentName,
builtComponentChecksum: createFrontComponentInput.builtComponentChecksum,
workspaceId,
createdAt: now,
updatedAt: now,
universalIdentifier,
applicationId: flatApplication.id,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
};
};
@@ -5,27 +5,24 @@ import { type FlatApplication } from 'src/engine/core-modules/application/types/
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
import { type CreateNavigationMenuItemInput } from 'src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input';
import { type UniversalFlatNavigationMenuItem } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-navigation-menu-item.type';
export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
({
createNavigationMenuItemInput,
workspaceId,
flatApplication,
flatNavigationMenuItemMaps,
flatObjectMetadataMaps,
flatViewMaps,
}: {
createNavigationMenuItemInput: CreateNavigationMenuItemInput;
workspaceId: string;
flatApplication: FlatApplication;
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
} & Pick<
AllFlatEntityMaps,
'flatObjectMetadataMaps' | 'flatViewMaps'
>): FlatNavigationMenuItem => {
const id = uuidv4();
>): UniversalFlatNavigationMenuItem => {
const now = new Date().toISOString();
let position = createNavigationMenuItemInput.position;
@@ -68,22 +65,15 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
});
return {
id,
universalIdentifier: id,
universalIdentifier: uuidv4(),
userWorkspaceId: createNavigationMenuItemInput.userWorkspaceId ?? null,
targetRecordId: createNavigationMenuItemInput.targetRecordId ?? null,
targetObjectMetadataId:
createNavigationMenuItemInput.targetObjectMetadataId ?? null,
targetObjectMetadataUniversalIdentifier,
viewId: createNavigationMenuItemInput.viewId ?? null,
viewUniversalIdentifier,
folderId: createNavigationMenuItemInput.folderId ?? null,
folderUniversalIdentifier,
name: createNavigationMenuItemInput.name ?? null,
link: createNavigationMenuItemInput.link ?? null,
position,
workspaceId,
applicationId: flatApplication.id,
applicationUniversalIdentifier: flatApplication.universalIdentifier,
createdAt: now,
updatedAt: now,
@@ -5,21 +5,19 @@ import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { type CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout-tab/dtos/inputs/create-page-layout-tab.input';
import { type UniversalFlatPageLayoutTab } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-tab.type';
export type FromCreatePageLayoutTabInputToFlatPageLayoutTabToCreateArgs = {
createPageLayoutTabInput: CreatePageLayoutTabInput;
workspaceId: string;
flatApplication: FlatApplication;
} & Pick<AllFlatEntityMaps, 'flatPageLayoutMaps'>;
export const fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate = ({
createPageLayoutTabInput: rawCreatePageLayoutTabInput,
workspaceId,
flatApplication,
flatPageLayoutMaps,
}: FromCreatePageLayoutTabInputToFlatPageLayoutTabToCreateArgs): FlatPageLayoutTab => {
}: FromCreatePageLayoutTabInputToFlatPageLayoutTabToCreateArgs): UniversalFlatPageLayoutTab => {
const createPageLayoutTabInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreatePageLayoutTabInput,
@@ -27,7 +25,6 @@ export const fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate = ({
);
const createdAt = new Date().toISOString();
const pageLayoutTabId = v4();
const { pageLayoutUniversalIdentifier } =
resolveEntityRelationUniversalIdentifiers({
@@ -41,19 +38,14 @@ export const fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate = ({
});
return {
id: pageLayoutTabId,
title: createPageLayoutTabInput.title,
position: createPageLayoutTabInput.position ?? 0,
pageLayoutId: createPageLayoutTabInput.pageLayoutId,
pageLayoutUniversalIdentifier,
workspaceId,
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: pageLayoutTabId,
applicationId: flatApplication.id,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
widgetIds: [],
widgetUniversalIdentifiers: [],
icon: null,
layoutMode: PageLayoutTabLayoutMode.GRID,
@@ -4,15 +4,14 @@ import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { fromPageLayoutWidgetConfigurationToUniversalConfiguration } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util';
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input';
import { validateWidgetConfigurationInput } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-widget-configuration-input.util';
import { type UniversalFlatPageLayoutWidget } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-widget.type';
export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
{
createPageLayoutWidgetInput: CreatePageLayoutWidgetInput;
workspaceId: string;
flatApplication: FlatApplication;
} & Pick<
AllFlatEntityMaps,
@@ -21,12 +20,11 @@ export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
createPageLayoutWidgetInput: rawCreatePageLayoutWidgetInput,
workspaceId,
flatApplication,
flatPageLayoutTabMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => {
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): UniversalFlatPageLayoutWidget => {
const { pageLayoutTabId, ...createPageLayoutWidgetInput } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreatePageLayoutWidgetInput,
@@ -38,7 +36,6 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
});
const createdAt = new Date().toISOString();
const pageLayoutWidgetId = v4();
const {
pageLayoutTabUniversalIdentifier,
@@ -53,22 +50,16 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
});
return {
id: pageLayoutWidgetId,
pageLayoutTabId,
pageLayoutTabUniversalIdentifier,
workspaceId,
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: pageLayoutWidgetId,
universalIdentifier: v4(),
title: createPageLayoutWidgetInput.title,
type: createPageLayoutWidgetInput.type,
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
objectMetadataUniversalIdentifier,
gridPosition: createPageLayoutWidgetInput.gridPosition,
position: createPageLayoutWidgetInput.position ?? null,
configuration: createPageLayoutWidgetInput.configuration,
applicationId: flatApplication.id,
applicationUniversalIdentifier: flatApplication.universalIdentifier,
conditionalDisplay: null,
universalConfiguration:
@@ -4,22 +4,20 @@ import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
import { type CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import { type UniversalFlatPageLayout } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout.type';
export type FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs = {
createPageLayoutInput: CreatePageLayoutInput;
workspaceId: string;
flatApplication: FlatApplication;
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
createPageLayoutInput: rawCreatePageLayoutInput,
workspaceId,
flatApplication,
flatObjectMetadataMaps,
}: FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs): FlatPageLayout => {
}: FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs): UniversalFlatPageLayout => {
const createPageLayoutInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreatePageLayoutInput,
@@ -27,7 +25,6 @@ export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
);
const createdAt = new Date().toISOString();
const pageLayoutId = v4();
const { objectMetadataUniversalIdentifier } =
resolveEntityRelationUniversalIdentifiers({
@@ -39,21 +36,15 @@ export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
});
return {
id: pageLayoutId,
name: createPageLayoutInput.name,
type: createPageLayoutInput.type ?? PageLayoutType.RECORD_PAGE,
objectMetadataId: createPageLayoutInput.objectMetadataId ?? null,
objectMetadataUniversalIdentifier,
workspaceId,
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: pageLayoutId,
applicationId: flatApplication.id,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
tabIds: [],
tabUniversalIdentifiers: [],
defaultTabToFocusOnMobileAndSidePanelId: null,
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier: null,
};
};
@@ -2,33 +2,25 @@ import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'tw
import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
import { type CreateRoleInput } from 'src/engine/metadata-modules/role/dtos/create-role-input.dto';
import { type UniversalFlatRole } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-role.type';
export const fromCreateRoleInputToFlatRoleToCreate = ({
createRoleInput,
workspaceId,
flatApplication,
}: {
createRoleInput: CreateRoleInput;
workspaceId: string;
flatApplication: FlatApplication;
}): FlatRole => {
}): UniversalFlatRole => {
const now = new Date().toISOString();
const {
label,
description,
icon,
id: inputId,
} = trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
createRoleInput,
['description', 'icon', 'id', 'label'],
);
const id = inputId ?? v4();
const { label, description, icon } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
createRoleInput,
['description', 'icon', 'id', 'label'],
);
return {
id,
label,
description: description ?? null,
icon: icon ?? null,
@@ -45,20 +37,12 @@ export const fromCreateRoleInputToFlatRoleToCreate = ({
canBeAssignedToAgents: createRoleInput.canBeAssignedToAgents ?? true,
canBeAssignedToApiKeys: createRoleInput.canBeAssignedToApiKeys ?? true,
isEditable: true,
workspaceId,
createdAt: now,
updatedAt: now,
universalIdentifier: createRoleInput.universalIdentifier ?? v4(),
applicationId: flatApplication.id,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
roleTargetIds: [],
roleTargetUniversalIdentifiers: [],
objectPermissionIds: [],
permissionFlagIds: [],
fieldPermissionIds: [],
rowLevelPermissionPredicateIds: [],
rowLevelPermissionPredicateUniversalIdentifiers: [],
rowLevelPermissionPredicateGroupIds: [],
rowLevelPermissionPredicateGroupUniversalIdentifiers: [],
};
};
@@ -81,7 +81,7 @@ export const fromCreateViewInputToFlatViewToCreate = ({
openRecordIn: createViewInput.openRecordIn ?? ViewOpenRecordIn.SIDE_PANEL,
position: createViewInput.position ?? 0,
type: createViewInput.type ?? ViewType.TABLE,
universalIdentifier: createViewInput.universalIdentifier ?? v4(),
universalIdentifier: v4(),
visibility: createViewInput.visibility ?? ViewVisibility.WORKSPACE,
createdByUserWorkspaceId: createdByUserWorkspaceId ?? null,
viewFieldUniversalIdentifiers: [],
@@ -2,19 +2,17 @@ import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'tw
import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type FlatWebhook } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook.type';
import { type CreateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/create-webhook.input';
import { generateWebhookSecret } from 'src/engine/metadata-modules/webhook/utils/generate-webhook-secret.util';
import { type UniversalFlatWebhook } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-webhook.type';
export const fromCreateWebhookInputToFlatWebhookToCreate = ({
createWebhookInput,
workspaceId,
flatApplication,
}: {
createWebhookInput: CreateWebhookInput;
workspaceId: string;
flatApplication: FlatApplication;
}): FlatWebhook => {
}): UniversalFlatWebhook => {
const now = new Date().toISOString();
const { targetUrl, description } =
@@ -23,21 +21,17 @@ export const fromCreateWebhookInputToFlatWebhookToCreate = ({
['targetUrl', 'description'],
);
const id = createWebhookInput.id ?? v4();
const secret = createWebhookInput.secret ?? generateWebhookSecret();
return {
id,
targetUrl,
operations: createWebhookInput.operations,
description: description ?? null,
secret,
workspaceId,
createdAt: now,
updatedAt: now,
deletedAt: null,
universalIdentifier: id,
applicationId: flatApplication.id,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
};
};
@@ -1,4 +1,4 @@
import { Field, HideField, InputType } from '@nestjs/graphql';
import { Field, InputType } from '@nestjs/graphql';
import { IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
@@ -11,11 +11,6 @@ export class CreateFrontComponentInput {
@Field(() => UUIDScalarType, { nullable: true })
id?: string;
@IsUUID()
@IsOptional()
@HideField()
universalIdentifier?: string;
@IsString()
@IsOptional()
@Field()
@@ -10,6 +10,7 @@ import { type FlatApplication } from 'src/engine/core-modules/application/types/
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
import { fromCreateFrontComponentInputToFlatFrontComponentToCreate } from 'src/engine/metadata-modules/flat-front-component/utils/from-create-front-component-input-to-flat-front-component-to-create.util';
@@ -93,7 +94,6 @@ export class FrontComponentService {
const flatFrontComponentToCreate =
fromCreateFrontComponentInputToFlatFrontComponentToCreate({
createFrontComponentInput: input,
workspaceId,
flatApplication: resolvedOwnerFlatApplication,
});
@@ -129,8 +129,8 @@ export class FrontComponentService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatFrontComponentToCreate.id,
return findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatFrontComponentToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatFrontComponentMaps,
});
}
@@ -29,11 +29,6 @@ export class CreateLogicFunctionFromSourceInput {
@Field(() => UUIDScalarType, { nullable: true })
id?: string;
@IsUUID()
@IsOptional()
@Field(() => UUIDScalarType, { nullable: true })
universalIdentifier?: string;
@IsString()
@IsNotEmpty()
@Field()
@@ -7,6 +7,7 @@ import { type FlatApplication } from 'src/engine/core-modules/application/types/
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-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 { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import {
LogicFunctionException,
LogicFunctionExceptionCode,
@@ -85,7 +86,7 @@ export class LogicFunctionMetadataService {
input: CreateLogicFunction;
ownerFlatApplication: FlatApplication;
workspaceId: string;
}) {
}): Promise<FlatLogicFunction> {
const resolvedOwnerFlatApplication =
ownerFlatApplication ??
(
@@ -97,7 +98,6 @@ export class LogicFunctionMetadataService {
const flatLogicFunctionToCreate =
fromCreateLogicFunctionInputToFlatLogicFunction({
createLogicFunctionInput: input,
workspaceId,
ownerFlatApplication: resolvedOwnerFlatApplication,
});
@@ -125,7 +125,18 @@ export class LogicFunctionMetadataService {
);
}
return flatLogicFunctionToCreate;
const { flatLogicFunctionMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatLogicFunctionMaps'],
},
);
return findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatLogicFunctionToCreate.universalIdentifier,
flatEntityMaps: flatLogicFunctionMaps,
});
}
async updateOne({
@@ -1,29 +1,22 @@
import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { LogicFunctionRuntime } 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 CreateLogicFunction } from 'src/engine/metadata-modules/logic-function/dtos/create-logic-function.input';
import { LogicFunctionRuntime } from 'src/engine/metadata-modules/logic-function/logic-function.entity';
import { type UniversalFlatLogicFunction } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-logic-function.type';
export type FromCreateLogicFunctionInputToFlatLogicFunctionArgs = {
createLogicFunctionInput: CreateLogicFunction;
workspaceId: string;
ownerFlatApplication: FlatApplication;
};
export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
createLogicFunctionInput: rawCreateLogicFunctionInput,
workspaceId,
ownerFlatApplication,
}: FromCreateLogicFunctionInputToFlatLogicFunctionArgs): FlatLogicFunction => {
const id = rawCreateLogicFunctionInput.id ?? v4();
}: FromCreateLogicFunctionInputToFlatLogicFunctionArgs): UniversalFlatLogicFunction => {
const currentDate = new Date();
const universalIdentifier =
rawCreateLogicFunctionInput.universalIdentifier ?? v4();
return {
id,
cronTriggerSettings:
rawCreateLogicFunctionInput.cronTriggerSettings ?? null,
databaseEventTriggerSettings:
@@ -35,14 +28,12 @@ export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
sourceHandlerPath: rawCreateLogicFunctionInput.sourceHandlerPath,
handlerName: rawCreateLogicFunctionInput.handlerName,
builtHandlerPath: rawCreateLogicFunctionInput.builtHandlerPath,
universalIdentifier,
universalIdentifier: v4(),
createdAt: currentDate.toISOString(),
updatedAt: currentDate.toISOString(),
deletedAt: null,
applicationId: ownerFlatApplication.id,
runtime: LogicFunctionRuntime.NODE22,
timeoutSeconds: rawCreateLogicFunctionInput.timeoutSeconds ?? 300,
workspaceId,
checksum: rawCreateLogicFunctionInput.checksum ?? null,
toolInputSchema: rawCreateLogicFunctionInput.toolInputSchema ?? null,
isTool: rawCreateLogicFunctionInput?.isTool ?? false,
@@ -14,6 +14,7 @@ import { getRecordImageIdentifier } from 'src/engine/core-modules/record-crud/ut
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-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 { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/from-create-navigation-menu-item-input-to-flat-navigation-menu-item-to-create.util';
import { fromDeleteNavigationMenuItemInputToFlatNavigationMenuItemOrThrow } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/from-delete-navigation-menu-item-input-to-flat-navigation-menu-item-or-throw.util';
import { fromFlatNavigationMenuItemToNavigationMenuItemDto } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/from-flat-navigation-menu-item-to-navigation-menu-item-dto.util';
@@ -174,7 +175,6 @@ export class NavigationMenuItemService {
const flatNavigationMenuItemToCreate =
fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate({
createNavigationMenuItemInput: normalizedInput,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps,
flatObjectMetadataMaps,
@@ -214,8 +214,8 @@ export class NavigationMenuItemService {
);
return fromFlatNavigationMenuItemToNavigationMenuItemDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatNavigationMenuItemToCreate.id,
findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatNavigationMenuItemToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatNavigationMenuItemMaps,
}),
);
@@ -6,6 +6,7 @@ import { ApplicationService } from 'src/engine/core-modules/application/services
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
import { fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate } from 'src/engine/metadata-modules/flat-page-layout-tab/utils/from-create-page-layout-tab-input-to-flat-page-layout-tab-to-create.util';
import { fromDestroyPageLayoutTabInputToFlatPageLayoutTabOrThrow } from 'src/engine/metadata-modules/flat-page-layout-tab/utils/from-destroy-page-layout-tab-input-to-flat-page-layout-tab-or-throw.util';
@@ -151,7 +152,6 @@ export class PageLayoutTabService {
const flatPageLayoutTabToCreate =
fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate({
createPageLayoutTabInput,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatPageLayoutMaps: existingFlatPageLayoutMaps,
});
@@ -188,13 +188,13 @@ export class PageLayoutTabService {
},
);
const createdTab = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPageLayoutTabToCreate.id,
const createdTab = findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatPageLayoutTabToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatPageLayoutTabMaps,
});
await this.dashboardSyncService.updateLinkedDashboardsUpdatedAtByTabId({
tabId: flatPageLayoutTabToCreate.id,
tabId: createdTab.id,
workspaceId,
updatedAt: new Date(createdTab.updatedAt),
});
@@ -6,6 +6,7 @@ import { ApplicationService } from 'src/engine/core-modules/application/services
import { transformRichTextV2Value } from 'src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
@@ -32,10 +33,11 @@ import { isChartFieldsForValidation } from 'src/engine/metadata-modules/page-lay
import { validateChartConfigurationFieldReferences } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-chart-configuration-field-references.util';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
import { type UniversalFlatPageLayoutWidget } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-widget.type';
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
type WidgetMigrationOperations = {
flatEntityToCreate: FlatPageLayoutWidget[];
flatEntityToCreate: UniversalFlatPageLayoutWidget[];
flatEntityToUpdate: FlatPageLayoutWidget[];
flatEntityToDelete: FlatPageLayoutWidget[];
};
@@ -258,7 +260,6 @@ export class PageLayoutWidgetService {
const flatPageLayoutWidgetToCreate =
fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate({
createPageLayoutWidgetInput: createInput,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatPageLayoutTabMaps,
flatObjectMetadataMaps,
@@ -287,13 +288,13 @@ export class PageLayoutWidgetService {
const recomputedMaps = await this.getFlatPageLayoutWidgetMaps(workspaceId);
const createdWidget = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPageLayoutWidgetToCreate.id,
const createdWidget = findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatPageLayoutWidgetToCreate.universalIdentifier,
flatEntityMaps: recomputedMaps,
});
await this.dashboardSyncService.updateLinkedDashboardsUpdatedAtByWidgetId({
widgetId: flatPageLayoutWidgetToCreate.id,
widgetId: createdWidget.id,
workspaceId,
updatedAt: new Date(createdWidget.updatedAt),
});
@@ -1,24 +1,20 @@
import { Injectable } from '@nestjs/common';
import { PageLayoutTabLayoutMode } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-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 { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate } from 'src/engine/metadata-modules/flat-page-layout-tab/utils/from-create-page-layout-tab-input-to-flat-page-layout-tab-to-create.util';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util';
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
import { fromCreatePageLayoutInputToFlatPageLayoutToCreate } from 'src/engine/metadata-modules/flat-page-layout/utils/from-create-page-layout-input-to-flat-page-layout-to-create.util';
import { reconstructFlatPageLayoutWithTabsAndWidgets } from 'src/engine/metadata-modules/flat-page-layout/utils/reconstruct-flat-page-layout-with-tabs-and-widgets.util';
import { type PageLayoutDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout.dto';
import {
@@ -30,6 +26,9 @@ import {
import { fromFlatPageLayoutWithTabsAndWidgetsToPageLayoutDto } from 'src/engine/metadata-modules/page-layout/utils/from-flat-page-layout-with-tabs-and-widgets-to-page-layout-dto.util';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
import { type UniversalFlatPageLayout } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout.type';
import { type UniversalFlatPageLayoutTab } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-tab.type';
import { type UniversalFlatPageLayoutWidget } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-widget.type';
@Injectable()
export class PageLayoutDuplicationService {
@@ -50,8 +49,6 @@ export class PageLayoutDuplicationService {
flatPageLayoutMaps,
flatPageLayoutTabMaps,
flatPageLayoutWidgetMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
} = await this.getPageLayoutFlatEntityMaps(workspaceId);
const originalFlatLayout = this.findOriginalLayoutOrThrow(
@@ -70,50 +67,29 @@ export class PageLayoutDuplicationService {
{ workspaceId },
);
const newFlatPageLayout = fromCreatePageLayoutInputToFlatPageLayoutToCreate(
{
createPageLayoutInput: {
name: originalFlatLayout.name,
type: originalFlatLayout.type,
objectMetadataId: originalFlatLayout.objectMetadataId,
},
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatObjectMetadataMaps,
},
);
const now = new Date().toISOString();
const optimisticFlatPageLayoutMaps = addFlatEntityToFlatEntityMapsOrThrow({
flatEntity: newFlatPageLayout,
flatEntityMaps: createEmptyFlatEntityMaps(),
const newFlatPageLayout = this.buildDuplicatedPageLayout({
originalFlatLayout,
flatApplication: workspaceCustomFlatApplication,
now,
});
const { newFlatTabs, originalTabIdToNewTabIdMap } =
this.createDuplicatedTabs({
originalTabs: originalTabsWithWidgets.map(({ tab }) => tab),
newPageLayoutId: newFlatPageLayout.id,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatPageLayoutMaps: optimisticFlatPageLayoutMaps,
});
const optimisticFlatPageLayoutTabMaps = newFlatTabs.reduce(
(maps, flatTab) =>
addFlatEntityToFlatEntityMapsOrThrow({
flatEntity: flatTab,
flatEntityMaps: maps,
}),
createEmptyFlatEntityMaps(),
);
const newFlatWidgets = this.createDuplicatedWidgets({
originalTabsWithWidgets,
originalTabIdToNewTabIdMap,
workspaceId,
const {
newFlatTabs,
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap,
} = this.buildDuplicatedTabs({
originalTabs: originalTabsWithWidgets.map(({ tab }) => tab),
newPageLayoutUniversalIdentifier: newFlatPageLayout.universalIdentifier,
flatApplication: workspaceCustomFlatApplication,
flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
now,
});
const newFlatWidgets = this.buildDuplicatedWidgets({
originalTabsWithWidgets,
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap,
flatApplication: workspaceCustomFlatApplication,
now,
});
const validateAndBuildResult =
@@ -158,8 +134,8 @@ export class PageLayoutDuplicationService {
const newFlatLayoutWithTabsAndWidgets =
reconstructFlatPageLayoutWithTabsAndWidgets({
layout: findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: newFlatPageLayout.id,
layout: findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: newFlatPageLayout.universalIdentifier,
flatEntityMaps: recomputedFlatPageLayoutMaps,
}),
flatPageLayoutTabMaps: recomputedFlatPageLayoutTabMaps,
@@ -243,84 +219,128 @@ export class PageLayoutDuplicationService {
}));
}
private createDuplicatedTabs({
originalTabs,
newPageLayoutId,
workspaceId,
private buildDuplicatedPageLayout({
originalFlatLayout,
flatApplication,
flatPageLayoutMaps,
now,
}: {
originalTabs: FlatPageLayoutTab[];
newPageLayoutId: string;
workspaceId: string;
originalFlatLayout: FlatPageLayout;
flatApplication: FlatApplication;
flatPageLayoutMaps: AllFlatEntityMaps['flatPageLayoutMaps'];
}): {
newFlatTabs: FlatPageLayoutTab[];
originalTabIdToNewTabIdMap: Map<string, string>;
} {
const originalTabIdToNewTabIdMap = new Map<string, string>();
const newFlatTabs = originalTabs.map((originalTab) => {
const newFlatTab =
fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate({
createPageLayoutTabInput: {
title: originalTab.title,
position: originalTab.position,
pageLayoutId: newPageLayoutId,
},
workspaceId,
flatApplication,
flatPageLayoutMaps,
});
originalTabIdToNewTabIdMap.set(originalTab.id, newFlatTab.id);
return newFlatTab;
});
return { newFlatTabs, originalTabIdToNewTabIdMap };
now: string;
}): UniversalFlatPageLayout {
return {
name: originalFlatLayout.name,
type: originalFlatLayout.type,
objectMetadataUniversalIdentifier:
originalFlatLayout.objectMetadataUniversalIdentifier,
createdAt: now,
updatedAt: now,
deletedAt: null,
universalIdentifier: v4(),
applicationUniversalIdentifier: flatApplication.universalIdentifier,
tabUniversalIdentifiers: [],
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier: null,
};
}
private createDuplicatedWidgets({
originalTabsWithWidgets,
originalTabIdToNewTabIdMap,
workspaceId,
private buildDuplicatedTabs({
originalTabs,
newPageLayoutUniversalIdentifier,
flatApplication,
flatPageLayoutTabMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
now,
}: {
originalTabs: FlatPageLayoutTab[];
newPageLayoutUniversalIdentifier: string;
flatApplication: FlatApplication;
now: string;
}): {
newFlatTabs: UniversalFlatPageLayoutTab[];
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap: Map<
string,
string
>;
} {
const originalTabUniversalIdentifierToNewTabUniversalIdentifierMap =
new Map<string, string>();
const newFlatTabs = originalTabs.map((originalTab) => {
const newUniversalIdentifier = v4();
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap.set(
originalTab.universalIdentifier,
newUniversalIdentifier,
);
return {
title: originalTab.title,
position: originalTab.position,
pageLayoutUniversalIdentifier: newPageLayoutUniversalIdentifier,
createdAt: now,
updatedAt: now,
deletedAt: null,
universalIdentifier: newUniversalIdentifier,
applicationUniversalIdentifier: flatApplication.universalIdentifier,
widgetUniversalIdentifiers: [],
icon: originalTab.icon ?? null,
layoutMode: originalTab.layoutMode ?? PageLayoutTabLayoutMode.GRID,
} satisfies UniversalFlatPageLayoutTab;
});
return {
newFlatTabs,
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap,
};
}
private buildDuplicatedWidgets({
originalTabsWithWidgets,
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap,
flatApplication,
now,
}: {
originalTabsWithWidgets: {
tab: FlatPageLayoutTab;
widgets: FlatPageLayoutWidget[];
}[];
originalTabIdToNewTabIdMap: Map<string, string>;
workspaceId: string;
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap: Map<
string,
string
>;
flatApplication: FlatApplication;
flatPageLayoutTabMaps: AllFlatEntityMaps['flatPageLayoutTabMaps'];
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps'];
}): FlatPageLayoutWidget[] {
now: string;
}): UniversalFlatPageLayoutWidget[] {
return originalTabsWithWidgets.flatMap(({ tab, widgets }) => {
const newTabId = originalTabIdToNewTabIdMap.get(tab.id)!;
const newTabUniversalIdentifier =
originalTabUniversalIdentifierToNewTabUniversalIdentifierMap.get(
tab.universalIdentifier,
);
return widgets.map((originalWidget) =>
fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate({
createPageLayoutWidgetInput: {
if (!isDefined(newTabUniversalIdentifier)) {
throw new PageLayoutException(
`Could not find duplicated tab for original tab ${tab.universalIdentifier}`,
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
);
}
return widgets.map(
(originalWidget) =>
({
pageLayoutTabUniversalIdentifier: newTabUniversalIdentifier,
createdAt: now,
updatedAt: now,
deletedAt: null,
universalIdentifier: v4(),
title: originalWidget.title,
gridPosition: originalWidget.gridPosition,
type: originalWidget.type,
objectMetadataId: originalWidget.objectMetadataId,
configuration: originalWidget.configuration,
pageLayoutTabId: newTabId,
},
workspaceId,
flatApplication,
flatPageLayoutTabMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
}),
objectMetadataUniversalIdentifier:
originalWidget.objectMetadataUniversalIdentifier,
gridPosition: originalWidget.gridPosition,
position: originalWidget.position ?? null,
applicationUniversalIdentifier: flatApplication.universalIdentifier,
conditionalDisplay: null,
universalConfiguration:
originalWidget.universalConfiguration ?? null,
}) satisfies UniversalFlatPageLayoutWidget,
);
});
}
@@ -6,6 +6,7 @@ import { isDefined } from 'twenty-shared/utils';
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
@@ -201,7 +202,6 @@ export class PageLayoutService {
const flatPageLayoutToCreate =
fromCreatePageLayoutInputToFlatPageLayoutToCreate({
createPageLayoutInput,
workspaceId,
flatApplication: workspaceCustomFlatApplication,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
});
@@ -239,8 +239,8 @@ export class PageLayoutService {
);
return fromFlatPageLayoutToPageLayoutDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPageLayoutToCreate.id,
findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatPageLayoutToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatPageLayoutMaps,
}),
);
@@ -10,6 +10,7 @@ import { type FlatApplication } from 'src/engine/core-modules/application/types/
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { fromCreateRoleInputToFlatRoleToCreate } from 'src/engine/metadata-modules/flat-role/utils/from-create-role-input-to-flat-role-to-create.util';
import { fromDeleteRoleInputToFlatRoleOrThrow } from 'src/engine/metadata-modules/flat-role/utils/from-delete-role-input-to-flat-role-or-throw.util';
@@ -110,7 +111,6 @@ export class RoleService {
}): Promise<RoleDTO> {
const flatRoleToCreate = fromCreateRoleInputToFlatRoleToCreate({
createRoleInput: input,
workspaceId,
flatApplication: ownerFlatApplication,
});
@@ -147,8 +147,8 @@ export class RoleService {
);
return fromFlatRoleToRoleDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatRoleToCreate.id,
findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatRoleToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatRoleMaps,
}),
);
@@ -1,4 +1,4 @@
import { Field, HideField, InputType } from '@nestjs/graphql';
import { Field, InputType } from '@nestjs/graphql';
import {
IsBoolean,
@@ -108,10 +108,4 @@ export class CreateViewInput {
nullable: true,
})
visibility?: ViewVisibility;
@HideField()
universalIdentifier?: string;
@HideField()
applicationId?: string;
}
@@ -8,6 +8,7 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { fromCreateWebhookInputToFlatWebhookToCreate } from 'src/engine/metadata-modules/flat-webhook/utils/from-create-webhook-input-to-flat-webhook-to-create.util';
import { fromDeleteWebhookInputToFlatWebhookOrThrow } from 'src/engine/metadata-modules/flat-webhook/utils/from-delete-webhook-input-to-flat-webhook-or-throw.util';
import { fromFlatWebhookToWebhookDto } from 'src/engine/metadata-modules/flat-webhook/utils/from-flat-webhook-to-webhook-dto.util';
@@ -110,7 +111,6 @@ export class WebhookService {
...input,
targetUrl: normalizedTargetUrl,
},
workspaceId,
flatApplication: workspaceCustomFlatApplication,
});
@@ -146,8 +146,8 @@ export class WebhookService {
);
return fromFlatWebhookToWebhookDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatWebhookToCreate.id,
findFlatEntityByUniversalIdentifierOrThrow({
universalIdentifier: flatWebhookToCreate.universalIdentifier,
flatEntityMaps: recomputedFlatWebhookMaps,
}),
);
@@ -126,7 +126,6 @@ export class CodeStepBuildService {
| JsonbProperty<HttpRouteTriggerSettings>
| undefined,
},
workspaceId,
ownerFlatApplication: resolvedOwnerFlatApplication,
});