Files
twenty/packages/twenty-front/src/modules/object-metadata/utils/enrichObjectMetadataItemsWithPermissions.ts
T
Charles Bochet d5a7dec117 refactor: rename ObjectMetadataItem to EnrichedObjectMetadataItem and clean up metadata flows (#18830)
## Summary

- Renames `ObjectMetadataItem` to `EnrichedObjectMetadataItem` across
the entire frontend (~440 files) to clarify that this type includes
derived fields (`readableFields`, `updatableFields`, nested `fields[]`,
`indexMetadatas[]`) computed at read time from the metadata store
- Creates `splitObjectMetadataGqlResponse` that goes directly from a
GraphQL `ObjectMetadataItemsQuery` response to flat store items
(combining the old
`mapPaginatedObjectMetadataItemsToObjectMetadataItems` +
`splitObjectMetadataItemWithRelated` two-step flow into one call)
- Removes `ObjectMetadataItemWithRelated` type and all "WithRelated"
naming
- Renames `generatedMockObjectMetadataItems` to
`generateTestEnrichedObjectMetadataItemsMock` to make it clear this is
test-only enriched data
- Deletes `useLoadMockedObjectMetadataItems` hook (consolidated into
`useLoadMockedMinimalMetadata`)
- Ensures nothing destined for the metadata store computes
`readableFields`/`updatableFields` (preventing the localStorage bloat
from #18809)

## Type hierarchy (before → after)

**Before:**
```
ObjectMetadataItemsQuery → mapPaginated → ObjectMetadataItemWithRelated → enrich → ObjectMetadataItem
                                        → split → FlatObjectMetadataItem (store)
```

**After:**
```
ObjectMetadataItemsQuery → splitObjectMetadataGqlResponse → FlatObjectMetadataItem (store)
                         → mapPaginated + enrich (tests only) → EnrichedObjectMetadataItem
```

## Test plan

- [x] `npx nx typecheck twenty-front` passes
- [x] `npx nx test twenty-front` passes (767 suites, 4505 tests)
- [x] `npx nx lint twenty-front` passes
- [ ] CI checks pass


Made with [Cursor](https://cursor.com)
2026-03-22 15:53:47 +01:00

58 lines
2.3 KiB
TypeScript

import { getNonReadableFieldMetadataIdsFromObjectPermissions } from '@/object-metadata/utils/getNonReadableFieldMetadataIdsFromObjectPermissions';
import { getNonUpdatableFieldMetadataIdsFromObjectPermissions } from '@/object-metadata/utils/getNonUpdatableFieldMetadataIdsFromObjectPermissions';
import { getObjectPermissionsFromMapByObjectMetadataId } from '@/settings/roles/role-permissions/objects-permissions/utils/getObjectPermissionsFromMapByObjectMetadataId';
import { type ObjectPermissions } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
type enrichObjectMetadataItemsWithPermissionsArgs = {
objectMetadataItems: Omit<
EnrichedObjectMetadataItem,
'readableFields' | 'updatableFields'
>[];
objectPermissionsByObjectMetadataId: Record<
string,
ObjectPermissions & { objectMetadataId: string }
>;
};
export const enrichObjectMetadataItemsWithPermissions = ({
objectMetadataItems,
objectPermissionsByObjectMetadataId,
}: enrichObjectMetadataItemsWithPermissionsArgs) => {
const formattedObjects: EnrichedObjectMetadataItem[] =
objectMetadataItems.map((object) => {
const objectPermissions = getObjectPermissionsFromMapByObjectMetadataId({
objectPermissionsByObjectMetadataId,
objectMetadataId: object.id,
});
const nonReadableFieldMetadataIds = !isDefined(objectPermissions)
? []
: getNonReadableFieldMetadataIdsFromObjectPermissions({
objectPermissions: objectPermissions,
});
const nonUpdatableFieldMetadataIds = !isDefined(objectPermissions)
? []
: getNonUpdatableFieldMetadataIdsFromObjectPermissions({
objectPermissions: objectPermissions,
});
const { fields, ...objectWithoutFields } = object;
return {
...objectWithoutFields,
fields: fields,
readableFields: fields.filter(
(field) => !nonReadableFieldMetadataIds.includes(field.id),
),
updatableFields: fields.filter(
(field) => !nonUpdatableFieldMetadataIds.includes(field.id),
),
} satisfies EnrichedObjectMetadataItem;
}) ?? [];
return formattedObjects;
};