Fix unclear metadata validation errors (#20234)

https://github.com/user-attachments/assets/8f8f1122-3de1-4a9b-8bb4-a3c8d31e47ae

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Abdul Rahman
2026-05-05 23:48:05 +05:30
committed by GitHub
parent a03c2647cf
commit e0563377b5
70 changed files with 935 additions and 771 deletions
@@ -4,33 +4,19 @@ import {
Injectable,
type NestInterceptor,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { type Observable, catchError } from 'rxjs';
import { SOURCE_LOCALE } from 'twenty-shared/translations';
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
import { objectMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/object-metadata/utils/object-metadata-graphql-api-exception-handler.util';
@Injectable()
export class ObjectMetadataGraphqlApiExceptionInterceptor
implements NestInterceptor
{
constructor(private readonly i18nService: I18nService) {}
// oxlint-disable-next-line @typescripttypescript/no-explicit-any
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const gqlContext = GqlExecutionContext.create(context);
const ctx = gqlContext.getContext();
const locale = ctx.req?.locale ?? SOURCE_LOCALE;
const i18n = this.i18nService.getI18nInstance(locale);
intercept(_context: ExecutionContext, next: CallHandler): Observable<any> {
return next
.handle()
.pipe(
catchError((err) =>
objectMetadataGraphqlApiExceptionHandler(err, i18n),
),
);
.pipe(catchError((err) => objectMetadataGraphqlApiExceptionHandler(err)));
}
}
@@ -137,7 +137,6 @@ export class ObjectMetadataResolver {
async createOneObject(
@Args('input') input: CreateOneObjectInput,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
@Context() context: I18nContext,
) {
try {
const flatobjectMetadata =
@@ -148,10 +147,7 @@ export class ObjectMetadataResolver {
return fromFlatObjectMetadataToObjectMetadataDto(flatobjectMetadata);
} catch (error) {
objectMetadataGraphqlApiExceptionHandler(
error,
this.i18nService.getI18nInstance(context.req.locale),
);
objectMetadataGraphqlApiExceptionHandler(error);
}
}
@@ -160,7 +156,6 @@ export class ObjectMetadataResolver {
async deleteOneObject(
@Args('input') deleteObjectInput: DeleteOneObjectInput,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
@Context() context: I18nContext,
) {
try {
const flatobjectMetadata =
@@ -171,10 +166,7 @@ export class ObjectMetadataResolver {
return fromFlatObjectMetadataToObjectMetadataDto(flatobjectMetadata);
} catch (error) {
objectMetadataGraphqlApiExceptionHandler(
error,
this.i18nService.getI18nInstance(context.req.locale),
);
objectMetadataGraphqlApiExceptionHandler(error);
}
}
@@ -183,7 +175,6 @@ export class ObjectMetadataResolver {
async updateOneObject(
@Args('input') updateObjectInput: UpdateOneObjectInput,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
@Context() context: I18nContext,
) {
try {
const flatobjectMetadata =
@@ -194,10 +185,7 @@ export class ObjectMetadataResolver {
return fromFlatObjectMetadataToObjectMetadataDto(flatobjectMetadata);
} catch (error) {
objectMetadataGraphqlApiExceptionHandler(
error,
this.i18nService.getI18nInstance(context.req.locale),
);
objectMetadataGraphqlApiExceptionHandler(error);
}
}
@@ -218,10 +206,7 @@ export class ObjectMetadataResolver {
return fieldMetadataItems;
} catch (error) {
objectMetadataGraphqlApiExceptionHandler(
error,
this.i18nService.getI18nInstance(context.req.locale),
);
objectMetadataGraphqlApiExceptionHandler(error);
return [];
}
@@ -231,7 +216,7 @@ export class ObjectMetadataResolver {
async indexMetadataList(
@AuthWorkspace() workspace: WorkspaceEntity,
@Parent() objectMetadata: ObjectMetadataDTO,
@Context() context: { loaders: IDataloaders } & I18nContext,
@Context() context: { loaders: IDataloaders },
): Promise<IndexMetadataDTO[]> {
try {
const indexMetadataItems = await context.loaders.indexMetadataLoader.load(
@@ -243,10 +228,7 @@ export class ObjectMetadataResolver {
return indexMetadataItems;
} catch (error) {
objectMetadataGraphqlApiExceptionHandler(
error,
this.i18nService.getI18nInstance(context.req.locale),
);
objectMetadataGraphqlApiExceptionHandler(error);
return [];
}
@@ -1,4 +1,3 @@
import { type I18n } from '@lingui/core';
import { assertUnreachable } from 'twenty-shared/utils';
import {
@@ -14,14 +13,11 @@ import {
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
import { InvalidMetadataException } from 'src/engine/metadata-modules/utils/exceptions/invalid-metadata.exception';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { workspaceMigrationBuilderExceptionFormatter } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-builder-exception-formatter';
import { workspaceMigrationBuilderGraphqlApiExceptionHandler } from 'src/engine/workspace-manager/workspace-migration/interceptors/utils/workspace-migration-builder-graphql-api-exception-handler.util';
export const objectMetadataGraphqlApiExceptionHandler = (
error: Error,
i18n: I18n,
) => {
export const objectMetadataGraphqlApiExceptionHandler = (error: Error) => {
if (error instanceof WorkspaceMigrationBuilderException) {
workspaceMigrationBuilderExceptionFormatter(error, i18n);
workspaceMigrationBuilderGraphqlApiExceptionHandler(error);
}
if (error instanceof InvalidMetadataException) {