Rework types for logic function (#18074)

## Summary

- **Consolidate logic function services**: Remove
`LogicFunctionMetadataService` and consolidate all logic function CRUD
operations into `LogicFunctionFromSourceService`, with a new
`LogicFunctionFromSourceHelperService` for shared validation/migration
logic
- **Introduce typed conversion utils following the skill pattern**: Add
`fromCreateLogicFunctionFromSourceInputToUniversalFlatLogicFunctionToCreate`
and `fromUpdateLogicFunctionFromSourceInputToFlatLogicFunctionToUpdate`
that convert DTO inputs directly to flat entities
(`UniversalFlatLogicFunction` / `FlatLogicFunction`), replacing the
previous intermediate `UpdateLogicFunctionMetadataParams` indirection
- **Simplify `CodeStepBuildService`**: Remove ~100 lines of manual
duplication logic by delegating to
`LogicFunctionFromSourceService.duplicateOneWithSource`
- **Remove completed 1-17 migration**: Delete
`MigrateWorkflowCodeStepsCommand` and associated utils that migrated
workflow code steps from serverless functions to logic functions
This commit is contained in:
Charles Bochet
2026-02-19 17:25:08 +01:00
committed by GitHub
parent 0e25aeb5be
commit 10bd005021
22 changed files with 654 additions and 1343 deletions
@@ -14,19 +14,22 @@ import { FeatureFlagGuard } from 'src/engine/guards/feature-flag.guard';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { CreateLogicFunctionFromSourceInput } from 'src/engine/metadata-modules/logic-function/dtos/create-logic-function-from-source.input';
import { ExecuteOneLogicFunctionInput } from 'src/engine/metadata-modules/logic-function/dtos/execute-logic-function.input';
import { LogicFunctionExecutionResultDTO } from 'src/engine/metadata-modules/logic-function/dtos/logic-function-execution-result.dto';
import { LogicFunctionIdInput } from 'src/engine/metadata-modules/logic-function/dtos/logic-function-id.input';
import { LogicFunctionLogsDTO } from 'src/engine/metadata-modules/logic-function/dtos/logic-function-logs.dto';
import { LogicFunctionLogsInput } from 'src/engine/metadata-modules/logic-function/dtos/logic-function-logs.input';
import { LogicFunctionDTO } from 'src/engine/metadata-modules/logic-function/dtos/logic-function.dto';
import { UpdateLogicFunctionFromSourceInput } from 'src/engine/metadata-modules/logic-function/dtos/update-logic-function-from-source.input';
import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
import { findFlatLogicFunctionOrThrow } from 'src/engine/metadata-modules/logic-function/utils/find-flat-logic-function-or-throw.util';
import { fromFlatLogicFunctionToLogicFunctionDto } from 'src/engine/metadata-modules/logic-function/utils/from-flat-logic-function-to-logic-function-dto.util';
import { logicFunctionGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/logic-function/utils/logic-function-graphql-api-exception-handler.utils';
import { SubscriptionChannel } from 'src/engine/subscriptions/enums/subscription-channel.enum';
import { SubscriptionService } from 'src/engine/subscriptions/subscription.service';
import { CreateLogicFunctionFromSourceInput } from 'src/engine/metadata-modules/logic-function/dtos/create-logic-function-from-source.input';
import { UpdateLogicFunctionFromSourceInput } from 'src/engine/metadata-modules/logic-function/dtos/update-logic-function-from-source.input';
import { LogicFunctionMetadataService } from 'src/engine/metadata-modules/logic-function/services/logic-function-metadata.service';
@UseGuards(WorkspaceAuthGuard, FeatureFlagGuard, NoPermissionGuard)
@MetadataResolver()
@@ -35,7 +38,7 @@ import { LogicFunctionMetadataService } from 'src/engine/metadata-modules/logic-
export class LogicFunctionResolver {
constructor(
private readonly logicFunctionFromSourceService: LogicFunctionFromSourceService,
private readonly logicFunctionMetadataService: LogicFunctionMetadataService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly subscriptionService: SubscriptionService,
) {}
@@ -45,10 +48,20 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<LogicFunctionDTO> {
try {
return await this.logicFunctionMetadataService.findOne({
const { flatLogicFunctionMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatLogicFunctionMaps'],
},
);
const flatLogicFunction = findFlatLogicFunctionOrThrow({
id,
workspaceId,
flatLogicFunctionMaps,
});
return fromFlatLogicFunctionToLogicFunctionDto({ flatLogicFunction });
} catch (error) {
return logicFunctionGraphQLApiExceptionHandler(error);
}
@@ -59,9 +72,23 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<LogicFunctionDTO[]> {
try {
return await this.logicFunctionMetadataService.findMany({
workspaceId,
});
const { flatLogicFunctionMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatLogicFunctionMaps'],
},
);
return Object.values(flatLogicFunctionMaps.byUniversalIdentifier)
.filter(
(flatLogicFunction): flatLogicFunction is FlatLogicFunction =>
isDefined(flatLogicFunction) &&
!isDefined(flatLogicFunction.deletedAt),
)
.map((flatLogicFunction) =>
fromFlatLogicFunctionToLogicFunctionDto({ flatLogicFunction }),
);
} catch (error) {
return logicFunctionGraphQLApiExceptionHandler(error);
}
@@ -74,10 +101,33 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
) {
try {
return await this.logicFunctionMetadataService.getAvailablePackages({
logicFunctionId: id,
workspaceId,
});
const { flatLogicFunctionMaps, flatApplicationMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatLogicFunctionMaps', 'flatApplicationMaps'],
},
);
const logicFunctionUniversalIdentifier =
flatLogicFunctionMaps.universalIdentifierById[id];
if (!logicFunctionUniversalIdentifier) {
return {};
}
const logicFunction =
flatLogicFunctionMaps.byUniversalIdentifier[
logicFunctionUniversalIdentifier
];
if (!logicFunction) {
return {};
}
const application = flatApplicationMaps.byId[logicFunction.applicationId];
return application?.availablePackages ?? {};
} catch (error) {
return logicFunctionGraphQLApiExceptionHandler(error);
}
@@ -90,7 +140,7 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<LogicFunctionDTO> {
try {
return await this.logicFunctionFromSourceService.deleteOne({
return await this.logicFunctionFromSourceService.deleteOneWithSource({
id,
workspaceId,
});
@@ -106,7 +156,7 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<LogicFunctionDTO> {
try {
return await this.logicFunctionFromSourceService.createOne({
return await this.logicFunctionFromSourceService.createOneFromSource({
input,
workspaceId,
});
@@ -122,7 +172,7 @@ export class LogicFunctionResolver {
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<LogicFunctionExecutionResultDTO> {
try {
return await this.logicFunctionFromSourceService.executeOne({
return await this.logicFunctionFromSourceService.executeOneFromSource({
id,
payload,
workspaceId,
@@ -151,13 +201,13 @@ export class LogicFunctionResolver {
@Mutation(() => Boolean)
@UseGuards(SettingsPermissionGuard(PermissionFlagType.WORKFLOWS))
async updateOneLogicFunction(
@Args('input') { id, update }: UpdateLogicFunctionFromSourceInput,
@Args('input')
updateLogicFunctionFromSourceInput: UpdateLogicFunctionFromSourceInput,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
): Promise<boolean> {
try {
await this.logicFunctionFromSourceService.updateOne({
id,
update,
await this.logicFunctionFromSourceService.updateOneFromSource({
updateLogicFunctionFromSourceInput,
workspaceId,
});