ObjectMetadataServiceV2.updateOne (#13891)
# Introduction Last service to get migrated, `updateOne` object metadata service v2
This commit is contained in:
+8
@@ -0,0 +1,8 @@
|
||||
import { type FlatObjectMetadataPropertiesToCompare } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-properties-to-compare.type';
|
||||
|
||||
export const OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES = [
|
||||
'labelSingular',
|
||||
'labelPlural',
|
||||
'description',
|
||||
'icon',
|
||||
] as const satisfies FlatObjectMetadataPropertiesToCompare[];
|
||||
+84
-1
@@ -8,14 +8,17 @@ import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine
|
||||
import { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util';
|
||||
import { deleteObjectFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-object-from-flat-object-metadata-maps-or-throw.util';
|
||||
import { getSubFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util';
|
||||
import { replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { fromCreateObjectInputToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata.util';
|
||||
import { fromDeleteObjectInputToFlatFieldMetadatasToDelete } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util';
|
||||
import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util';
|
||||
import { fromUpdateObjectInputToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata.util';
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input';
|
||||
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
|
||||
import { UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
@@ -33,6 +36,86 @@ export class ObjectMetadataServiceV2 {
|
||||
private readonly flatObjectMetadataValidatorService: FlatObjectMetadataValidatorService,
|
||||
) {}
|
||||
|
||||
async updateOne({
|
||||
updateObjectInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
updateObjectInput: UpdateOneObjectInput;
|
||||
}): Promise<ObjectMetadataDTO> {
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const optimisticallyUpdatedFlatObjectMetadata =
|
||||
fromUpdateObjectInputToFlatObjectMetadata({
|
||||
existingFlatObjectMetadataMaps,
|
||||
updateObjectInput,
|
||||
});
|
||||
|
||||
const validationErrors =
|
||||
this.flatObjectMetadataValidatorService.validateFlatObjectMetadataUpdate({
|
||||
existingFlatObjectMetadataMaps,
|
||||
updatedFlatObjectMetadata: optimisticallyUpdatedFlatObjectMetadata,
|
||||
});
|
||||
|
||||
if (validationErrors.length > 0) {
|
||||
throw new MultipleMetadataValidationErrors(
|
||||
validationErrors,
|
||||
'Multiple validation errors occurred while updating object',
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const fromFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
objectMetadataIds: [optimisticallyUpdatedFlatObjectMetadata.id],
|
||||
});
|
||||
const toFlatObjectMetadataMaps =
|
||||
replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadata: optimisticallyUpdatedFlatObjectMetadata,
|
||||
flatObjectMetadataMaps: fromFlatObjectMetadataMaps,
|
||||
});
|
||||
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
|
||||
fromFlatObjectMetadataMaps,
|
||||
toFlatObjectMetadataMaps,
|
||||
inferDeletionFromMissingObjectFieldIndex: false,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceMigrationRunnerV2Service.run(workspaceMigration);
|
||||
} catch {
|
||||
throw new ObjectMetadataException(
|
||||
'Workspace migration failed to run',
|
||||
ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
const { flatObjectMetadataMaps: recomputedFlatObjectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const updatedFlatObjectMetadata =
|
||||
recomputedFlatObjectMetadataMaps.byId[
|
||||
optimisticallyUpdatedFlatObjectMetadata.id
|
||||
];
|
||||
|
||||
if (!isDefined(updatedFlatObjectMetadata)) {
|
||||
throw new ObjectMetadataException(
|
||||
'Updated object metadata not found in recomputed cache',
|
||||
ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
return fromFlatObjectMetadataToObjectMetadataDto(updatedFlatObjectMetadata);
|
||||
}
|
||||
|
||||
async deleteOne({
|
||||
deleteObjectInput,
|
||||
workspaceId,
|
||||
@@ -189,7 +272,7 @@ export class ObjectMetadataServiceV2 {
|
||||
|
||||
if (!isDefined(createdFlatObjectMetadata)) {
|
||||
throw new ObjectMetadataException(
|
||||
'Fail to find just created object metadata',
|
||||
'Created object metadata not found in recomputed cache',
|
||||
ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
+30
-5
@@ -8,6 +8,8 @@ import {
|
||||
Resolver,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type';
|
||||
@@ -25,6 +27,7 @@ import {
|
||||
type UpdateObjectPayload,
|
||||
} from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook';
|
||||
import { ObjectMetadataServiceV2 } from 'src/engine/metadata-modules/object-metadata/object-metadata-v2.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { objectMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/object-metadata/utils/object-metadata-graphql-api-exception-handler.util';
|
||||
import { resolveObjectMetadataStandardOverride } from 'src/engine/metadata-modules/object-metadata/utils/resolve-object-metadata-standard-override.util';
|
||||
@@ -42,6 +45,8 @@ export class ObjectMetadataResolver {
|
||||
constructor(
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly beforeUpdateOneObject: BeforeUpdateOneObject<UpdateObjectPayload>,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
private readonly objectMetadataServiceV2: ObjectMetadataServiceV2,
|
||||
) {}
|
||||
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
@@ -112,15 +117,35 @@ export class ObjectMetadataResolver {
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.DATA_MODEL))
|
||||
@Mutation(() => ObjectMetadataDTO)
|
||||
async updateOneObject(
|
||||
@Args('input') input: UpdateOneObjectInput,
|
||||
@Args('input') updateObjectInput: UpdateOneObjectInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
@Context() context: I18nContext,
|
||||
) {
|
||||
try {
|
||||
const updatedInput = (await this.beforeUpdateOneObject.run(input, {
|
||||
const isWorkspaceMigrationV2Enabled =
|
||||
await this.featureFlagService.isFeatureEnabled(
|
||||
FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
workspaceId,
|
||||
locale: context.req.locale,
|
||||
})) as UpdateOneObjectInput;
|
||||
);
|
||||
|
||||
if (isWorkspaceMigrationV2Enabled) {
|
||||
try {
|
||||
return await this.objectMetadataServiceV2.updateOne({
|
||||
updateObjectInput,
|
||||
workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
objectMetadataGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedInput = (await this.beforeUpdateOneObject.run(
|
||||
updateObjectInput,
|
||||
{
|
||||
workspaceId,
|
||||
locale: context.req.locale,
|
||||
},
|
||||
)) as UpdateOneObjectInput;
|
||||
|
||||
return await this.objectMetadataService.updateOneObject(
|
||||
updatedInput,
|
||||
|
||||
+9
-8
@@ -110,7 +110,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
workspaceId: createObjectInput.workspaceId,
|
||||
});
|
||||
|
||||
// Since V2 returns FlatObjectMetadata, we need to fetch the created entity
|
||||
const createdObjectMetadata = await this.objectMetadataRepository.findOne(
|
||||
{
|
||||
where: {
|
||||
@@ -288,7 +287,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
}
|
||||
|
||||
public async updateOneObject(
|
||||
input: UpdateOneObjectInput,
|
||||
updateObjectInput: UpdateOneObjectInput,
|
||||
workspaceId: string,
|
||||
): Promise<ObjectMetadataEntity> {
|
||||
const mainDataSource =
|
||||
@@ -306,14 +305,16 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps(
|
||||
{ workspaceId },
|
||||
);
|
||||
const inputId = input.id;
|
||||
const inputId = updateObjectInput.id;
|
||||
const inputPayload = {
|
||||
...input.update,
|
||||
...(isDefined(input.update.labelSingular)
|
||||
? { labelSingular: capitalize(input.update.labelSingular) }
|
||||
...updateObjectInput.update,
|
||||
...(isDefined(updateObjectInput.update.labelSingular)
|
||||
? {
|
||||
labelSingular: capitalize(updateObjectInput.update.labelSingular),
|
||||
}
|
||||
: {}),
|
||||
...(isDefined(input.update.labelPlural)
|
||||
? { labelPlural: capitalize(input.update.labelPlural) }
|
||||
...(isDefined(updateObjectInput.update.labelPlural)
|
||||
? { labelPlural: capitalize(updateObjectInput.update.labelPlural) }
|
||||
: {}),
|
||||
};
|
||||
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/object-metadata/constants/object-metadata-standard-overrides-properties.constant';
|
||||
|
||||
export type ObjectMetadataStandardOverridesProperties =
|
||||
(typeof OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES)[number];
|
||||
Reference in New Issue
Block a user