[GQL_VIEW_FILTER_API_BREAKING_CHANGE][WHEN_RELEASED_REQUIRES_CACHE_FLUSH] ViewFilter migration to workspace migration v2 (#15010)
# Introduction Migrating `viewFilter` to v2 in order to migrate later the field update side effect on view to v2 too ## What's done - Created flat-view-filter - flat view filter runner - flat view filter builder - create view filter service v2 and input transpilers - refactor the existing view filter resolver to fix standard ( BREAKING_CHANGE on graphql api update especially ) REST stays the same - refactored the front to consume the mutations autogenerated ## New generic tools ### Compare two flat entity Introducing a new util to compare two flat entity, it's strictly typed and will be added to the generic builder in a following PR This will ease flat entity addition as won't required to create a specific abstraction for comparison Generic builder will expect specific constant: properties to compare and properties to stringify ### Transform flat entity for comparison Forked and refactor the initial existing method for flat entity business scope and type safety ## Coverage Migrated existing integration tests to fit new contract API This PR does not add strong coverage on validation exceptions Deadlines are too short close https://github.com/twentyhq/core-team-issues/issues/1666
This commit is contained in:
+1
@@ -19,4 +19,5 @@ export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = {
|
||||
databaseEventTrigger: emptyCreatedDeletedUpdated,
|
||||
cronTrigger: emptyCreatedDeletedUpdated,
|
||||
routeTrigger: emptyCreatedDeletedUpdated,
|
||||
viewFilter: emptyCreatedDeletedUpdated,
|
||||
} as const satisfies OrchestratorActionsReport;
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = (
|
||||
): ValidationErrorResponse => {
|
||||
const emptyResponseError: ValidationErrorResponse = {
|
||||
summary: {
|
||||
invalidViewFilter: 0,
|
||||
invalidObjectMetadata: 0,
|
||||
invalidView: 0,
|
||||
invalidViewField: 0,
|
||||
@@ -31,6 +32,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = (
|
||||
databaseEventTrigger: [],
|
||||
cronTrigger: [],
|
||||
routeTrigger: [],
|
||||
viewFilter: [],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+37
@@ -20,6 +20,7 @@ import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/work
|
||||
import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service';
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationBuildOrchestratorService {
|
||||
@@ -28,6 +29,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
private readonly workspaceMigrationV2IndexActionsBuilderService: WorkspaceMigrationV2IndexActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ViewActionsBuilderService: WorkspaceMigrationV2ViewActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ViewFieldActionsBuilderService: WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ViewFilterActionsBuilderService: WorkspaceMigrationV2ViewFilterActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ServerlessFunctionActionsBuilderService: WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
private readonly workspaceMigrationV2DatabaseEventTriggerActionsBuilderService: WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
private readonly workspaceMigrationV2CronTriggerActionsBuilderService: WorkspaceMigrationV2CronTriggerActionsBuilderService,
|
||||
@@ -88,6 +90,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
cronTrigger: [],
|
||||
routeTrigger: [],
|
||||
fieldMetadata: [],
|
||||
viewFilter: [],
|
||||
};
|
||||
|
||||
const optimisticAllFlatEntityMaps = this.setupOptimisticCache({
|
||||
@@ -104,6 +107,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
flatCronTriggerMaps,
|
||||
flatRouteTriggerMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewFilterMaps,
|
||||
} = fromToAllFlatEntityMaps;
|
||||
|
||||
if (isDefined(flatObjectMetadataMaps)) {
|
||||
@@ -268,6 +272,36 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatViewFilterMaps)) {
|
||||
const { from: fromFlatViewFilterMaps, to: toFlatViewFilterMaps } =
|
||||
flatViewFilterMaps;
|
||||
const viewFilterResult =
|
||||
await this.workspaceMigrationV2ViewFilterActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
from: fromFlatViewFilterMaps,
|
||||
to: toFlatViewFilterMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: {
|
||||
flatFieldMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
flatViewMaps: optimisticAllFlatEntityMaps.flatViewMaps,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
optimisticAllFlatEntityMaps.flatViewFilterMaps =
|
||||
viewFilterResult.optimisticFlatEntityMaps;
|
||||
optimisticAllFlatEntityMaps.flatViewMaps =
|
||||
viewFilterResult.dependencyOptimisticFlatEntityMaps.flatViewMaps;
|
||||
|
||||
if (viewFilterResult.status === 'fail') {
|
||||
orchestratorFailureReport.viewFilter.push(...viewFilterResult.errors);
|
||||
} else {
|
||||
orchestratorActionsReport.viewFilter = viewFilterResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatServerlessFunctionMaps)) {
|
||||
const {
|
||||
from: fromFlatServerlessFunctionMaps,
|
||||
@@ -434,6 +468,9 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
...aggregatedOrchestratorActionsReport.viewField.deleted,
|
||||
...aggregatedOrchestratorActionsReport.viewField.created,
|
||||
...aggregatedOrchestratorActionsReport.viewField.updated,
|
||||
...aggregatedOrchestratorActionsReport.viewFilter.deleted,
|
||||
...aggregatedOrchestratorActionsReport.viewFilter.created,
|
||||
...aggregatedOrchestratorActionsReport.viewFilter.updated,
|
||||
///
|
||||
|
||||
// Serverless functions
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
|
||||
export type ViewFilterRelatedFlatEntityMaps = Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatViewMaps' | 'flatFieldMetadataMaps'
|
||||
>;
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { compareTwoFlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util';
|
||||
import { ViewFilterRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type';
|
||||
import {
|
||||
FlatEntityUpdateValidationArgs,
|
||||
FlatEntityValidationArgs,
|
||||
FlatEntityValidationReturnType,
|
||||
WorkspaceEntityMigrationBuilderV2Service,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
|
||||
import {
|
||||
UpdateViewFilterAction,
|
||||
WorkspaceMigrationViewFilterActionV2,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type';
|
||||
import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
|
||||
'viewFilter',
|
||||
FlatViewFilter,
|
||||
WorkspaceMigrationViewFilterActionV2,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewFilterValidatorService: FlatViewFilterValidatorService,
|
||||
) {
|
||||
super('viewFilter');
|
||||
}
|
||||
|
||||
protected async validateFlatEntityCreation({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatViewFilterToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationViewFilterActionV2,
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterCreation({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatViewFilterToValidate,
|
||||
optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatViewFilterToValidate.viewId,
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps,
|
||||
});
|
||||
|
||||
const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: {
|
||||
...flatView,
|
||||
viewFilterIds: [...flatView.viewFilterIds, flatViewFilterToValidate.id],
|
||||
},
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create_view_filter',
|
||||
viewFilter: flatViewFilterToValidate,
|
||||
},
|
||||
dependencyOptimisticFlatEntityMaps: {
|
||||
...dependencyOptimisticFlatEntityMaps,
|
||||
flatViewMaps: updatedFlatViewMaps,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityDeletion({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatViewFilterToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationViewFilterActionV2,
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterDeletion({
|
||||
flatViewFilterToValidate,
|
||||
optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const flatView = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.viewId,
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps,
|
||||
});
|
||||
|
||||
const updatedFlatViewMaps = isDefined(flatView)
|
||||
? replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: {
|
||||
...flatView,
|
||||
viewFilterIds: flatView.viewFilterIds.filter(
|
||||
(id) => id !== flatViewFilterToValidate.id,
|
||||
),
|
||||
},
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps,
|
||||
})
|
||||
: dependencyOptimisticFlatEntityMaps.flatViewMaps;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete_view_filter',
|
||||
viewFilterId: flatViewFilterToValidate.id,
|
||||
},
|
||||
dependencyOptimisticFlatEntityMaps: {
|
||||
...dependencyOptimisticFlatEntityMaps,
|
||||
flatViewMaps: updatedFlatViewMaps,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityUpdate({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityUpdate: { from: fromFlatViewFilter, to: toFlatViewFilter },
|
||||
optimisticFlatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
| FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationViewFilterActionV2,
|
||||
FlatViewFilter,
|
||||
ViewFilterRelatedFlatEntityMaps
|
||||
>
|
||||
| undefined
|
||||
> {
|
||||
const viewFilterUpdatedProperties = compareTwoFlatViewFilter({
|
||||
fromFlatViewFilter,
|
||||
toFlatViewFilter,
|
||||
});
|
||||
|
||||
if (viewFilterUpdatedProperties.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterUpdate({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatViewFilterToValidate: toFlatViewFilter,
|
||||
optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const updateViewFilterAction: UpdateViewFilterAction = {
|
||||
type: 'update_view_filter',
|
||||
viewFilterId: toFlatViewFilter.id,
|
||||
updates: viewFilterUpdatedProperties,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewFilterAction,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
};
|
||||
}
|
||||
}
|
||||
+2
@@ -7,6 +7,7 @@ import { type WorkspaceMigrationRouteTriggerActionV2 } from 'src/engine/workspac
|
||||
import { type WorkspaceMigrationServerlessFunctionActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type';
|
||||
import { type WorkspaceMigrationViewActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type';
|
||||
import { type WorkspaceMigrationViewFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type';
|
||||
import { type WorkspaceMigrationViewFilterActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type';
|
||||
|
||||
export type WorkspaceMigrationActionV2 =
|
||||
| WorkspaceMigrationObjectActionV2
|
||||
@@ -14,6 +15,7 @@ export type WorkspaceMigrationActionV2 =
|
||||
| WorkspaceMigrationIndexActionV2
|
||||
| WorkspaceMigrationViewActionV2
|
||||
| WorkspaceMigrationViewFieldActionV2
|
||||
| WorkspaceMigrationViewFilterActionV2
|
||||
| WorkspaceMigrationServerlessFunctionActionV2
|
||||
| WorkspaceMigrationDatabaseEventTriggerActionV2
|
||||
| WorkspaceMigrationCronTriggerActionV2
|
||||
|
||||
+6
-16
@@ -1,30 +1,20 @@
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type FlatViewFieldPropertiesToCompare } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-properties-to-compare.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
|
||||
export type FlatViewFieldPropertyUpdate<
|
||||
P extends FlatViewFieldPropertiesToCompare,
|
||||
> = {
|
||||
property: P;
|
||||
} & FromTo<ViewFieldEntity[P]>;
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type';
|
||||
|
||||
export type CreateViewFieldAction = {
|
||||
type: 'create_view_field';
|
||||
viewField: FlatViewField;
|
||||
};
|
||||
|
||||
export type FlatViewFieldPropertiesUpdates = Array<
|
||||
{
|
||||
[P in FlatViewFieldPropertiesToCompare]: FlatViewFieldPropertyUpdate<P>;
|
||||
}[FlatViewFieldPropertiesToCompare]
|
||||
>;
|
||||
|
||||
export type UpdateViewFieldAction = {
|
||||
type: 'update_view_field';
|
||||
viewFieldId: string;
|
||||
updates: FlatViewFieldPropertiesUpdates;
|
||||
updates: Array<
|
||||
{
|
||||
[P in FlatViewFieldPropertiesToCompare]: PropertyUpdate<FlatViewField, P>;
|
||||
}[FlatViewFieldPropertiesToCompare]
|
||||
>;
|
||||
};
|
||||
|
||||
export type DeleteViewFieldAction = {
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { type FlatViewFilterPropertiesToCompare } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type';
|
||||
|
||||
export type CreateViewFilterAction = {
|
||||
type: 'create_view_filter';
|
||||
viewFilter: FlatViewFilter;
|
||||
};
|
||||
|
||||
export type UpdateViewFilterAction = {
|
||||
type: 'update_view_filter';
|
||||
viewFilterId: string;
|
||||
updates: Array<
|
||||
{
|
||||
[P in FlatViewFilterPropertiesToCompare]: PropertyUpdate<
|
||||
FlatViewFilter,
|
||||
P
|
||||
>;
|
||||
}[FlatViewFilterPropertiesToCompare]
|
||||
>;
|
||||
};
|
||||
|
||||
export type DeleteViewFilterAction = {
|
||||
type: 'delete_view_filter';
|
||||
viewFilterId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationViewFilterActionV2 =
|
||||
| CreateViewFilterAction
|
||||
| UpdateViewFilterAction
|
||||
| DeleteViewFilterAction;
|
||||
|
||||
export type WorkspaceMigrationViewFilterActionTypeV2 =
|
||||
WorkspaceMigrationViewFilterActionV2['type'];
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { ViewFilterExceptionCode } from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
|
||||
import { ViewFilterRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type';
|
||||
|
||||
@Injectable()
|
||||
export class FlatViewFilterValidatorService {
|
||||
constructor() {}
|
||||
|
||||
validateFlatViewFilterCreation({
|
||||
flatViewFilterToValidate,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
optimisticFlatViewFilterMaps,
|
||||
}: {
|
||||
flatViewFilterToValidate: FlatViewFilter;
|
||||
dependencyOptimisticFlatEntityMaps: ViewFilterRelatedFlatEntityMaps;
|
||||
optimisticFlatViewFilterMaps: FlatViewFilterMaps;
|
||||
}): FailedFlatEntityValidation<FlatViewFilter> {
|
||||
const validationResult: FailedFlatEntityValidation<FlatViewFilter> = {
|
||||
type: 'create_view_filter',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatViewFilterToValidate.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.id,
|
||||
flatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (isDefined(existingViewFilter)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA,
|
||||
message: t`View filter with this id already exists`,
|
||||
userFriendlyMessage: msg`View filter with this id already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
const referencedView = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.viewId,
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(referencedView)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA,
|
||||
message: t`View not found`,
|
||||
userFriendlyMessage: msg`View not found`,
|
||||
});
|
||||
}
|
||||
|
||||
const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.fieldMetadataId,
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(referencedFieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA,
|
||||
message: t`Field metadata not found`,
|
||||
userFriendlyMessage: msg`Field metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatViewFilterDeletion({
|
||||
flatViewFilterToValidate,
|
||||
optimisticFlatViewFilterMaps,
|
||||
}: {
|
||||
flatViewFilterToValidate: FlatViewFilter;
|
||||
optimisticFlatViewFilterMaps: FlatViewFilterMaps;
|
||||
}): FailedFlatEntityValidation<FlatViewFilter> {
|
||||
const validationResult: FailedFlatEntityValidation<FlatViewFilter> = {
|
||||
type: 'delete_view_filter',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatViewFilterToValidate.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.id,
|
||||
flatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingViewFilter)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND,
|
||||
message: t`View filter not found`,
|
||||
userFriendlyMessage: msg`View filter not found`,
|
||||
});
|
||||
} else if (!isDefined(existingViewFilter.deletedAt)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA,
|
||||
message: t`View filter has to be soft deleted first`,
|
||||
userFriendlyMessage: msg`View filter has to be soft deleted first`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatViewFilterUpdate({
|
||||
flatViewFilterToValidate,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
optimisticFlatViewFilterMaps,
|
||||
}: {
|
||||
flatViewFilterToValidate: FlatViewFilter;
|
||||
dependencyOptimisticFlatEntityMaps: ViewFilterRelatedFlatEntityMaps;
|
||||
optimisticFlatViewFilterMaps: FlatViewFilterMaps;
|
||||
}): FailedFlatEntityValidation<FlatViewFilter> {
|
||||
const validationResult: FailedFlatEntityValidation<FlatViewFilter> = {
|
||||
type: 'update_view_filter',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatViewFilterToValidate.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.id,
|
||||
flatEntityMaps: optimisticFlatViewFilterMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingViewFilter)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND,
|
||||
message: t`View filter not found`,
|
||||
userFriendlyMessage: msg`View filter not found`,
|
||||
});
|
||||
}
|
||||
|
||||
const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatViewFilterToValidate.fieldMetadataId,
|
||||
flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(referencedFieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA,
|
||||
message: t`Field metadata not found`,
|
||||
userFriendlyMessage: msg`Field metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
}
|
||||
+3
@@ -10,6 +10,7 @@ import { FlatObjectMetadataValidatorService } from 'src/engine/workspace-manager
|
||||
import { FlatRouteTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service';
|
||||
import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service';
|
||||
import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service';
|
||||
import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service';
|
||||
import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service';
|
||||
|
||||
@Module({
|
||||
@@ -17,6 +18,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
|
||||
providers: [
|
||||
FlatViewValidatorService,
|
||||
FlatViewFieldValidatorService,
|
||||
FlatViewFilterValidatorService,
|
||||
FlatIndexValidatorService,
|
||||
FlatFieldMetadataValidatorService,
|
||||
FlatObjectMetadataValidatorService,
|
||||
@@ -29,6 +31,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
|
||||
exports: [
|
||||
FlatViewValidatorService,
|
||||
FlatViewFieldValidatorService,
|
||||
FlatViewFilterValidatorService,
|
||||
FlatIndexValidatorService,
|
||||
FlatFieldMetadataValidatorService,
|
||||
FlatObjectMetadataValidatorService,
|
||||
|
||||
+3
@@ -10,6 +10,7 @@ import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/work
|
||||
import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service';
|
||||
import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module';
|
||||
|
||||
@@ -20,6 +21,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2ObjectActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewFilterActionsBuilderService,
|
||||
WorkspaceMigrationV2IndexActionsBuilderService,
|
||||
WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
@@ -32,6 +34,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2IndexActionsBuilderService,
|
||||
WorkspaceMigrationV2ObjectActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewFilterActionsBuilderService,
|
||||
WorkspaceMigrationV2FieldActionsBuilderService,
|
||||
WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { CreateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class CreateViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create_view_filter',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<CreateViewFilterAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatViewFilterMaps } = allFlatEntityMaps;
|
||||
const { viewFilter } = action;
|
||||
|
||||
const updatedFlatViewFilterMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: viewFilter,
|
||||
flatEntityMaps: flatViewFilterMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatViewFilterMaps: updatedFlatViewFilterMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<CreateViewFilterAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { viewFilter } = action;
|
||||
|
||||
const viewFilterRepository =
|
||||
queryRunner.manager.getRepository<ViewFilterEntity>(ViewFilterEntity);
|
||||
|
||||
await viewFilterRepository.insert({
|
||||
...viewFilter,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<CreateViewFilterAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { DeleteViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_view_filter',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<DeleteViewFilterAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatViewFilterMaps } = allFlatEntityMaps;
|
||||
const { viewFilterId } = action;
|
||||
|
||||
const updatedFlatViewFilterMaps = deleteFlatEntityFromFlatEntityMapsOrThrow(
|
||||
{
|
||||
entityToDeleteId: viewFilterId,
|
||||
flatEntityMaps: flatViewFilterMaps,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
flatViewFilterMaps: updatedFlatViewFilterMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<DeleteViewFilterAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { viewFilterId } = action;
|
||||
|
||||
const viewFilterRepository =
|
||||
queryRunner.manager.getRepository<ViewFilterEntity>(ViewFilterEntity);
|
||||
|
||||
await viewFilterRepository.delete({
|
||||
id: viewFilterId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<DeleteViewFilterAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { UpdateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update_view_filter',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<UpdateViewFilterAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatViewFilterMaps } = allFlatEntityMaps;
|
||||
const { viewFilterId } = action;
|
||||
|
||||
const existingViewFilter = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: viewFilterId,
|
||||
flatEntityMaps: flatViewFilterMaps,
|
||||
});
|
||||
|
||||
const updatedViewFilter = {
|
||||
...existingViewFilter,
|
||||
...fromWorkspaceMigrationUpdateActionToPartialEntity(action),
|
||||
};
|
||||
|
||||
const updatedFlatViewFilterMaps = replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: updatedViewFilter,
|
||||
flatEntityMaps: flatViewFilterMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatViewFilterMaps: updatedFlatViewFilterMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UpdateViewFilterAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner } = context;
|
||||
const { viewFilterId } = action;
|
||||
|
||||
const viewFilterRepository =
|
||||
queryRunner.manager.getRepository<ViewFilterEntity>(ViewFilterEntity);
|
||||
|
||||
const update = fromWorkspaceMigrationUpdateActionToPartialEntity(action);
|
||||
|
||||
await viewFilterRepository.update(viewFilterId, update);
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<UpdateViewFilterAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+7
@@ -24,6 +24,9 @@ import { UpdateServerlessFunctionActionHandlerService } from 'src/engine/workspa
|
||||
import { CreateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/create-view-field-action-handler.service';
|
||||
import { DeleteViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/delete-view-field-action-handler.service';
|
||||
import { UpdateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/update-view-field-action-handler.service';
|
||||
import { CreateViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service';
|
||||
import { DeleteViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service';
|
||||
import { UpdateViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service';
|
||||
import { CreateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service';
|
||||
import { DeleteViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/delete-view-action-handler.service';
|
||||
import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/update-view-action-handler.service';
|
||||
@@ -50,6 +53,10 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor
|
||||
UpdateViewFieldActionHandlerService,
|
||||
DeleteViewFieldActionHandlerService,
|
||||
|
||||
CreateViewFilterActionHandlerService,
|
||||
UpdateViewFilterActionHandlerService,
|
||||
DeleteViewFilterActionHandlerService,
|
||||
|
||||
CreateServerlessFunctionActionHandlerService,
|
||||
DeleteServerlessFunctionActionHandlerService,
|
||||
UpdateServerlessFunctionActionHandlerService,
|
||||
|
||||
+1
-4
@@ -1,7 +1,4 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function orderObjectProperties<T extends Array<any> | object>(
|
||||
data: T,
|
||||
): T {
|
||||
export function orderObjectProperties<T>(data: T): T {
|
||||
if (Array.isArray(data)) {
|
||||
return data.map(orderObjectProperties) as T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user