-
Couldn't load subscription status.
- Fork 4.4k
Refactor twenty-front metadata api services for v2
#15360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
76a5c57 to
1406b00
Compare
050b24d to
1950ea5
Compare
packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR refactors frontend metadata API services to handle v2 error responses with improved user experience. The refactoring introduces a discriminated union pattern (MetadataRequestResult<T>) for all metadata operations, returning either {status: 'successful', response} or {status: 'failed', error}.
Key Changes:
- Centralized error handling via
useMetadataErrorHandlerhook that classifies errors as v1, v2-validation, or v2-internal - Consolidated CRUD operations into unified hooks (
usePersistView,usePersistViewField,usePersistServerlessFunction) - All object/field metadata hooks now return discriminated unions instead of throwing exceptions
- Consumers check
result.status === 'successful'before proceeding with navigation or state updates - V2 validation errors display individual field-level error messages with translations
Architecture:
The new pattern creates clear separation between error handling (centralized in the hook) and error display (via snackbar), with consumers only needing to check status for control flow decisions.
Issues Found:
- Several view-related hooks (
useSaveCurrentViewFields,useSaveCurrentViewGroups,useSaveRecordSortsToViewSorts) do not check operation status, potentially swallowing errors silently - These hooks execute operations but ignore the discriminated union results, which defeats the purpose of the refactoring
Confidence Score: 4/5
- This PR is mostly safe to merge with some view operation hooks that need error handling improvements
- The core refactoring is well-designed with proper discriminated unions and centralized error handling. Object/field metadata operations correctly check status before proceeding. However, several view-related hooks ignore operation results, which could lead to silent failures in production. These are not critical blockers since errors are still shown to users via snackbars, but the inconsistent status checking pattern reduces reliability.
- Pay close attention to
useSaveCurrentViewFields.ts,useSaveCurrentViewGroups.ts, anduseSaveRecordSortsToViewSorts.ts- these ignore operation status and may silently fail
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/twenty-front/src/modules/metadata-error-handler/hooks/useMetadataErrorHandler.ts | 5/5 | new centralized error handler classifying v1/v2 errors and displaying user-friendly messages |
| packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts | 3/5 | refactored to use usePersistViewField but does not check operation status, potentially swallowing errors |
| packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts | 3/5 | refactored to use usePersistViewGroupRecords but does not check operation status, potentially swallowing errors |
| packages/twenty-front/src/modules/views/hooks/useSaveRecordSortsToViewSorts.ts | 3/5 | refactored to use usePersistViewSortRecords but does not check operation status, potentially swallowing errors |
Sequence Diagram
sequenceDiagram
participant UI as UI Component
participant Hook as Metadata Hook
participant Handler as useMetadataErrorHandler
participant Classifier as classifyMetadataError
participant Mutation as GraphQL Mutation
participant Snackbar as useSnackBar
UI->>Hook: createOneObjectMetadataItem(input)
Hook->>Mutation: Execute mutation
alt Success
Mutation-->>Hook: Success response
Hook->>Hook: refreshObjectMetadataItems()
Hook-->>UI: {status: 'successful', response}
UI->>UI: Navigate to new object
else Error
Mutation-->>Hook: ApolloError
Hook->>Handler: handleMetadataError(error, primaryMetadataName)
Handler->>Classifier: classifyMetadataError(error, primaryMetadataName)
alt V2 Validation Error
Classifier-->>Handler: {type: 'v2-validation', extensions, relatedFailingMetadataNames}
Handler->>Handler: Extract primary entity errors
loop For each validation error
Handler->>Snackbar: enqueueErrorSnackBar(userFriendlyMessage)
end
alt No primary errors but related errors
Handler->>Snackbar: enqueueErrorSnackBar(related entity message)
end
else V2 Internal Error
Classifier-->>Handler: {type: 'v2-internal', code, message}
Handler->>Snackbar: enqueueErrorSnackBar(internal error message)
else V1 Error
Classifier-->>Handler: {type: 'v1', error}
Handler->>Snackbar: enqueueErrorSnackBar(apolloError)
end
Hook-->>UI: {status: 'failed', error}
UI->>UI: Stay on current page
end
55 files reviewed, 3 comments
packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts
Show resolved
Hide resolved
packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts
Show resolved
Hide resolved
packages/twenty-front/src/modules/views/hooks/useSaveRecordSortsToViewSorts.ts
Show resolved
Hide resolved
|
🚀 Preview Environment Ready! Your preview environment is available at: http://bore.pub:15014 This environment will automatically shut down when the PR is closed or after 5 hours. |
# Introduction Followup of #15331 ( Reducing size by concerns ) This PR centralizes v2 format error types in `twenty-shared` and consuming them in the existing v2 error format logic in `twenty-server` ## Next This #15360 handles the frontend v2 format error refactor ## Conclusion Related to twentyhq/core-team-issues#1776
bcfa284 to
f8f8ac6
Compare
Introduction
Please first review this PR initial base #15358
In a nutshell refactored the frontend fetchers to display v2 errors format smoothly
Please note that the v2 now finished the whole validation and does fail fast anymore ( summary is hardcoded for the moment )
[ { "extensions": { "code": "BAD_USER_INPUT", "errors": { "cronTrigger": [], "databaseEventTrigger": [], "fieldMetadata": [ { "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", "value": "", }, ], "flatEntityMinimalInformation": { "id": Any<String>, "name": "testField", "objectMetadataId": Any<String>, }, "status": "fail", "type": "create_field", }, ], "index": [], "objectMetadata": [], "routeTrigger": [], "serverlessFunction": [], "view": [], "viewField": [], "viewFilter": [], "viewGroup": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { "invalidCronTrigger": 0, "invalidDatabaseEventTrigger": 0, "invalidFieldMetadata": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidRouteTrigger": 0, "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "invalidViewFilter": 0, "invalidViewGroup": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", }, "message": "Multiple validation errors occurred while creating fields", "name": "GraphQLError", }, ]What's done
usePersistViewtool ( CRUD )usePersistViewXtools accordingly ( no more records or core )Result
Primary entity error
When performing an metadata operation on a given metadata, if validation errors occurs we will display each of them in a toast

Here while creating an object metadata.
Related entity error
Still while creating an object

Translated
Conclusion
This PR is an extract of #15331
close twentyhq/core-team-issues#1776
Notes