Add sync front component (#17748)
## Context Allow twenty apps to sync front components
This commit is contained in:
+1
@@ -20,6 +20,7 @@ export class ApplicationExceptionFilter implements ExceptionFilter {
|
||||
case ApplicationExceptionCode.ENTITY_NOT_FOUND:
|
||||
case ApplicationExceptionCode.APPLICATION_NOT_FOUND:
|
||||
case ApplicationExceptionCode.LOGIC_FUNCTION_NOT_FOUND:
|
||||
case ApplicationExceptionCode.FRONT_COMPONENT_NOT_FOUND:
|
||||
throw new NotFoundError(exception);
|
||||
case ApplicationExceptionCode.FORBIDDEN:
|
||||
case ApplicationExceptionCode.INVALID_INPUT:
|
||||
|
||||
+3
-1
@@ -11,6 +11,7 @@ import { FileEntity } from 'src/engine/core-modules/file/entities/file.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { FrontComponentModule } from 'src/engine/metadata-modules/front-component/front-component.module';
|
||||
import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { ObjectPermissionModule } from 'src/engine/metadata-modules/object-permission/object-permission.module';
|
||||
@@ -21,8 +22,8 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/workspace-migration-runner.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
|
||||
import { CodeStepBuildModule } from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/code-step-build.module';
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { CodeStepBuildModule } from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/code-step-build.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -44,6 +45,7 @@ import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-commo
|
||||
FileStorageModule,
|
||||
WorkspaceCacheModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
FrontComponentModule,
|
||||
],
|
||||
providers: [
|
||||
ApplicationResolver,
|
||||
|
||||
@@ -8,6 +8,7 @@ export enum ApplicationExceptionCode {
|
||||
OBJECT_NOT_FOUND = 'OBJECT_NOT_FOUND',
|
||||
FIELD_NOT_FOUND = 'FIELD_NOT_FOUND',
|
||||
LOGIC_FUNCTION_NOT_FOUND = 'LOGIC_FUNCTION_NOT_FOUND',
|
||||
FRONT_COMPONENT_NOT_FOUND = 'FRONT_COMPONENT_NOT_FOUND',
|
||||
ENTITY_NOT_FOUND = 'ENTITY_NOT_FOUND',
|
||||
APPLICATION_NOT_FOUND = 'APPLICATION_NOT_FOUND',
|
||||
FORBIDDEN = 'FORBIDDEN',
|
||||
@@ -24,6 +25,8 @@ const getApplicationExceptionUserFriendlyMessage = (
|
||||
return msg`Field not found.`;
|
||||
case ApplicationExceptionCode.LOGIC_FUNCTION_NOT_FOUND:
|
||||
return msg`Logic function not found.`;
|
||||
case ApplicationExceptionCode.FRONT_COMPONENT_NOT_FOUND:
|
||||
return msg`Front component not found.`;
|
||||
case ApplicationExceptionCode.ENTITY_NOT_FOUND:
|
||||
return msg`Entity not found.`;
|
||||
case ApplicationExceptionCode.APPLICATION_NOT_FOUND:
|
||||
|
||||
+109
@@ -4,6 +4,7 @@ import { parse } from 'path';
|
||||
|
||||
import {
|
||||
FieldManifest,
|
||||
FrontComponentManifest,
|
||||
LogicFunctionManifest,
|
||||
Manifest,
|
||||
ObjectFieldManifest,
|
||||
@@ -34,7 +35,9 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ
|
||||
import { findFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entities-by-application-id.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { FrontComponentService } from 'src/engine/metadata-modules/front-component/front-component.service';
|
||||
import { LogicFunctionService } from 'src/engine/metadata-modules/logic-function/services/logic-function.service';
|
||||
import { FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
@@ -64,6 +67,7 @@ export class ApplicationSyncService {
|
||||
private readonly fieldPermissionService: FieldPermissionService,
|
||||
private readonly permissionService: PermissionFlagService,
|
||||
private readonly fileStorageService: FileStorageService,
|
||||
private readonly frontComponentService: FrontComponentService,
|
||||
) {}
|
||||
|
||||
public async synchronizeFromManifest({
|
||||
@@ -108,6 +112,14 @@ export class ApplicationSyncService {
|
||||
});
|
||||
}
|
||||
|
||||
if ((manifest.frontComponents ?? []).length > 0) {
|
||||
await this.syncFrontComponents({
|
||||
frontComponentsToSync: manifest.frontComponents,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
await this.syncRoles({
|
||||
manifest,
|
||||
workspaceId,
|
||||
@@ -948,6 +960,103 @@ export class ApplicationSyncService {
|
||||
}
|
||||
}
|
||||
|
||||
private async syncFrontComponents({
|
||||
frontComponentsToSync,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
frontComponentsToSync: FrontComponentManifest[];
|
||||
workspaceId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
const { flatFrontComponentMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatFrontComponentMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const applicationFrontComponents = Object.values(
|
||||
flatFrontComponentMaps.byUniversalIdentifier,
|
||||
).filter(
|
||||
(frontComponent) =>
|
||||
isDefined(frontComponent) &&
|
||||
frontComponent.applicationId === ownerFlatApplication.id,
|
||||
) as FlatFrontComponent[];
|
||||
|
||||
const frontComponentsToSyncUniversalIdentifiers = frontComponentsToSync.map(
|
||||
(frontComponent) => frontComponent.universalIdentifier,
|
||||
);
|
||||
|
||||
const applicationFrontComponentsUniversalIdentifiers =
|
||||
applicationFrontComponents.map(
|
||||
(frontComponent) => frontComponent.universalIdentifier,
|
||||
);
|
||||
|
||||
const frontComponentsToDelete = applicationFrontComponents.filter(
|
||||
(frontComponent) =>
|
||||
isDefined(frontComponent.universalIdentifier) &&
|
||||
!frontComponentsToSyncUniversalIdentifiers.includes(
|
||||
frontComponent.universalIdentifier,
|
||||
),
|
||||
);
|
||||
|
||||
const frontComponentsToUpdate = applicationFrontComponents.filter(
|
||||
(frontComponent) =>
|
||||
isDefined(frontComponent.universalIdentifier) &&
|
||||
frontComponentsToSyncUniversalIdentifiers.includes(
|
||||
frontComponent.universalIdentifier,
|
||||
),
|
||||
);
|
||||
|
||||
const frontComponentsToCreate = frontComponentsToSync.filter(
|
||||
(frontComponentToSync) =>
|
||||
!applicationFrontComponentsUniversalIdentifiers.includes(
|
||||
frontComponentToSync.universalIdentifier,
|
||||
),
|
||||
);
|
||||
|
||||
for (const frontComponentToDelete of frontComponentsToDelete) {
|
||||
await this.frontComponentService.destroyOne({
|
||||
id: frontComponentToDelete.id,
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
for (const frontComponentToUpdate of frontComponentsToUpdate) {
|
||||
const frontComponentToSync = frontComponentsToSync.find(
|
||||
(frontComponent) =>
|
||||
frontComponent.universalIdentifier ===
|
||||
frontComponentToUpdate.universalIdentifier,
|
||||
);
|
||||
|
||||
if (!frontComponentToSync) {
|
||||
throw new ApplicationException(
|
||||
`Failed to find frontComponent to sync with universalIdentifier ${frontComponentToUpdate.universalIdentifier}`,
|
||||
ApplicationExceptionCode.FRONT_COMPONENT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.frontComponentService.updateOne({
|
||||
id: frontComponentToUpdate.id,
|
||||
update: frontComponentToSync,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
for (const frontComponentToCreate of frontComponentsToCreate) {
|
||||
await this.frontComponentService.createOne({
|
||||
input: frontComponentToCreate,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async uninstallApplication({
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
|
||||
Reference in New Issue
Block a user