From 30df6c10ea42a69e877ec161b56a11f45e2eb837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Thu, 29 Feb 2024 13:03:52 -0300 Subject: [PATCH] test: improve utils coverage (#4230) * test: improve utils coverage * refactor: review - rename isDefined to isNonNullable, update tests and return statement --- .../activities/components/ActivityTitle.tsx | 4 +-- .../hooks/useActivityConnectionUtils.ts | 4 +-- .../hooks/useActivityTargetObjectRecords.ts | 6 ++-- .../useAttachRelationInBothDirections.ts | 6 ++-- .../hooks/useCreateActivityInCache.ts | 4 +-- ...enCreateActivityDrawerForSelectedRowIds.ts | 4 +-- .../activities/hooks/useUpsertActivity.ts | 10 +++--- .../components/ActivityActionBar.tsx | 15 ++++---- .../components/TimelineQueryEffect.tsx | 6 ++-- .../timeline/hooks/useTimelineActivities.ts | 6 ++-- .../utils/sortCachedObjectEdges.ts | 4 +-- .../triggerAttachRelationOptimisticEffect.ts | 4 +-- .../triggerDeleteRecordsOptimisticEffect.ts | 6 ++-- .../triggerUpdateRecordOptimisticEffect.ts | 13 +++---- .../triggerUpdateRelationsOptimisticEffect.ts | 11 +++--- .../modules/apollo/services/apollo.factory.ts | 4 +-- .../modules/favorites/hooks/useFavorites.ts | 4 +-- .../modules/favorites/utils/mapFavorites.ts | 9 +++-- ...eFilterOutUnexistingObjectMetadataItems.ts | 4 +-- .../hooks/useObjectMetadataItem.ts | 4 +-- .../hooks/useObjectMetadataItemOnly.ts | 4 +-- .../hooks/useObjectNamePluralFromSingular.ts | 4 +-- .../hooks/useObjectNameSingularFromPlural.ts | 4 +-- .../utils/isLabelIdentifierField.ts | 4 +-- .../utils/parseFieldRelationType.ts | 6 ++-- .../useReadFindManyRecordsQueryInCache.ts | 4 +-- .../useMapConnectionToRecords.test.tsx | 4 +-- .../hooks/useDeleteManyRecords.ts | 4 +-- .../hooks/useMapConnectionToRecords.ts | 8 ++--- .../ObjectFilterDropdownDateSearchInput.tsx | 6 ++-- .../RecordBoardDeprecatedInternalEffect.tsx | 6 ++-- ...ecordBoardColumnsFamilySelectorScopeMap.ts | 4 +-- .../input/hooks/useRegisterInputEvents.ts | 4 +-- .../record-field/utils/isFieldValueEmpty.ts | 6 ++-- .../utils/isRecordMatchingFilter.ts | 8 ++--- ...turnObjectDropdownFilterIntoQueryFilter.ts | 4 +-- .../components/RecordShowContainer.tsx | 4 +-- .../components/RecordShowContainerEffect.tsx | 4 +-- .../SingleEntitySelectMenuItems.tsx | 4 +-- .../SingleEntitySelectMenuItemsWithSearch.tsx | 4 +-- .../hooks/useLimitPerMetadataItem.ts | 4 +-- ...ltFormattedAsObjectRecordForSelectArray.ts | 4 +-- ...atchesSearchFilterAndSelectedItemsQuery.ts | 6 ++-- ...archMatchesSearchFilterAndToSelectQuery.ts | 6 ++-- .../useMultiObjectSearchSelectedItemsQuery.ts | 6 ++-- .../hooks/useOrderByFieldPerMetadataItem.ts | 4 +-- .../hooks/useSearchFilterPerMetadataItem.ts | 4 +-- .../utils/getChildRelationArray.ts | 7 ++-- .../utils/makeAndFilterVariables.ts | 4 +-- .../utils/makeOrFilterVariables.ts | 4 +-- .../utils/sanitizeRecordInput.ts | 4 +-- .../utils/sortObjectRecordByDateField.ts | 8 ++--- .../hooks/useFilteredSearchEntityQuery.ts | 8 ++--- .../components/UserTableColumn.tsx | 4 +-- .../input/components/DoubleTextInput.tsx | 4 +-- .../right-drawer/components/RightDrawer.tsx | 4 +-- .../hotkey/hooks/useSetHotkeyScope.ts | 4 +-- .../hooks/useClickOutsideListener.ts | 4 +-- .../hooks/useScopeInternalContextOrThrow.ts | 4 +-- .../ViewFieldsVisibilityDropdownSection.tsx | 6 ++-- .../views/components/ViewsDropdownButton.tsx | 4 +-- .../internal/useFiltersFromQueryParams.ts | 4 +-- .../src/modules/views/hooks/useViewBar.ts | 10 +++--- .../mapViewFieldsToBoardFieldDefinitions.ts | 4 +-- .../utils/mapViewFieldsToColumnDefinitions.ts | 4 +-- .../pages/object-record/RecordShowPage.tsx | 4 +-- .../src/testing/mock-data/index.ts | 6 ++-- .../src/utils/__tests__/assert.test.ts | 19 ---------- .../src/utils/__tests__/isDefined.test.ts | 19 ---------- .../src/utils/__tests__/isNonNullable.test.ts | 15 ++++++++ .../parseApolloStoreFieldName.test.ts | 30 ++++++++++++++++ .../src/utils/__tests__/sort.test.ts | 35 +++++++++++++++++++ ...yToCunks.test.ts => arrayToChunks.test.ts} | 0 .../array/__tests__/groupArrayItemsBy.test.ts | 25 +++++++++++++ .../array/__tests__/mapArrayToObject.test.ts | 23 ++++++++++++ .../src/utils/array/groupArrayItemsBy.ts | 30 +++++++++++++--- .../src/utils/array/mapArrayToObject.ts | 29 +++++++++++++-- .../src/utils/array/moveArrayItem.ts | 18 ++++++++-- packages/twenty-front/src/utils/assert.ts | 2 -- packages/twenty-front/src/utils/is-domain.ts | 4 +-- packages/twenty-front/src/utils/is-url.ts | 4 +-- packages/twenty-front/src/utils/isDefined.ts | 3 -- .../twenty-front/src/utils/isNonNullable.ts | 4 +++ .../src/utils/parseApolloStoreFieldName.ts | 15 ++++---- packages/twenty-front/src/utils/sort.ts | 2 +- 85 files changed, 396 insertions(+), 240 deletions(-) delete mode 100644 packages/twenty-front/src/utils/__tests__/assert.test.ts delete mode 100644 packages/twenty-front/src/utils/__tests__/isDefined.test.ts create mode 100644 packages/twenty-front/src/utils/__tests__/isNonNullable.test.ts create mode 100644 packages/twenty-front/src/utils/__tests__/parseApolloStoreFieldName.test.ts create mode 100644 packages/twenty-front/src/utils/__tests__/sort.test.ts rename packages/twenty-front/src/utils/array/__tests__/{arrayToCunks.test.ts => arrayToChunks.test.ts} (100%) create mode 100644 packages/twenty-front/src/utils/array/__tests__/groupArrayItemsBy.test.ts create mode 100644 packages/twenty-front/src/utils/array/__tests__/mapArrayToObject.test.ts delete mode 100644 packages/twenty-front/src/utils/assert.ts delete mode 100644 packages/twenty-front/src/utils/isDefined.ts create mode 100644 packages/twenty-front/src/utils/isNonNullable.ts diff --git a/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx b/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx index 05cc0bdd3..4eb7b3803 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx @@ -22,7 +22,7 @@ import { } from '@/ui/input/components/Checkbox'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; const StyledEditableTitleInput = styled.input<{ completed: boolean; @@ -166,7 +166,7 @@ export const ActivityTitle = ({ activityId }: ActivityTitleProps) => { }); }; - const completed = isDefined(activity.completedAt); + const completed = isNonNullable(activity.completedAt); return ( diff --git a/packages/twenty-front/src/modules/activities/hooks/useActivityConnectionUtils.ts b/packages/twenty-front/src/modules/activities/hooks/useActivityConnectionUtils.ts index 55cd0b401..a858368df 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useActivityConnectionUtils.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useActivityConnectionUtils.ts @@ -8,7 +8,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { getEmptyPageInfo } from '@/object-record/cache/utils/getEmptyPageInfo'; import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords'; import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useActivityConnectionUtils = () => { const mapConnectionToRecords = useMapConnectionToRecords(); @@ -19,7 +19,7 @@ export const useActivityConnectionUtils = () => { comments: ObjectRecordConnection; }, ) => { - if (!isDefined(activityWithConnections)) { + if (!isNonNullable(activityWithConnections)) { throw new Error('Activity with connections is not defined'); } diff --git a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts index 359b1c755..15e1fb1f9 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts @@ -7,7 +7,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { Nullable } from '~/types/Nullable'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useActivityTargetObjectRecords = ({ activityId, @@ -31,7 +31,7 @@ export const useActivityTargetObjectRecords = ({ .map>((activityTarget) => { const correspondingObjectMetadataItem = objectMetadataItems.find( (objectMetadataItem) => - isDefined(activityTarget[objectMetadataItem.nameSingular]) && + isNonNullable(activityTarget[objectMetadataItem.nameSingular]) && !objectMetadataItem.isSystem, ); @@ -47,7 +47,7 @@ export const useActivityTargetObjectRecords = ({ targetObjectNameSingular: correspondingObjectMetadataItem.nameSingular, }; }) - .filter(isDefined); + .filter(isNonNullable); return { activityTargetObjectRecords, diff --git a/packages/twenty-front/src/modules/activities/hooks/useAttachRelationInBothDirections.ts b/packages/twenty-front/src/modules/activities/hooks/useAttachRelationInBothDirections.ts index 2ef89de54..bdc0df87d 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useAttachRelationInBothDirections.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useAttachRelationInBothDirections.ts @@ -6,7 +6,7 @@ import { triggerAttachRelationOptimisticEffect } from '@/apollo/optimistic-effec import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { getObjectMetadataItemByNameSingular } from '@/object-metadata/utils/getObjectMetadataItemBySingularName'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useAttachRelationInBothDirections = () => { const { objectMetadataItems } = useObjectMetadataItems(); @@ -46,7 +46,7 @@ export const useAttachRelationInBothDirections = () => { (field) => field.name === fieldNameOnSourceRecord, ); - if (!isDefined(fieldMetadataItemOnSourceRecord)) { + if (!isNonNullable(fieldMetadataItemOnSourceRecord)) { throw new Error( `Field ${fieldNameOnSourceRecord} not found on object ${sourceObjectNameSingular}`, ); @@ -57,7 +57,7 @@ export const useAttachRelationInBothDirections = () => { objectMetadataItems, }); - if (!isDefined(relationDefinition)) { + if (!isNonNullable(relationDefinition)) { throw new Error( `Relation metadata not found for field ${fieldNameOnSourceRecord} on object ${sourceObjectNameSingular}`, ); diff --git a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts index b9809e797..5c1bd50d7 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts @@ -14,7 +14,7 @@ import { useCreateOneRecordInCache } from '@/object-record/hooks/useCreateOneRec import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useCreateActivityInCache = () => { const { createManyRecordsInCache: createManyActivityTargetsInCache } = @@ -71,7 +71,7 @@ export const useCreateActivityInCache = () => { return targetObject; }) - .filter(isDefined); + .filter(isNonNullable); const activityTargetsToCreate = makeActivityTargetsToCreateFromTargetableObjects({ diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts index f4a6210e1..9cde4d743 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts @@ -5,7 +5,7 @@ import { ActivityType } from '@/activities/types/Activity'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ActivityTargetableObject } from '../types/ActivityTargetableEntity'; @@ -47,7 +47,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = ( targetObjectRecord, }; }) - .filter(isDefined); + .filter(isNonNullable); if (relatedEntities) { activityTargetableObjectArray = diff --git a/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts b/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts index 4570622b5..746735dad 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts @@ -16,7 +16,7 @@ import { objectShowPageTargetableObjectState } from '@/activities/timeline/state import { Activity } from '@/activities/types/Activity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; // TODO: create a generic way to have records only in cache for create mode and delete them afterwards ? export const useUpsertActivity = () => { @@ -85,7 +85,7 @@ export const useUpsertActivity = () => { makeActivityWithConnection(activityToCreate); if (weAreOnTaskPage) { - if (isDefined(activityWithConnection.completedAt)) { + if (isNonNullable(activityWithConnection.completedAt)) { injectActivitiesQueries({ activitiesFilters: currentCompletedTaskQueryVariables?.filter, activitiesOrderByVariables: @@ -125,7 +125,7 @@ export const useUpsertActivity = () => { const injectOnlyInIdFilterForNotesQueries = activityWithConnection.type !== 'Note'; - if (isDefined(currentCompletedTaskQueryVariables)) { + if (isNonNullable(currentCompletedTaskQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentCompletedTaskQueryVariables?.filter, activitiesOrderByVariables: @@ -137,7 +137,7 @@ export const useUpsertActivity = () => { }); } - if (isDefined(currentIncompleteTaskQueryVariables)) { + if (isNonNullable(currentIncompleteTaskQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentIncompleteTaskQueryVariables?.filter ?? {}, @@ -150,7 +150,7 @@ export const useUpsertActivity = () => { }); } - if (isDefined(currentNotesQueryVariables)) { + if (isNonNullable(currentNotesQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentNotesQueryVariables?.filter, activitiesOrderByVariables: currentNotesQueryVariables?.orderBy, diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx index 9ae5f7d63..397255487 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx @@ -28,7 +28,7 @@ import { mapToRecordId } from '@/object-record/utils/mapToObjectId'; import { IconPlus, IconTrash } from '@/ui/display/icon'; import { IconButton } from '@/ui/input/button/components/IconButton'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; const StyledButtonContainer = styled.div` display: inline-flex; @@ -109,7 +109,10 @@ export const ActivityActionBar = () => { setIsRightDrawerOpen(false); if (viewableActivityId) { - if (isActivityInCreateMode && isDefined(temporaryActivityForEditor)) { + if ( + isActivityInCreateMode && + isNonNullable(temporaryActivityForEditor) + ) { deleteActivityFromCache(temporaryActivityForEditor); setTemporaryActivityForEditor(null); } else { @@ -136,7 +139,7 @@ export const ActivityActionBar = () => { }); } else if ( weAreOnObjectShowPage && - isDefined(objectShowPageTargetableObject) + isNonNullable(objectShowPageTargetableObject) ) { removeFromActivitiesQueries({ activityIdToRemove: viewableActivityId, @@ -146,7 +149,7 @@ export const ActivityActionBar = () => { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY, }); - if (isDefined(currentCompletedTaskQueryVariables)) { + if (isNonNullable(currentCompletedTaskQueryVariables)) { removeFromActivitiesQueries({ activityIdToRemove: viewableActivityId, targetableObjects: [objectShowPageTargetableObject], @@ -157,7 +160,7 @@ export const ActivityActionBar = () => { }); } - if (isDefined(currentIncompleteTaskQueryVariables)) { + if (isNonNullable(currentIncompleteTaskQueryVariables)) { removeFromActivitiesQueries({ activityIdToRemove: viewableActivityId, targetableObjects: [objectShowPageTargetableObject], @@ -168,7 +171,7 @@ export const ActivityActionBar = () => { }); } - if (isDefined(currentNotesQueryVariables)) { + if (isNonNullable(currentNotesQueryVariables)) { removeFromActivitiesQueries({ activityIdToRemove: viewableActivityId, targetableObjects: [objectShowPageTargetableObject], diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx index e28eee40b..2f548e80a 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx @@ -12,7 +12,7 @@ import { Activity } from '@/activities/types/Activity'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { sortObjectRecordByDateField } from '@/object-record/utils/sortObjectRecordByDateField'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const TimelineQueryEffect = ({ targetableObject, @@ -31,7 +31,7 @@ export const TimelineQueryEffect = ({ targetableObjects: [targetableObject], activitiesFilters: {}, activitiesOrderByVariables: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY, - skip: !isDefined(targetableObject), + skip: !isNonNullable(targetableObject), }); const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] = @@ -41,7 +41,7 @@ export const TimelineQueryEffect = ({ useRecoilState(timelineActivitiesForGroupState); useEffect(() => { - if (!isDefined(targetableObject)) { + if (!isNonNullable(targetableObject)) { return; } diff --git a/packages/twenty-front/src/modules/activities/timeline/hooks/useTimelineActivities.ts b/packages/twenty-front/src/modules/activities/timeline/hooks/useTimelineActivities.ts index 0af9d4931..8498ed4da 100644 --- a/packages/twenty-front/src/modules/activities/timeline/hooks/useTimelineActivities.ts +++ b/packages/twenty-front/src/modules/activities/timeline/hooks/useTimelineActivities.ts @@ -13,7 +13,7 @@ import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getR import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { sortByAscString } from '~/utils/array/sortByAscString'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useTimelineActivities = ({ targetableObject, @@ -27,7 +27,7 @@ export const useTimelineActivities = ({ ); useEffect(() => { - if (isDefined(targetableObject)) { + if (isNonNullable(targetableObject)) { setObjectShowPageTargetableObject(targetableObject); } }, [targetableObject, setObjectShowPageTargetableObject]); @@ -100,7 +100,7 @@ export const useTimelineActivities = ({ const activities = activitiesWithConnection ?.map(makeActivityWithoutConnection as any) .map(({ activity }: any) => activity as any) - .filter(isDefined); + .filter(isNonNullable); return { activities, diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/sortCachedObjectEdges.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/sortCachedObjectEdges.ts index 10d4514af..536563efd 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/sortCachedObjectEdges.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/sortCachedObjectEdges.ts @@ -4,7 +4,7 @@ import { ReadFieldFunction } from '@apollo/client/cache/core/types/common'; import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge'; import { OrderBy } from '@/object-metadata/types/OrderBy'; import { OrderByField } from '@/object-metadata/types/OrderByField'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { sortAsc, sortDesc, sortNullsFirst, sortNullsLast } from '~/utils/sort'; export const sortCachedObjectEdges = ({ @@ -31,7 +31,7 @@ export const sortCachedObjectEdges = ({ orderByFieldName, recordFromCache, ) ?? null; - const isSubFieldFilter = isDefined(fieldValue) && !!orderBySubFieldName; + const isSubFieldFilter = isNonNullable(fieldValue) && !!orderBySubFieldName; if (!isSubFieldFilter) return fieldValue as string | number | null; diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect.ts index ba99ce464..188d43083 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect.ts @@ -2,7 +2,7 @@ import { ApolloCache, StoreObject } from '@apollo/client'; import { isCachedObjectRecordConnection } from '@/apollo/optimistic-effect/utils/isCachedObjectRecordConnection'; import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const triggerAttachRelationOptimisticEffect = ({ @@ -43,7 +43,7 @@ export const triggerAttachRelationOptimisticEffect = ({ __typename: sourceRecordTypeName, }); - if (!isDefined(sourceRecordReference)) { + if (!isNonNullable(sourceRecordReference)) { return targetRecordFieldValue; } diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect.ts index 2478a3e30..6ffff14c7 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect.ts @@ -6,7 +6,7 @@ import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord'; import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge'; import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRecordQueryVariables'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName'; export const triggerDeleteRecordsOptimisticEffect = ({ @@ -38,7 +38,7 @@ export const triggerDeleteRecordsOptimisticEffect = ({ const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse; - const { fieldArguments: rootQueryVariables } = + const { fieldVariables: rootQueryVariables } = parseApolloStoreFieldName( storeFieldName, ); @@ -68,7 +68,7 @@ export const triggerDeleteRecordsOptimisticEffect = ({ // TODO: same as in update, should we trigger DELETE ? if ( - isDefined(rootQueryVariables?.first) && + isNonNullable(rootQueryVariables?.first) && cachedEdges?.length === rootQueryVariables.first ) { return DELETE; diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect.ts index fa544b664..92890351c 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect.ts @@ -9,7 +9,7 @@ import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRec import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename'; import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName'; // TODO: add extensive unit tests for this function @@ -56,7 +56,7 @@ export const triggerUpdateRecordOptimisticEffect = ({ const rootQueryConnection = rootQueryCachedResponse; - const { fieldArguments: rootQueryVariables } = + const { fieldVariables: rootQueryVariables } = parseApolloStoreFieldName( storeFieldName, ); @@ -71,7 +71,7 @@ export const triggerUpdateRecordOptimisticEffect = ({ const rootQueryOrderBy = rootQueryVariables?.orderBy; const rootQueryLimit = rootQueryVariables?.first; - const shouldTryToMatchFilter = isDefined(rootQueryFilter); + const shouldTryToMatchFilter = isNonNullable(rootQueryFilter); if (shouldTryToMatchFilter) { const updatedRecordMatchesThisRootQueryFilter = @@ -101,7 +101,7 @@ export const triggerUpdateRecordOptimisticEffect = ({ if (updatedRecordShouldBeAddedToRootQueryEdges) { const updatedRecordNodeReference = toReference(updatedRecord); - if (isDefined(updatedRecordNodeReference)) { + if (isNonNullable(updatedRecordNodeReference)) { rootQueryNextEdges.push({ __typename: objectEdgeTypeName, node: updatedRecordNodeReference, @@ -115,7 +115,8 @@ export const triggerUpdateRecordOptimisticEffect = ({ } } - const rootQueryNextEdgesShouldBeSorted = isDefined(rootQueryOrderBy); + const rootQueryNextEdgesShouldBeSorted = + isNonNullable(rootQueryOrderBy); if ( rootQueryNextEdgesShouldBeSorted && @@ -128,7 +129,7 @@ export const triggerUpdateRecordOptimisticEffect = ({ }); } - const shouldLimitNextRootQueryEdges = isDefined(rootQueryLimit); + const shouldLimitNextRootQueryEdges = isNonNullable(rootQueryLimit); // TODO: not sure that we should trigger a DELETE here, as it will trigger a network request // Is it the responsibility of this optimistic effect function to delete a root query that will trigger a network request ? diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts index 633fde736..aa9eac813 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts @@ -12,7 +12,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const triggerUpdateRelationsOptimisticEffect = ({ cache, @@ -36,7 +36,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({ } const fieldDoesNotExist = - isDefined(updatedSourceRecord) && + isNonNullable(updatedSourceRecord) && !(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord); if (fieldDoesNotExist) { @@ -87,7 +87,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({ ? currentFieldValueOnSourceRecord.edges.map( ({ node }) => node as CachedObjectRecord, ) - : [currentFieldValueOnSourceRecord].filter(isDefined); + : [currentFieldValueOnSourceRecord].filter(isNonNullable); const updatedFieldValueOnSourceRecordIsARecordConnection = isObjectRecordConnection( @@ -100,10 +100,11 @@ export const triggerUpdateRelationsOptimisticEffect = ({ ? updatedFieldValueOnSourceRecord.edges.map( ({ node }) => node as CachedObjectRecord, ) - : [updatedFieldValueOnSourceRecord].filter(isDefined); + : [updatedFieldValueOnSourceRecord].filter(isNonNullable); const shouldDetachSourceFromAllTargets = - isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0; + isNonNullable(currentSourceRecord) && + targetRecordsToDetachFrom.length > 0; if (shouldDetachSourceFromAllTargets) { // TODO: see if we can de-hardcode this, put cascade delete in relation metadata item diff --git a/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts b/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts index ac16aecf0..23b4612f5 100644 --- a/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts +++ b/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts @@ -14,7 +14,7 @@ import { createUploadLink } from 'apollo-upload-client'; import { renewToken } from '@/auth/services/AuthService'; import { AuthTokenPair } from '~/generated/graphql'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; import { logDebug } from '~/utils/logDebug'; import { ApolloManager } from '../types/apolloManager.interface'; @@ -139,7 +139,7 @@ export class ApolloFactory implements ApolloManager { isDebugMode ? logger : null, retryLink, httpLink, - ].filter(assertNotNull), + ].filter(isNonNullable), ); }; diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts index cd2996f78..8614bfc60 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts @@ -11,7 +11,7 @@ import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useFavorites = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); @@ -56,7 +56,7 @@ export const useFavorites = () => { return favorites .map((favorite) => { for (const relationField of favoriteRelationFieldMetadataItems) { - if (isDefined(favorite[relationField.name])) { + if (isNonNullable(favorite[relationField.name])) { const relationObject = favorite[relationField.name]; const relationObjectNameSingular = diff --git a/packages/twenty-front/src/modules/favorites/utils/mapFavorites.ts b/packages/twenty-front/src/modules/favorites/utils/mapFavorites.ts index 4a9d42492..ae9fae903 100644 --- a/packages/twenty-front/src/modules/favorites/utils/mapFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/utils/mapFavorites.ts @@ -1,11 +1,10 @@ import { getLogoUrlFromDomainName } from '~/utils'; -import { assertNotNull } from '~/utils/assert'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const mapFavorites = (favorites: any) => { return favorites .map((favorite: any) => { - const recordInformation = isDefined(favorite?.person) + const recordInformation = isNonNullable(favorite?.person) ? { id: favorite.person.id, labelIdentifier: @@ -16,7 +15,7 @@ export const mapFavorites = (favorites: any) => { avatarType: 'rounded', link: `/object/person/${favorite.person.id}`, } - : isDefined(favorite?.company) + : isNonNullable(favorite?.company) ? { id: favorite.company.id, labelIdentifier: favorite.company.name, @@ -33,6 +32,6 @@ export const mapFavorites = (favorites: any) => { position: favorite?.position, }; }) - .filter(assertNotNull) + .filter(isNonNullable) .sort((a: any, b: any) => a.position - b.position); }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useFilterOutUnexistingObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useFilterOutUnexistingObjectMetadataItems.ts index 8241aeffb..75ad0aed1 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useFilterOutUnexistingObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useFilterOutUnexistingObjectMetadataItems.ts @@ -2,7 +2,7 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsByNameSingularMapSelector } from '@/object-metadata/states/objectMetadataItemsByNameSingularMapSelector'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useFilterOutUnexistingObjectMetadataItems = () => { const objectMetadataItemsByNameSingularMap = useRecoilValue( @@ -12,7 +12,7 @@ export const useFilterOutUnexistingObjectMetadataItems = () => { const filterOutUnexistingObjectMetadataItems = ( objectMetadatItem: ObjectMetadataItem, ) => - isDefined( + isNonNullable( objectMetadataItemsByNameSingularMap.get(objectMetadatItem.nameSingular), ); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index f7abee464..95b88de5e 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -21,7 +21,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery'; import { useGenerateUpdateOneRecordMutation } from '@/object-record/hooks/useGenerateUpdateOneRecordMutation'; import { generateDeleteOneRecordMutation } from '@/object-record/utils/generateDeleteOneRecordMutation'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier'; @@ -63,7 +63,7 @@ export const useObjectMetadataItem = ( objectMetadataItems = mockObjectMetadataItems; } - if (!isDefined(objectMetadataItem)) { + if (!isNonNullable(objectMetadataItem)) { throw new ObjectMetadataItemNotFoundError( objectNameSingular, objectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts index d5e5b3f55..12dc6f28e 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts @@ -5,7 +5,7 @@ import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/Object import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier'; @@ -34,7 +34,7 @@ export const useObjectMetadataItemOnly = ({ objectMetadataItems = mockObjectMetadataItems; } - if (!isDefined(objectMetadataItem)) { + if (!isNonNullable(objectMetadataItem)) { throw new ObjectMetadataItemNotFoundError( objectNameSingular, objectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts index 3cf1c60bb..412006108 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useObjectNamePluralFromSingular = ({ objectNameSingular, @@ -28,7 +28,7 @@ export const useObjectNamePluralFromSingular = ({ ) ?? null; } - if (!isDefined(objectMetadataItem)) { + if (!isNonNullable(objectMetadataItem)) { throw new Error( `Object metadata item not found for ${objectNameSingular} object`, ); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts index 432a3b718..6a00794f8 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useObjectNameSingularFromPlural = ({ objectNamePlural, @@ -29,7 +29,7 @@ export const useObjectNameSingularFromPlural = ({ ) ?? null; } - if (!isDefined(objectMetadataItem)) { + if (!isNonNullable(objectMetadataItem)) { throw new Error( `Object metadata item not found for ${objectNamePlural} object`, ); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/isLabelIdentifierField.ts b/packages/twenty-front/src/modules/object-metadata/utils/isLabelIdentifierField.ts index 06bc0c576..489ea0e26 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/isLabelIdentifierField.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/isLabelIdentifierField.ts @@ -1,6 +1,6 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const DEFAULT_LABEL_IDENTIFIER_FIELD_NAME = 'name'; @@ -14,6 +14,6 @@ export const isLabelIdentifierField = ({ 'labelIdentifierFieldMetadataId' >; }) => - isDefined(objectMetadataItem.labelIdentifierFieldMetadataId) + isNonNullable(objectMetadataItem.labelIdentifierFieldMetadataId) ? fieldMetadataItem.id === objectMetadataItem.labelIdentifierFieldMetadataId : fieldMetadataItem.name === DEFAULT_LABEL_IDENTIFIER_FIELD_NAME; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts b/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts index 65a90c8fa..de9d705e4 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts @@ -4,7 +4,7 @@ import { FieldMetadataType, RelationMetadataType, } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const parseFieldRelationType = ( field: FieldMetadataItem | undefined, @@ -30,14 +30,14 @@ export const parseFieldRelationType = ( }; if ( - isDefined(field.fromRelationMetadata) && + isNonNullable(field.fromRelationMetadata) && field.fromRelationMetadata.relationType in config ) { return config[field.fromRelationMetadata.relationType].from; } if ( - isDefined(field.toRelationMetadata) && + isNonNullable(field.toRelationMetadata) && field.toRelationMetadata.relationType in config ) { return config[field.toRelationMetadata.relationType].to; diff --git a/packages/twenty-front/src/modules/object-record/cache/hooks/useReadFindManyRecordsQueryInCache.ts b/packages/twenty-front/src/modules/object-record/cache/hooks/useReadFindManyRecordsQueryInCache.ts index 4b0bc978e..56e7e09cd 100644 --- a/packages/twenty-front/src/modules/object-record/cache/hooks/useReadFindManyRecordsQueryInCache.ts +++ b/packages/twenty-front/src/modules/object-record/cache/hooks/useReadFindManyRecordsQueryInCache.ts @@ -6,7 +6,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecordQueryResult } from '@/object-record/types/ObjectRecordQueryResult'; import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useReadFindManyRecordsQueryInCache = ({ objectMetadataItem, @@ -38,7 +38,7 @@ export const useReadFindManyRecordsQueryInCache = ({ const existingRecordConnection = existingRecordsQueryResult?.[objectMetadataItem.namePlural]; - const existingObjectRecords = isDefined(existingRecordConnection) + const existingObjectRecords = isNonNullable(existingRecordConnection) ? getRecordsFromRecordConnection({ recordConnection: existingRecordConnection, }) diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx index 6d58d3b7d..9694cc6ce 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx @@ -13,7 +13,7 @@ import { import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords'; import { Person } from '@/people/types/Person'; import { getJestHookWrapper } from '~/testing/jest/getJestHookWrapper'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; const Wrapper = getJestHookWrapper({ apolloMocks: [], @@ -184,7 +184,7 @@ describe('useMapConnectionToRecords', () => { expect(isNonEmptyArray(peopleResult)).toBe(true); expect(firstPersonResult.id).toBe(firstPersonMock.id); - expect(isDefined(firstPersonsCompanyresult)).toBe(true); + expect(isNonNullable(firstPersonsCompanyresult)).toBe(true); expect(firstPersonsCompanyresult.id).toEqual(firstPersonsCompanyMock.id); }); }); diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDeleteManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useDeleteManyRecords.ts index b3236cc5d..7b2f392cf 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useDeleteManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useDeleteManyRecords.ts @@ -4,7 +4,7 @@ import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { getDeleteManyRecordsMutationResponseField } from '@/object-record/hooks/useGenerateDeleteManyRecordMutation'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; type useDeleteOneRecordProps = { @@ -56,7 +56,7 @@ export const useDeleteManyRecords = ({ const cachedRecords = records .map((record) => getRecordFromCache(record.id, cache)) - .filter(isDefined); + .filter(isNonNullable); triggerDeleteRecordsOptimisticEffect({ cache, diff --git a/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts index a682f1e2b..03b599846 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts @@ -8,7 +8,7 @@ import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelati import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection'; import { FieldMetadataType } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useMapConnectionToRecords = () => { const objectMetadataItems = useRecoilValue(objectMetadataItemsState); @@ -26,7 +26,7 @@ export const useMapConnectionToRecords = () => { depth: number; }): ObjectRecord[] => { if ( - !isDefined(objectRecordConnection) || + !isNonNullable(objectRecordConnection) || !isNonEmptyArray(objectMetadataItems) ) { return []; @@ -79,7 +79,7 @@ export const useMapConnectionToRecords = () => { if ( !relationFieldMetadataItem || - !isDefined(relatedObjectMetadataSingularName) + !isNonNullable(relatedObjectMetadataSingularName) ) { throw new Error( `Could not find relation object metadata item for object name plural ${relationField.name} in mapConnectionToRecords`, @@ -90,7 +90,7 @@ export const useMapConnectionToRecords = () => { relationField.name ] as ObjectRecordConnection | undefined | null; - if (!isDefined(relationConnection)) { + if (!isNonNullable(relationConnection)) { continue; } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx index a7154459a..f397312f4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx @@ -1,6 +1,6 @@ import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const ObjectFilterDropdownDateSearchInput = () => { const { @@ -15,9 +15,9 @@ export const ObjectFilterDropdownDateSearchInput = () => { selectFilter?.({ fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, - value: isDefined(date) ? date.toISOString() : '', + value: isNonNullable(date) ? date.toISOString() : '', operand: selectedOperandInDropdown, - displayValue: isDefined(date) ? date.toLocaleString() : '', + displayValue: isNonNullable(date) ? date.toLocaleString() : '', definition: filterDefinitionUsedInDropdown, }); diff --git a/packages/twenty-front/src/modules/object-record/record-board-deprecated/components/RecordBoardDeprecatedInternalEffect.tsx b/packages/twenty-front/src/modules/object-record/record-board-deprecated/components/RecordBoardDeprecatedInternalEffect.tsx index b1a3c998a..f9c916d32 100644 --- a/packages/twenty-front/src/modules/object-record/record-board-deprecated/components/RecordBoardDeprecatedInternalEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board-deprecated/components/RecordBoardDeprecatedInternalEffect.tsx @@ -6,7 +6,7 @@ import { useRecordBoardDeprecatedActionBarEntriesInternal } from '@/object-recor import { useRecordBoardDeprecatedContextMenuEntriesInternal } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedContextMenuEntriesInternal'; import { useRecordBoardDeprecatedScopedStates } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedScopedStates'; import { useUpdateCompanyBoardColumnsInternal } from '@/object-record/record-board-deprecated/hooks/internal/useUpdateCompanyBoardColumnsInternal'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export type RecordBoardDeprecatedInternalEffectProps = { onFieldsChange: (fields: any) => void; @@ -40,13 +40,13 @@ export const RecordBoardDeprecatedInternalEffect = () => { }, [opportunities, setSavedOpportunities]); useEffect(() => { - if (isDefined(fetchMoreOpportunities)) { + if (isNonNullable(fetchMoreOpportunities)) { fetchMoreOpportunities(); } }, [fetchMoreOpportunities]); useEffect(() => { - if (isDefined(fetchMoreCompanies)) { + if (isNonNullable(fetchMoreCompanies)) { fetchMoreCompanies(); } }, [fetchMoreCompanies]); diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap.ts b/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap.ts index 46d5c6123..c2ab6ed95 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap.ts @@ -5,7 +5,7 @@ import { recordBoardColumnsFamilyStateScopeMap } from '@/object-record/record-bo import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition'; import { createFamilySelectorScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilySelectorScopeMap'; import { guardRecoilDefaultValue } from '@/ui/utilities/recoil-scope/utils/guardRecoilDefaultValue'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; export const recordBoardColumnsFamilySelectorScopeMap = createFamilySelectorScopeMap( @@ -57,7 +57,7 @@ export const recordBoardColumnsFamilySelectorScopeMap = }), ); }) - .filter(assertNotNull); + .filter(isNonNullable); const lastColumn = [...columns].sort( (a, b) => b.position - a.position, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents.ts index c4aa0b308..80343923a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents.ts @@ -2,7 +2,7 @@ import { Key } from 'ts-key-enum'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useRegisterInputEvents = ({ inputRef, @@ -30,7 +30,7 @@ export const useRegisterInputEvents = ({ onClickOutside?.(event, inputValue); }, - enabled: isDefined(onClickOutside), + enabled: isNonNullable(onClickOutside), }); useScopedHotkeys( diff --git a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts index c9e4d04a8..d4f8877f5 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts @@ -17,9 +17,9 @@ import { isFieldSelect } from '@/object-record/record-field/types/guards/isField import { isFieldSelectValue } from '@/object-record/record-field/types/guards/isFieldSelectValue'; import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText'; import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; -const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === ''; +const isValueEmpty = (value: unknown) => !isNonNullable(value) || value === ''; export const isFieldValueEmpty = ({ fieldDefinition, @@ -46,7 +46,7 @@ export const isFieldValueEmpty = ({ } if (isFieldSelect(fieldDefinition)) { - return isFieldSelectValue(fieldValue) && !assertNotNull(fieldValue); + return isFieldSelectValue(fieldValue) && !isNonNullable(fieldValue); } if (isFieldCurrency(fieldDefinition)) { diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts index 49347b22f..9a2ff1ff8 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts @@ -22,8 +22,8 @@ import { isMatchingFloatFilter } from '@/object-record/record-filter/utils/isMat import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter'; import { isMatchingUUIDFilter } from '@/object-record/record-filter/utils/isMatchingUUIDFilter'; import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; import { isEmptyObject } from '~/utils/isEmptyObject'; +import { isNonNullable } from '~/utils/isNonNullable'; const isAndFilter = ( filter: ObjectRecordQueryFilter, @@ -102,7 +102,7 @@ export const isRecordMatchingFilter = ({ if (isNotFilter(filter)) { const filterValue = filter.not; - if (!isDefined(filterValue)) { + if (!isNonNullable(filterValue)) { throw new Error('Unexpected value for "not" filter : ' + filterValue); } @@ -117,7 +117,7 @@ export const isRecordMatchingFilter = ({ } return Object.entries(filter).every(([filterKey, filterValue]) => { - if (!isDefined(filterValue)) { + if (!isNonNullable(filterValue)) { throw new Error( 'Unexpected value for filter key "' + filterKey + '" : ' + filterValue, ); @@ -129,7 +129,7 @@ export const isRecordMatchingFilter = ({ (field) => field.name === filterKey, ); - if (!isDefined(objectMetadataField)) { + if (!isNonNullable(objectMetadataField)) { throw new Error( 'Field metadata item "' + filterKey + diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts index 5c19a8fa2..352166c0a 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts @@ -11,7 +11,7 @@ import { import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { Field } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { Filter } from '../../object-filter-dropdown/types/Filter'; @@ -38,7 +38,7 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); } - if (!isDefined(rawUIFilter.value) || rawUIFilter.value === '') { + if (!isNonNullable(rawUIFilter.value) || rawUIFilter.value === '') { return undefined; } diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 6c39968d5..98f4e4f13 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -30,7 +30,7 @@ import { FileFolder, useUploadImageMutation, } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; type RecordShowContainerProps = { objectNameSingular: string; @@ -131,7 +131,7 @@ export const RecordShowContainer = ({ - {!recordLoading && isDefined(recordFromStore) && ( + {!recordLoading && isNonNullable(recordFromStore) && ( <> { - if (!loading && isDefined(record)) { + if (!loading && isNonNullable(record)) { const { activity: activityWithoutConnection } = makeActivityWithoutConnection(record as any); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx index 6385b06c4..8273f15f8 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx @@ -13,7 +13,7 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; import { EntityForSelect } from '../types/EntityForSelect'; import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope'; @@ -55,7 +55,7 @@ export const SingleEntitySelectMenuItems = ({ const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter( (entity): entity is EntityForSelect => - assertNotNull(entity) && isNonEmptyString(entity.name), + isNonNullable(entity) && isNonEmptyString(entity.name), ); useScopedHotkeys( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx index c24c35aee..d2b814237 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx @@ -6,7 +6,7 @@ import { import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch'; @@ -42,7 +42,7 @@ export const SingleEntitySelectMenuItemsWithSearch = ({ relationPickerScopeId, }); - const showCreateButton = isDefined(onCreate) && searchFilter !== ''; + const showCreateButton = isNonNullable(onCreate) && searchFilter !== ''; const entities = useFilteredSearchEntityQuery({ filters: [ diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts index 95be7ef2b..29602a6a4 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts @@ -1,6 +1,6 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const useLimitPerMetadataItem = ({ @@ -15,7 +15,7 @@ export const useLimitPerMetadataItem = ({ .map(({ nameSingular }) => { return [`limit${capitalize(nameSingular)}`, limit]; }) - .filter(isDefined), + .filter(isNonNullable), ); return { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts index eedf25327..6091f2b85 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts @@ -5,7 +5,7 @@ import { objectMetadataItemsByNamePluralMapSelector } from '@/object-metadata/st import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier'; import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export type MultiObjectRecordQueryResult = { [namePlural: string]: ObjectRecordConnection; @@ -30,7 +30,7 @@ export const useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArr const objectMetadataItem = objectMetadataItemsByNamePluralMap.get(namePlural); - if (!isDefined(objectMetadataItem)) return []; + if (!isNonNullable(objectMetadataItem)) return []; return objectRecordConnection.edges.map(({ node }) => ({ objectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts index cc48f29b8..635f2e754 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts @@ -13,7 +13,7 @@ import { import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem'; import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({ @@ -71,7 +71,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({ }, ]; }) - .filter(isDefined), + .filter(isNonNullable), ); const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({ @@ -99,7 +99,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({ ...orderByFieldPerMetadataItem, ...limitPerMetadataItem, }, - skip: !isDefined(multiSelectQueryForSelectedIds), + skip: !isNonNullable(multiSelectQueryForSelectedIds), }, ); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts index 518f78477..538b61919 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts @@ -14,7 +14,7 @@ import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/us import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem'; import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({ @@ -72,7 +72,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({ makeAndFilterVariables(searchFilters), ]; }) - .filter(isDefined), + .filter(isNonNullable), ); const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({ @@ -98,7 +98,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({ ...orderByFieldPerMetadataItem, ...limitPerMetadataItem, }, - skip: !isDefined(multiSelectQuery), + skip: !isNonNullable(multiSelectQuery), }); const { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts index f522d66a0..2c18f7d3b 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts @@ -12,7 +12,7 @@ import { } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const EMPTY_QUERY = gql` @@ -56,7 +56,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({ }, ]; }) - .filter(isDefined), + .filter(isNonNullable), ); const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({ @@ -83,7 +83,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({ ...orderByFieldPerMetadataItem, ...limitPerMetadataItem, }, - skip: !isDefined(multiSelectQueryForSelectedIds), + skip: !isNonNullable(multiSelectQueryForSelectedIds), }, ); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts index 42dd28f99..c04f650cd 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts @@ -1,6 +1,6 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getObjectOrderByField } from '@/object-metadata/utils/getObjectOrderByField'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { capitalize } from '~/utils/string/capitalize'; export const useOrderByFieldPerMetadataItem = ({ @@ -20,7 +20,7 @@ export const useOrderByFieldPerMetadataItem = ({ }, ]; }) - .filter(isDefined), + .filter(isNonNullable), ); return { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts index 1f54a8e96..0242a9202 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts @@ -3,7 +3,7 @@ import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/get import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables'; import { FieldMetadataType } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useSearchFilterPerMetadataItem = ({ objectMetadataItems, @@ -64,7 +64,7 @@ export const useSearchFilterPerMetadataItem = ({ return [objectMetadataItem.nameSingular, searchFilter] as const; }) - .filter(isDefined), + .filter(isNonNullable), ); return { diff --git a/packages/twenty-front/src/modules/object-record/utils/getChildRelationArray.ts b/packages/twenty-front/src/modules/object-record/utils/getChildRelationArray.ts index f7a93507c..74705662c 100644 --- a/packages/twenty-front/src/modules/object-record/utils/getChildRelationArray.ts +++ b/packages/twenty-front/src/modules/object-record/utils/getChildRelationArray.ts @@ -1,12 +1,15 @@ import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const getChildRelationArray = ({ childRelation, }: { childRelation: any; }) => { - if (isDefined(childRelation.edges) && Array.isArray(childRelation.edges)) { + if ( + isNonNullable(childRelation.edges) && + Array.isArray(childRelation.edges) + ) { return childRelation.edges.map((edge: ObjectRecordEdge) => edge.node); } else { return childRelation; diff --git a/packages/twenty-front/src/modules/object-record/utils/makeAndFilterVariables.ts b/packages/twenty-front/src/modules/object-record/utils/makeAndFilterVariables.ts index 2f5e36d93..1b97474be 100644 --- a/packages/twenty-front/src/modules/object-record/utils/makeAndFilterVariables.ts +++ b/packages/twenty-front/src/modules/object-record/utils/makeAndFilterVariables.ts @@ -1,10 +1,10 @@ import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const makeAndFilterVariables = ( filters: (ObjectRecordQueryFilter | undefined)[], ): ObjectRecordQueryFilter | undefined => { - const definedFilters = filters.filter(isDefined); + const definedFilters = filters.filter(isNonNullable); if (!definedFilters.length) return undefined; diff --git a/packages/twenty-front/src/modules/object-record/utils/makeOrFilterVariables.ts b/packages/twenty-front/src/modules/object-record/utils/makeOrFilterVariables.ts index 01cceb25c..2441ffee1 100644 --- a/packages/twenty-front/src/modules/object-record/utils/makeOrFilterVariables.ts +++ b/packages/twenty-front/src/modules/object-record/utils/makeOrFilterVariables.ts @@ -1,10 +1,10 @@ import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const makeOrFilterVariables = ( filters: (ObjectRecordQueryFilter | undefined)[], ): ObjectRecordQueryFilter | undefined => { - const definedFilters = filters.filter(isDefined); + const definedFilters = filters.filter(isNonNullable); if (!definedFilters.length) return undefined; diff --git a/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts b/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts index 4dd64c020..f8e572d97 100644 --- a/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts +++ b/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts @@ -5,7 +5,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { isFieldRelationValue } from '@/object-record/record-field/types/guards/isFieldRelationValue'; import { sanitizeLink } from '@/object-record/utils/sanitizeLinkRecordInput'; import { FieldMetadataType } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const sanitizeRecordInput = ({ objectMetadataItem, @@ -39,7 +39,7 @@ export const sanitizeRecordInput = ({ return [fieldName, fieldValue]; }) - .filter(isDefined), + .filter(isNonNullable), ); if ( objectMetadataItem.nameSingular !== CoreObjectNameSingular.Company || diff --git a/packages/twenty-front/src/modules/object-record/utils/sortObjectRecordByDateField.ts b/packages/twenty-front/src/modules/object-record/utils/sortObjectRecordByDateField.ts index 10b0b3269..bd9c1a66e 100644 --- a/packages/twenty-front/src/modules/object-record/utils/sortObjectRecordByDateField.ts +++ b/packages/twenty-front/src/modules/object-record/utils/sortObjectRecordByDateField.ts @@ -2,7 +2,7 @@ import { DateTime } from 'luxon'; import { OrderBy } from '@/object-metadata/types/OrderBy'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; const SORT_BEFORE = -1; const SORT_AFTER = 1; @@ -14,11 +14,11 @@ export const sortObjectRecordByDateField = const aDate = a[dateField]; const bDate = b[dateField]; - if (!isDefined(aDate) && !isDefined(bDate)) { + if (!isNonNullable(aDate) && !isNonNullable(bDate)) { return SORT_EQUAL; } - if (!isDefined(aDate)) { + if (!isNonNullable(aDate)) { if (sortDirection === 'AscNullsFirst') { return SORT_BEFORE; } else if (sortDirection === 'DescNullsFirst') { @@ -32,7 +32,7 @@ export const sortObjectRecordByDateField = throw new Error(`Invalid sortDirection: ${sortDirection}`); } - if (!isDefined(bDate)) { + if (!isNonNullable(bDate)) { if (sortDirection === 'AscNullsFirst') { return SORT_AFTER; } else if (sortDirection === 'DescNullsFirst') { diff --git a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts index 939160961..316c092cb 100644 --- a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts @@ -9,7 +9,7 @@ import { EntityForSelect } from '@/object-record/relation-picker/types/EntityFor import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; type SearchFilter = { fieldNames: string[]; filter: string | number }; @@ -104,13 +104,13 @@ export const useFilteredSearchEntityQuery = ({ return { selectedEntities: selectedRecords .map(mappingFunction) - .filter(assertNotNull), + .filter(isNonNullable), filteredSelectedEntities: filteredSelectedRecords .map(mappingFunction) - .filter(assertNotNull), + .filter(isNonNullable), entitiesToSelect: recordsToSelect .map(mappingFunction) - .filter(assertNotNull), + .filter(isNonNullable), loading: recordsToSelectLoading || filteredSelectedRecordsLoading || diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UserTableColumn.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UserTableColumn.tsx index 85e1be223..e93927fbf 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UserTableColumn.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UserTableColumn.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { RawData } from '@/spreadsheet-import/types'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; import { Column } from '../MatchColumnsStep'; @@ -39,7 +39,7 @@ export const UserTableColumn = ({ entries, }: UserTableColumnProps) => { const { header } = column; - const entry = entries.find(assertNotNull); + const entry = entries.find(isNonNullable); return ( diff --git a/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx index 3a5b387aa..5e87a3025 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx @@ -5,7 +5,7 @@ import { Key } from 'ts-key-enum'; import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleText'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { StyledInput } from './TextInput'; @@ -147,7 +147,7 @@ export const DoubleTextInput = ({ secondValue: secondInternalValue, }); }, - enabled: isDefined(onClickOutside), + enabled: isNonNullable(onClickOutside), }); return ( diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 445039aa7..1543b1f67 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -10,7 +10,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; import { ClickOutsideMode } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { useRightDrawer } from '../hooks/useRightDrawer'; import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState'; @@ -84,7 +84,7 @@ export const RightDrawer = () => { : theme.rightDrawerWidth : '0'; - if (!isDefined(rightDrawerPage)) { + if (!isNonNullable(rightDrawerPage)) { return <>; } diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts index 59f6253dd..26f29170c 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts @@ -1,6 +1,6 @@ import { useRecoilCallback } from 'recoil'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { DEFAULT_HOTKEYS_SCOPE_CUSTOM_SCOPES } from '../constants/DefaultHotkeysScopeCustomScopes'; import { currentHotkeyScopeState } from '../states/internal/currentHotkeyScopeState'; @@ -30,7 +30,7 @@ export const useSetHotkeyScope = () => .valueOrThrow(); if (currentHotkeyScope.scope === hotkeyScopeToSet) { - if (!isDefined(customScopes)) { + if (!isNonNullable(customScopes)) { if ( isCustomScopesEqual( currentHotkeyScope?.customScopes, diff --git a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts index e1db02e48..3c41eab55 100644 --- a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts +++ b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts @@ -8,7 +8,7 @@ import { } from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2'; import { ClickOutsideListenerCallback } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallback'; import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const useClickOutsideListener = (componentId: string) => { // TODO: improve typing @@ -67,7 +67,7 @@ export const useClickOutsideListener = (componentId: string) => { (callback) => callback.callbackId === callbackId, ); - if (!isDefined(existingCallbackWithSameId)) { + if (!isNonNullable(existingCallbackWithSameId)) { const existingCallbacksWithNewCallback = existingCallbacks.concat({ callbackId, callbackFunction, diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow.ts index 876efdee2..4c199e8d9 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow.ts @@ -1,6 +1,6 @@ import { useContext } from 'react'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ScopeInternalContext } from '../types/ScopeInternalContext'; @@ -9,7 +9,7 @@ export const useScopeInternalContextOrThrow = ( ) => { const context = useContext(Context); - if (!isDefined(context)) { + if (!isNonNullable(context)) { throw new Error( `Using a scope context without a ScopeInternalContext.Provider wrapper for context : ${Context.displayName}.`, ); diff --git a/packages/twenty-front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx b/packages/twenty-front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx index 32a784192..589837014 100644 --- a/packages/twenty-front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx @@ -20,7 +20,7 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; type ViewFieldsVisibilityDropdownSectionProps = { fields: Omit, 'size'>[]; @@ -69,7 +69,7 @@ export const ViewFieldsVisibilityDropdownSection = ({ Icon: field.isVisible ? IconMinus : IconPlus, onClick: () => onVisibilityChange(field), }, - ].filter(isDefined); + ].filter(isNonNullable); return iconButtons.length ? iconButtons : undefined; }; @@ -134,7 +134,7 @@ export const ViewFieldsVisibilityDropdownSection = ({ /> )} - {isDefined(openToolTipIndex) && + {isNonNullable(openToolTipIndex) && createPortal( handleViewSelect(view.id)} LeftIcon={IconList} text={view.name} diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts b/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts index 68636f597..ba17a330b 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts @@ -14,7 +14,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; const filterQueryParamsSchema = z.object({ filter: z.record( @@ -142,7 +142,7 @@ export const useFiltersFromQueryParams = () => { }, ), ) - ).filter(assertNotNull); + ).filter(isNonNullable); }, [ apolloClient, diff --git a/packages/twenty-front/src/modules/views/hooks/useViewBar.ts b/packages/twenty-front/src/modules/views/hooks/useViewBar.ts index af1500336..358dcfa3c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useViewBar.ts +++ b/packages/twenty-front/src/modules/views/hooks/useViewBar.ts @@ -7,8 +7,8 @@ import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-i import { ViewField } from '@/views/types/ViewField'; import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewSort } from '@/views/types/ViewSort'; -import { assertNotNull } from '~/utils/assert'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext'; import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState'; @@ -116,9 +116,7 @@ export const useViewBar = (props?: UseViewProps) => { return; } - const queriedViewFields = viewFields - .map((viewField) => viewField) - .filter(assertNotNull); + const queriedViewFields = viewFields.filter(isNonNullable); if (isPersistingView) { return; @@ -173,7 +171,7 @@ export const useViewBar = (props?: UseViewProps) => { definition: availableFilterDefinition, }; }) - .filter(assertNotNull); + .filter(isNonNullable); if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) { set(savedViewFiltersState, queriedViewFilters); @@ -220,7 +218,7 @@ export const useViewBar = (props?: UseViewProps) => { definition: availableSortDefinition, }; }) - .filter(assertNotNull); + .filter(isNonNullable); if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) { set(savedViewSortsState, queriedViewSorts); diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts b/packages/twenty-front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts index 5802aae1b..5a9573f2f 100644 --- a/packages/twenty-front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts +++ b/packages/twenty-front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts @@ -1,6 +1,6 @@ import { BoardFieldDefinition } from '@/object-record/record-board-deprecated/types/BoardFieldDefinition'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ViewField } from '../types/ViewField'; @@ -28,5 +28,5 @@ export const mapViewFieldsToBoardFieldDefinitions = ( } : null; }) - .filter(assertNotNull); + .filter(isNonNullable); }; diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts b/packages/twenty-front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts index 66fe0e0f7..9ebdd36f0 100644 --- a/packages/twenty-front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts +++ b/packages/twenty-front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts @@ -2,7 +2,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata' import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; import { moveArrayItem } from '~/utils/array/moveArrayItem'; -import { assertNotNull } from '~/utils/assert'; +import { isNonNullable } from '~/utils/isNonNullable'; import { ViewField } from '../types/ViewField'; @@ -48,7 +48,7 @@ export const mapViewFieldsToColumnDefinitions = ({ viewFieldId: viewField.id, }; }) - .filter(assertNotNull); + .filter(isNonNullable); // No label identifier set for this object if (!labelIdentifierFieldMetadataId) return columnDefinitionsFromViewFields; diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index 44dfa369e..0e6e93c87 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -16,7 +16,7 @@ import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddB import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { isNonNullable } from '~/utils/isNonNullable'; export const RecordShowPage = () => { const { objectNameSingular, objectRecordId } = useParams<{ @@ -55,7 +55,7 @@ export const RecordShowPage = () => { (favorite) => favorite.recordId === objectRecordId, ); - const isFavorite = isDefined(correspondingFavorite); + const isFavorite = isNonNullable(correspondingFavorite); const handleFavoriteButtonClick = async () => { if (!objectNameSingular || !record) return; diff --git a/packages/twenty-front/src/testing/mock-data/index.ts b/packages/twenty-front/src/testing/mock-data/index.ts index a2099efa2..d6a930822 100644 --- a/packages/twenty-front/src/testing/mock-data/index.ts +++ b/packages/twenty-front/src/testing/mock-data/index.ts @@ -1,7 +1,7 @@ import { isObject, isString } from '@sniptt/guards'; import { GraphQLVariables } from 'msw'; -import { isDefined } from '../../utils/isDefined'; +import { isNonNullable } from '../../utils/isNonNullable'; type StringFilter = { equals?: string; @@ -133,7 +133,7 @@ export const fetchOneFromData = ( data: Array, id: string, ): DataT | undefined => { - if (!isDefined(id)) { + if (!isNonNullable(id)) { throw new Error( `id is not defined in updateOneFromData, check that you provided where.id if needed.`, ); @@ -147,7 +147,7 @@ export const updateOneFromData = ( id: string | undefined, payload: GraphQLVariables, ): DataT | undefined => { - if (!isDefined(id)) { + if (!isNonNullable(id)) { throw new Error( `id is not defined in updateOneFromData, check that you provided where.id if needed.`, ); diff --git a/packages/twenty-front/src/utils/__tests__/assert.test.ts b/packages/twenty-front/src/utils/__tests__/assert.test.ts deleted file mode 100644 index 1d6b51af0..000000000 --- a/packages/twenty-front/src/utils/__tests__/assert.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { assertNotNull } from '~/utils/assert'; - -describe('assert', () => { - it('should return true for a NonNullable value', () => { - expect(assertNotNull(1)).toBeTruthy(); - }); - - it('should return true for a NonNullable value', () => { - expect(assertNotNull('')).toBeTruthy(); - }); - - it('should return false for a null value', () => { - expect(assertNotNull(null)).toBeFalsy(); - }); - - it('should return false for an undefined value', () => { - expect(assertNotNull(undefined)).toBeFalsy(); - }); -}); diff --git a/packages/twenty-front/src/utils/__tests__/isDefined.test.ts b/packages/twenty-front/src/utils/__tests__/isDefined.test.ts deleted file mode 100644 index 4d8645ff0..000000000 --- a/packages/twenty-front/src/utils/__tests__/isDefined.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { isDefined } from '~/utils/isDefined'; - -describe('isDefined', () => { - it('should return true for a NonNullable value', () => { - expect(isDefined(1)).toBe(true); - }); - - it('should return true for a NonNullable value', () => { - expect(isDefined('')).toBe(true); - }); - - it('should return false for a null value', () => { - expect(isDefined(null)).toBe(false); - }); - - it('should return false for an undefined value', () => { - expect(isDefined(undefined)).toBe(false); - }); -}); diff --git a/packages/twenty-front/src/utils/__tests__/isNonNullable.test.ts b/packages/twenty-front/src/utils/__tests__/isNonNullable.test.ts new file mode 100644 index 000000000..9969b33be --- /dev/null +++ b/packages/twenty-front/src/utils/__tests__/isNonNullable.test.ts @@ -0,0 +1,15 @@ +import { isNonNullable } from '~/utils/isNonNullable'; + +describe('isNonNullable', () => { + it('returns true if value is not undefined nor null', () => { + expect(isNonNullable('')).toBe(true); + }); + + it('returns false if value is null', () => { + expect(isNonNullable(null)).toBe(false); + }); + + it('returns false if value is undefined', () => { + expect(isNonNullable(undefined)).toBe(false); + }); +}); diff --git a/packages/twenty-front/src/utils/__tests__/parseApolloStoreFieldName.test.ts b/packages/twenty-front/src/utils/__tests__/parseApolloStoreFieldName.test.ts new file mode 100644 index 000000000..dcb5acb9c --- /dev/null +++ b/packages/twenty-front/src/utils/__tests__/parseApolloStoreFieldName.test.ts @@ -0,0 +1,30 @@ +import { parseApolloStoreFieldName } from '../parseApolloStoreFieldName'; + +describe('parseApolloStoreFieldName', () => { + it('returns an empty object if string is not a valid store field name', () => { + const result = parseApolloStoreFieldName('////'); + expect(result).toEqual({}); + }); + + it('returns the field name and parsed variables if they exist', () => { + const result = parseApolloStoreFieldName('fieldName({"key":"value"})'); + expect(result).toEqual({ + fieldName: 'fieldName', + fieldVariables: { key: 'value' }, + }); + }); + + it('returns only the field name if the variables cannot be parsed', () => { + const result = parseApolloStoreFieldName('fieldName(notJson)'); + expect(result).toEqual({ + fieldName: 'fieldName', + }); + }); + + it('returns only the field name if there are no variables', () => { + const result = parseApolloStoreFieldName('fieldName'); + expect(result).toEqual({ + fieldName: 'fieldName', + }); + }); +}); diff --git a/packages/twenty-front/src/utils/__tests__/sort.test.ts b/packages/twenty-front/src/utils/__tests__/sort.test.ts new file mode 100644 index 000000000..771c6aad1 --- /dev/null +++ b/packages/twenty-front/src/utils/__tests__/sort.test.ts @@ -0,0 +1,35 @@ +import { sortAsc, sortDesc, sortNullsFirst, sortNullsLast } from '../sort'; + +describe('sort', () => { + describe('sortNullsFirst', () => { + it('should sort nulls first', () => { + expect(sortNullsFirst(null, 'a')).toBe(-1); + expect(sortNullsFirst('a', null)).toBe(1); + expect(sortNullsFirst('a', 'a')).toBe(0); + }); + }); + + describe('sortNullsLast', () => { + it('should sort nulls last', () => { + expect(sortNullsLast(null, 'a')).toBe(1); + expect(sortNullsLast('a', null)).toBe(-1); + expect(sortNullsLast('a', 'a')).toBe(0); + }); + }); + + describe('sortAsc', () => { + it('should sort in ascending order', () => { + expect(sortAsc('a', 'b')).toBe(-1); + expect(sortAsc('b', 'a')).toBe(1); + expect(sortAsc('a', 'a')).toBe(0); + }); + }); + + describe('sortDesc', () => { + it('should sort in descending order', () => { + expect(sortDesc('a', 'b')).toBe(1); + expect(sortDesc('b', 'a')).toBe(-1); + expect(sortDesc('a', 'a')).toBe(0); + }); + }); +}); diff --git a/packages/twenty-front/src/utils/array/__tests__/arrayToCunks.test.ts b/packages/twenty-front/src/utils/array/__tests__/arrayToChunks.test.ts similarity index 100% rename from packages/twenty-front/src/utils/array/__tests__/arrayToCunks.test.ts rename to packages/twenty-front/src/utils/array/__tests__/arrayToChunks.test.ts diff --git a/packages/twenty-front/src/utils/array/__tests__/groupArrayItemsBy.test.ts b/packages/twenty-front/src/utils/array/__tests__/groupArrayItemsBy.test.ts new file mode 100644 index 000000000..79aba40c7 --- /dev/null +++ b/packages/twenty-front/src/utils/array/__tests__/groupArrayItemsBy.test.ts @@ -0,0 +1,25 @@ +import { groupArrayItemsBy } from '../groupArrayItemsBy'; + +describe('groupArrayItemsBy', () => { + it('groups an array of objects by a computed key', () => { + // Given + const array = [ + { id: '1', type: 'fruit', value: 'apple' }, + { id: '2', type: 'fruit', value: 'banana' }, + { id: '3', type: 'vegetable', value: 'carrot' }, + ]; + const computeGroupKey = ({ type }: (typeof array)[0]) => type; + + // When + const result = groupArrayItemsBy(array, computeGroupKey); + + // Then + expect(result).toEqual({ + fruit: [ + { id: '1', type: 'fruit', value: 'apple' }, + { id: '2', type: 'fruit', value: 'banana' }, + ], + vegetable: [{ id: '3', type: 'vegetable', value: 'carrot' }], + }); + }); +}); diff --git a/packages/twenty-front/src/utils/array/__tests__/mapArrayToObject.test.ts b/packages/twenty-front/src/utils/array/__tests__/mapArrayToObject.test.ts new file mode 100644 index 000000000..13699e078 --- /dev/null +++ b/packages/twenty-front/src/utils/array/__tests__/mapArrayToObject.test.ts @@ -0,0 +1,23 @@ +import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; + +describe('mapArrayToObject', () => { + it('maps an array of objects to an object with computed keys', () => { + // Given + const array = [ + { id: '1', value: 'one' }, + { id: '2', value: 'two' }, + { id: '3', value: 'three' }, + ]; + const computeItemKey = ({ id }: { id: string }) => id; + + // When + const result = mapArrayToObject(array, computeItemKey); + + // Then + expect(result).toEqual({ + '1': { id: '1', value: 'one' }, + '2': { id: '2', value: 'two' }, + '3': { id: '3', value: 'three' }, + }); + }); +}); diff --git a/packages/twenty-front/src/utils/array/groupArrayItemsBy.ts b/packages/twenty-front/src/utils/array/groupArrayItemsBy.ts index 61ff135d3..37b1c9b70 100644 --- a/packages/twenty-front/src/utils/array/groupArrayItemsBy.ts +++ b/packages/twenty-front/src/utils/array/groupArrayItemsBy.ts @@ -1,8 +1,30 @@ -export const groupArrayItemsBy = ( - array: Item[], - computeGroupKey: (item: Item) => Key, +/** + * Groups an array of items by a key computed from each item. + * + * @param array - The array to group. + * @param computeGroupKey - A function that computes the group key to which the item belongs. + * + * @returns An object with items grouped by a computed key. + * + * @example + * groupArrayItemsBy( + * [{ id: '1', type: 'fruit' }, { id: '2', type: 'vegetable' }, { id: '3', type: 'fruit' }], + * ({ type }) => type, + * ) + * ⬇️ + * { + * fruit: [{ id: '1', type: 'fruit' }, { id: '3', type: 'fruit' }], + * vegetable: [{ id: '2', type: 'vegetable' }], + * } + */ +export const groupArrayItemsBy = < + ArrayItem extends Record, + Key extends string, +>( + array: ArrayItem[], + computeGroupKey: (item: ArrayItem) => Key, ) => - array.reduce>>((result, item) => { + array.reduce>>((result, item) => { const groupKey = computeGroupKey(item); const previousGroup = result[groupKey] || []; diff --git a/packages/twenty-front/src/utils/array/mapArrayToObject.ts b/packages/twenty-front/src/utils/array/mapArrayToObject.ts index 816ee7dc3..2d331f178 100644 --- a/packages/twenty-front/src/utils/array/mapArrayToObject.ts +++ b/packages/twenty-front/src/utils/array/mapArrayToObject.ts @@ -1,4 +1,27 @@ -export const mapArrayToObject = ( +/** + * Transforms an array of items into an object where the keys are computed from each item. + * + * @param array - The array to transform. + * @param computeItemKey - A function that computes a key from an item. + * + * @returns An object where the keys are computed from the items in the array. + * + * @example + * mapArrayToObject( + * [{ id: '1', type: 'fruit' }, { id: '2', type: 'vegetable' }, { id: '3', type: 'fruit' }], + * ({ id }) => id, + * ) + * ⬇️ + * { + * '1': { id: '1', type: 'fruit' }, + * '2': { id: '2', type: 'vegetable' }, + * '3': { id: '3', type: 'fruit' }, + * } + */ +export const mapArrayToObject = ( array: ArrayItem[], - computeItemKey: (item: ArrayItem) => string, -) => Object.fromEntries(array.map((item) => [computeItemKey(item), item])); + computeItemKey: (item: ArrayItem) => Key, +) => + Object.fromEntries( + array.map((item) => [computeItemKey(item), item]), + ) as Record; diff --git a/packages/twenty-front/src/utils/array/moveArrayItem.ts b/packages/twenty-front/src/utils/array/moveArrayItem.ts index 1f4aa7127..92cd2ed2b 100644 --- a/packages/twenty-front/src/utils/array/moveArrayItem.ts +++ b/packages/twenty-front/src/utils/array/moveArrayItem.ts @@ -1,5 +1,19 @@ -export const moveArrayItem = ( - array: Item[], +/** + * Moves an item in an array from one index to another. + * + * @param array - The array to move an item in. + * @param indices - The indices to move the item from and to. + * @param indices.fromIndex - The index to move the item from. + * @param indices.toIndex - The index to move the item to. + * + * @returns A new array with the item moved to the new index. + * + * @example + * moveArrayItem(['a', 'b', 'c'], { fromIndex: 0, toIndex: 2 }) + * => ['b', 'c', 'a'] + */ +export const moveArrayItem = ( + array: ArrayItem[], { fromIndex, toIndex }: { fromIndex: number; toIndex: number }, ) => { if (!(fromIndex in array) || !(toIndex in array) || fromIndex === toIndex) { diff --git a/packages/twenty-front/src/utils/assert.ts b/packages/twenty-front/src/utils/assert.ts deleted file mode 100644 index 5e6c5feca..000000000 --- a/packages/twenty-front/src/utils/assert.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const assertNotNull = (item: T): item is NonNullable => - item !== null && item !== undefined; diff --git a/packages/twenty-front/src/utils/is-domain.ts b/packages/twenty-front/src/utils/is-domain.ts index 7db972074..aaec62034 100644 --- a/packages/twenty-front/src/utils/is-domain.ts +++ b/packages/twenty-front/src/utils/is-domain.ts @@ -1,7 +1,7 @@ -import { isDefined } from './isDefined'; +import { isNonNullable } from './isNonNullable'; export const isDomain = (url: string | undefined | null) => - isDefined(url) && + isNonNullable(url) && /^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$/.test( url, ); diff --git a/packages/twenty-front/src/utils/is-url.ts b/packages/twenty-front/src/utils/is-url.ts index bb6e8f7ee..3572451c2 100644 --- a/packages/twenty-front/src/utils/is-url.ts +++ b/packages/twenty-front/src/utils/is-url.ts @@ -1,7 +1,7 @@ -import { isDefined } from './isDefined'; +import { isNonNullable } from './isNonNullable'; export const isURL = (url: string | undefined | null) => - isDefined(url) && + isNonNullable(url) && url.match( /^(https?:\/\/)?(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/i, ); diff --git a/packages/twenty-front/src/utils/isDefined.ts b/packages/twenty-front/src/utils/isDefined.ts deleted file mode 100644 index aad8908b6..000000000 --- a/packages/twenty-front/src/utils/isDefined.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isDefined = ( - value: T | undefined | null, -): value is NonNullable => value !== undefined && value !== null; diff --git a/packages/twenty-front/src/utils/isNonNullable.ts b/packages/twenty-front/src/utils/isNonNullable.ts new file mode 100644 index 000000000..6958554d0 --- /dev/null +++ b/packages/twenty-front/src/utils/isNonNullable.ts @@ -0,0 +1,4 @@ +import { isNull, isUndefined } from '@sniptt/guards'; + +export const isNonNullable = (value: T): value is NonNullable => + !isUndefined(value) && !isNull(value); diff --git a/packages/twenty-front/src/utils/parseApolloStoreFieldName.ts b/packages/twenty-front/src/utils/parseApolloStoreFieldName.ts index cb25568e8..ea7776cf1 100644 --- a/packages/twenty-front/src/utils/parseApolloStoreFieldName.ts +++ b/packages/twenty-front/src/utils/parseApolloStoreFieldName.ts @@ -8,19 +8,22 @@ export const parseApolloStoreFieldName = < >( storeFieldName: string, ) => { - const matches = storeFieldName.match(/([a-zA-Z][a-zA-Z0-9 ]*)\((.*)\)/); + const matches = storeFieldName.match(/([a-zA-Z][a-zA-Z0-9 ]*)(\((.*)\))?/); - if (!matches?.[1]) return {}; + const fieldName = matches?.[1]; - const [, , stringifiedVariables] = matches; - const fieldName = matches[1] as string; + if (!fieldName) { + return {}; + } + + const stringifiedVariables = matches[3]; try { - const fieldArguments = stringifiedVariables + const fieldVariables = stringifiedVariables ? (JSON.parse(stringifiedVariables) as Variables) : undefined; - return { fieldName, fieldArguments }; + return { fieldName, fieldVariables }; } catch { return { fieldName }; } diff --git a/packages/twenty-front/src/utils/sort.ts b/packages/twenty-front/src/utils/sort.ts index 0eec8861a..8680cac16 100644 --- a/packages/twenty-front/src/utils/sort.ts +++ b/packages/twenty-front/src/utils/sort.ts @@ -13,7 +13,7 @@ export const sortNullsLast = ( export const sortAsc = ( fieldValueA: string | number, fieldValueB: string | number, -) => (fieldValueA < fieldValueB ? -1 : 1); +) => (fieldValueA === fieldValueB ? 0 : fieldValueA < fieldValueB ? -1 : 1); export const sortDesc = ( fieldValueA: string | number,