## Query depth deprecation

I'm deprecating depth parameter in our graphql query / cache tooling.
They were obsolete since we introduce the possibility to provide
RecordGqlFields

## Refactor combinedFindManyRecordHook

The hook can now take an array of operationSignatures

## Fix tasks issues

Fix optimistic rendering issue. Note that we still haven't handle
optimisticEffect on creation properly
This commit is contained in:
Charles Bochet
2024-04-29 23:33:23 +02:00
committed by GitHub
parent c946572fde
commit 6a14b1c6d6
187 changed files with 958 additions and 1482 deletions

View File

@ -1,22 +1,29 @@
import { ReactNode } from 'react';
import { expect } from '@storybook/test';
import { renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter';
const Wrapper = ({ children }: { children: ReactNode }) => (
<RecoilRoot>{children}</RecoilRoot>
<RecoilRoot>
<JestObjectMetadataItemSetter>{children}</JestObjectMetadataItemSetter>
</RecoilRoot>
);
describe('useGenerateFindManyRecordsForMultipleMetadataItemsQuery', () => {
it('should work as expected', async () => {
const { result } = renderHook(
() => {
const mockObjectMetadataItems = getObjectMetadataItemsMock();
return useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
targetObjectMetadataItems: mockObjectMetadataItems.slice(0, 2),
return useGenerateCombinedFindManyRecordsQuery({
operationSignatures: getObjectMetadataItemsMock()
.slice(0, 2)
.map((item) => ({
objectNameSingular: item.nameSingular,
variables: {},
})),
});
},
{

View File

@ -2,10 +2,12 @@ import { useApolloClient } from '@apollo/client';
import { v4 } from 'uuid';
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { useCreateOneRecordInCache } from '@/object-record/cache/hooks/useCreateOneRecordInCache';
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useCreateManyRecordsMutation } from '@/object-record/hooks/useCreateManyRecordsMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getCreateManyRecordsMutationResponseField } from '@/object-record/utils/getCreateManyRecordsMutationResponseField';
@ -14,8 +16,7 @@ import { isDefined } from '~/utils/isDefined';
type useCreateManyRecordsProps = {
objectNameSingular: string;
queryFields?: Record<string, any>;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
skipPostOptmisticEffect?: boolean;
};
@ -23,8 +24,7 @@ export const useCreateManyRecords = <
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
>({
objectNameSingular,
queryFields,
depth = 1,
recordGqlFields,
skipPostOptmisticEffect = false,
}: useCreateManyRecordsProps) => {
const apolloClient = useApolloClient();
@ -33,13 +33,15 @@ export const useCreateManyRecords = <
objectNameSingular,
});
const computedRecordGqlFields =
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
const { createManyRecordsMutation } = useCreateManyRecordsMutation({
objectNameSingular,
queryFields,
depth,
recordGqlFields: computedRecordGqlFields,
});
const createOneRecordInCache = useCreateOneRecordInCache<CachedObjectRecord>({
const createOneRecordInCache = useCreateOneRecordInCache<ObjectRecord>({
objectMetadataItem,
});
@ -65,7 +67,10 @@ export const useCreateManyRecords = <
const recordsCreatedInCache = [];
for (const recordToCreate of sanitizedCreateManyRecordsInput) {
const recordCreatedInCache = createOneRecordInCache(recordToCreate);
const recordCreatedInCache = createOneRecordInCache({
...recordToCreate,
__typename: getObjectTypename(objectMetadataItem.nameSingular),
});
if (isDefined(recordCreatedInCache)) {
recordsCreatedInCache.push(recordCreatedInCache);

View File

@ -5,18 +5,17 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { getCreateManyRecordsMutationResponseField } from '@/object-record/utils/getCreateManyRecordsMutationResponseField';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { capitalize } from '~/utils/string/capitalize';
export const useCreateManyRecordsMutation = ({
objectNameSingular,
queryFields,
depth,
recordGqlFields,
}: {
objectNameSingular: string;
queryFields?: Record<string, any>;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -39,8 +38,7 @@ export const useCreateManyRecordsMutation = ({
${mutationResponseField}(data: $data) ${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItem,
queryFields,
depth,
recordGqlFields,
})}
}`;

View File

@ -2,10 +2,12 @@ import { useApolloClient } from '@apollo/client';
import { v4 } from 'uuid';
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { useCreateOneRecordInCache } from '@/object-record/cache/hooks/useCreateOneRecordInCache';
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useCreateOneRecordMutation } from '@/object-record/hooks/useCreateOneRecordMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getCreateOneRecordMutationResponseField } from '@/object-record/utils/getCreateOneRecordMutationResponseField';
@ -14,8 +16,7 @@ import { isDefined } from '~/utils/isDefined';
type useCreateOneRecordProps = {
objectNameSingular: string;
queryFields?: Record<string, any>;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
skipPostOptmisticEffect?: boolean;
};
@ -23,7 +24,7 @@ export const useCreateOneRecord = <
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
>({
objectNameSingular,
queryFields,
recordGqlFields,
skipPostOptmisticEffect = false,
}: useCreateOneRecordProps) => {
const apolloClient = useApolloClient();
@ -32,14 +33,19 @@ export const useCreateOneRecord = <
objectNameSingular,
});
const computedRecordGqlFields =
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
const { createOneRecordMutation } = useCreateOneRecordMutation({
objectNameSingular,
queryFields,
recordGqlFields: computedRecordGqlFields,
});
const createOneRecordInCache = useCreateOneRecordInCache<CachedObjectRecord>({
objectMetadataItem,
});
const createOneRecordInCache = useCreateOneRecordInCache<CreatedObjectRecord>(
{
objectMetadataItem,
},
);
const { objectMetadataItems } = useObjectMetadataItems();
@ -57,6 +63,7 @@ export const useCreateOneRecord = <
const recordCreatedInCache = createOneRecordInCache({
...input,
id: idForCreation,
__typename: getObjectTypename(objectMetadataItem.nameSingular),
});
if (isDefined(recordCreatedInCache)) {

View File

@ -5,23 +5,29 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { getCreateOneRecordMutationResponseField } from '@/object-record/utils/getCreateOneRecordMutationResponseField';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { capitalize } from '~/utils/string/capitalize';
export const useCreateOneRecordMutation = ({
objectNameSingular,
queryFields,
depth,
recordGqlFields,
}: {
objectNameSingular: string;
queryFields?: Record<string, any>;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
const appliedRecordGqlFields =
recordGqlFields ??
generateDepthOneRecordGqlFields({
objectMetadataItem,
});
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
if (isUndefinedOrNull(objectMetadataItem)) {
@ -39,8 +45,7 @@ export const useCreateOneRecordMutation = ({
${mutationResponseField}(data: $input) ${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItem,
queryFields,
depth,
recordGqlFields: appliedRecordGqlFields,
})}
}
`;

View File

@ -4,25 +4,22 @@ import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
import { useFindDuplicateRecordsQuery } from '@/object-record/hooks/useFindDuplicatesRecordsQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
import { getFindDuplicateRecordsQueryResponseField } from '@/object-record/utils/getFindDuplicateRecordsQueryResponseField';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { logError } from '~/utils/logError';
import { ObjectRecordQueryResult } from '../types/ObjectRecordQueryResult';
export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
objectRecordId = '',
objectNameSingular,
onCompleted,
depth,
}: ObjectMetadataItemIdentifier & {
objectRecordId: string | undefined;
onCompleted?: (data: ObjectRecordConnection<T>) => void;
onCompleted?: (data: RecordGqlConnection) => void;
skip?: boolean;
depth?: number;
}) => {
const findDuplicateQueryStateIdentifier = objectNameSingular;
@ -32,7 +29,6 @@ export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
const { findDuplicateRecordsQuery } = useFindDuplicateRecordsQuery({
objectNameSingular,
depth,
});
const { enqueueSnackBar } = useSnackBar();
@ -41,7 +37,7 @@ export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
objectMetadataItem.nameSingular,
);
const { data, loading, error } = useQuery<ObjectRecordQueryResult<T>>(
const { data, loading, error } = useQuery<RecordGqlOperationFindManyResult>(
findDuplicateRecordsQuery,
{
variables: {

View File

@ -9,10 +9,8 @@ import { capitalize } from '~/utils/string/capitalize';
export const useFindDuplicateRecordsQuery = ({
objectNameSingular,
depth,
}: {
objectNameSingular: string;
depth?: number;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -31,7 +29,6 @@ export const useFindDuplicateRecordsQuery = ({
node ${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItem,
depth,
})}
cursor
}

View File

@ -8,11 +8,13 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMembe
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { isDefined } from '~/utils/isDefined';
@ -22,7 +24,6 @@ import { capitalize } from '~/utils/string/capitalize';
import { cursorFamilyState } from '../states/cursorFamilyState';
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
import { isFetchingMoreRecordsFamilyState } from '../states/isFetchingMoreRecordsFamilyState';
import { ObjectRecordQueryResult } from '../types/ObjectRecordQueryResult';
export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
objectNameSingular,
@ -31,20 +32,19 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
limit,
onCompleted,
skip,
queryFields,
recordGqlFields,
fetchPolicy,
}: ObjectMetadataItemIdentifier &
ObjectRecordQueryVariables & {
RecordGqlOperationVariables & {
onCompleted?: (
records: T[],
options?: {
pageInfo?: ObjectRecordConnection['pageInfo'];
pageInfo?: RecordGqlConnection['pageInfo'];
totalCount?: number;
},
) => void;
skip?: boolean;
depth?: number;
queryFields?: Record<string, any>;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
fetchPolicy?: WatchQueryFetchPolicy;
}) => {
const findManyQueryStateIdentifier =
@ -71,56 +71,55 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
const { findManyRecordsQuery } = useFindManyRecordsQuery({
objectNameSingular,
queryFields,
recordGqlFields,
});
const { enqueueSnackBar } = useSnackBar();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { data, loading, error, fetchMore } = useQuery<
ObjectRecordQueryResult<T>
>(findManyRecordsQuery, {
skip: skip || !objectMetadataItem || !currentWorkspaceMember,
variables: {
filter,
limit,
orderBy,
},
fetchPolicy: fetchPolicy,
onCompleted: (data) => {
if (!isDefined(data)) {
onCompleted?.([]);
}
const { data, loading, error, fetchMore } =
useQuery<RecordGqlOperationFindManyResult>(findManyRecordsQuery, {
skip: skip || !objectMetadataItem || !currentWorkspaceMember,
variables: {
filter,
limit,
orderBy,
},
fetchPolicy: fetchPolicy,
onCompleted: (data) => {
if (!isDefined(data)) {
onCompleted?.([]);
}
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
const records = getRecordsFromRecordConnection({
recordConnection: data?.[objectMetadataItem.namePlural],
}) as T[];
const records = getRecordsFromRecordConnection({
recordConnection: data?.[objectMetadataItem.namePlural],
}) as T[];
onCompleted?.(records, {
pageInfo,
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
});
onCompleted?.(records, {
pageInfo,
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
});
if (isDefined(data?.[objectMetadataItem.namePlural])) {
setLastCursor(pageInfo.endCursor ?? '');
setHasNextPage(pageInfo.hasNextPage ?? false);
}
},
onError: (error) => {
logError(
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
error,
);
enqueueSnackBar(
`Error during useFindManyRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
{
variant: 'error',
},
);
},
});
if (isDefined(data?.[objectMetadataItem.namePlural])) {
setLastCursor(pageInfo.endCursor ?? '');
setHasNextPage(pageInfo.hasNextPage ?? false);
}
},
onError: (error) => {
logError(
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
error,
);
enqueueSnackBar(
`Error during useFindManyRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
{
variant: 'error',
},
);
},
});
const fetchMoreRecords = useCallback(async () => {
if (hasNextPage) {
@ -138,7 +137,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
const nextEdges =
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
let newEdges: ObjectRecordEdge<T>[] = [];
let newEdges: RecordGqlEdge[] = [];
if (isNonEmptyArray(previousEdges) && isNonEmptyArray(nextEdges)) {
newEdges = filterUniqueRecordEdgesByCursor([
@ -180,7 +179,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural].totalCount,
},
} as ObjectRecordQueryResult<T>);
} as RecordGqlOperationFindManyResult);
},
});
} catch (error) {
@ -219,7 +218,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
const records = useMemo(
() =>
data?.[objectMetadataItem.namePlural]
? getRecordsFromRecordConnection({
? getRecordsFromRecordConnection<T>({
recordConnection: data?.[objectMetadataItem.namePlural],
})
: ([] as T[]),

View File

@ -2,18 +2,16 @@ import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { QueryFields } from '@/object-record/query-keys/types/QueryFields';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
export const useFindManyRecordsQuery = ({
objectNameSingular,
queryFields,
depth,
recordGqlFields,
computeReferences,
}: {
objectNameSingular: string;
queryFields?: QueryFields;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
computeReferences?: boolean;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
@ -25,8 +23,7 @@ export const useFindManyRecordsQuery = ({
const findManyRecordsQuery = generateFindManyRecordsQuery({
objectMetadataItem,
objectMetadataItems,
queryFields,
depth,
recordGqlFields,
computeReferences,
});

View File

@ -4,6 +4,9 @@ import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { isDefined } from '~/utils/isDefined';
@ -11,32 +14,34 @@ import { isDefined } from '~/utils/isDefined';
export const useFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
objectNameSingular,
objectRecordId = '',
recordGqlFields,
onCompleted,
skip,
depth,
}: ObjectMetadataItemIdentifier & {
objectRecordId: string | undefined;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
onCompleted?: (data: T) => void;
skip?: boolean;
depth?: number;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
const computedRecordGqlFields =
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
const { findOneRecordQuery } = useFindOneRecordQuery({
objectNameSingular,
depth,
recordGqlFields: computedRecordGqlFields,
});
const { data, loading, error } = useQuery<
{ [nameSingular: string]: T },
{ objectRecordId: string }
>(findOneRecordQuery, {
const { data, loading, error } = useQuery<{
[nameSingular: string]: RecordGqlNode;
}>(findOneRecordQuery, {
skip: !objectMetadataItem || !objectRecordId || skip,
variables: { objectRecordId },
onCompleted: (data) => {
const recordWithoutConnection = getRecordFromRecordNode({
const recordWithoutConnection = getRecordFromRecordNode<T>({
recordNode: { ...data[objectNameSingular] },
});
@ -50,7 +55,7 @@ export const useFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
const recordWithoutConnection = useMemo(
() =>
data?.[objectNameSingular]
? getRecordFromRecordNode({
? getRecordFromRecordNode<T>({
recordNode: data?.[objectNameSingular],
})
: undefined,

View File

@ -4,14 +4,15 @@ import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { capitalize } from '~/utils/string/capitalize';
export const useFindOneRecordQuery = ({
objectNameSingular,
depth,
recordGqlFields,
}: {
objectNameSingular: string;
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -30,7 +31,7 @@ export const useFindOneRecordQuery = ({
})${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
objectMetadataItem,
depth,
recordGqlFields,
})}
},
`;

View File

@ -1,12 +1,15 @@
import { useLazyQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
type UseLazyFindOneRecordParams = ObjectMetadataItemIdentifier & {
depth?: number;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
};
type FindOneRecordParams<T extends ObjectRecord> = {
@ -16,11 +19,17 @@ type FindOneRecordParams<T extends ObjectRecord> = {
export const useLazyFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
objectNameSingular,
depth,
recordGqlFields,
}: UseLazyFindOneRecordParams) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
const { findOneRecordQuery } = useFindOneRecordQuery({
objectNameSingular,
depth,
recordGqlFields:
recordGqlFields ??
generateDepthOneRecordGqlFields({ objectMetadataItem }),
});
const [findOneRecord, { loading, error, data, called }] =

View File

@ -6,23 +6,23 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
import { updateRecordFromCache } from '@/object-record/cache/utils/updateRecordFromCache';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { useUpdateOneRecordMutation } from '@/object-record/hooks/useUpdateOneRecordMutation';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
import { sanitizeRecordInput } from '@/object-record/utils/sanitizeRecordInput';
import { capitalize } from '~/utils/string/capitalize';
type useUpdateOneRecordProps = {
objectNameSingular: string;
queryFields?: Record<string, any>;
depth?: number;
recordGqlFields?: Record<string, any>;
};
export const useUpdateOneRecord = <
UpdatedObjectRecord extends ObjectRecord = ObjectRecord,
>({
objectNameSingular,
queryFields,
depth = 1,
recordGqlFields,
}: useUpdateOneRecordProps) => {
const apolloClient = useApolloClient();
@ -30,12 +30,16 @@ export const useUpdateOneRecord = <
objectNameSingular,
});
const computedRecordGqlFields =
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
const getRecordFromCache = useGetRecordFromCache({
objectNameSingular,
});
const { updateOneRecordMutation } = useUpdateOneRecordMutation({
objectNameSingular,
recordGqlFields: computedRecordGqlFields,
});
const { objectMetadataItems } = useObjectMetadataItems();
@ -54,14 +58,13 @@ export const useUpdateOneRecord = <
}),
};
const cachedRecord = getRecordFromCache<UpdatedObjectRecord>(idToUpdate);
const cachedRecord = getRecordFromCache<ObjectRecord>(idToUpdate);
const cachedRecordWithConnection = getRecordNodeFromRecord<ObjectRecord>({
record: cachedRecord,
objectMetadataItem,
objectMetadataItems,
depth,
queryFields,
recordGqlFields: computedRecordGqlFields,
computeReferences: true,
});
@ -69,6 +72,7 @@ export const useUpdateOneRecord = <
...cachedRecord,
...sanitizedInput,
...{ id: idToUpdate },
...{ __typename: capitalize(objectMetadataItem.nameSingular) },
};
const optimisticRecordWithConnection =
@ -76,8 +80,7 @@ export const useUpdateOneRecord = <
record: optimisticRecord,
objectMetadataItem,
objectMetadataItems,
depth,
queryFields,
recordGqlFields: computedRecordGqlFields,
computeReferences: true,
});

View File

@ -5,18 +5,20 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { capitalize } from '~/utils/string/capitalize';
export const useUpdateOneRecordMutation = ({
objectNameSingular,
recordGqlFields,
computeReferences = false,
depth,
}: {
objectNameSingular: string;
recordGqlFields?: RecordGqlOperationGqlRecordFields;
computeReferences?: boolean;
depth?: number;
}) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@ -28,6 +30,12 @@ export const useUpdateOneRecordMutation = ({
return { updateOneRecordMutation: EMPTY_MUTATION };
}
const appliedRecordGqlFields =
recordGqlFields ??
generateDepthOneRecordGqlFields({
objectMetadataItem,
});
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
const mutationResponseField = getUpdateOneRecordMutationResponseField(
@ -40,8 +48,8 @@ export const useUpdateOneRecordMutation = ({
{
objectMetadataItems,
objectMetadataItem,
depth,
computeReferences,
recordGqlFields: appliedRecordGqlFields,
},
)}
}

View File

@ -1,13 +1,14 @@
import { useRecoilCallback } from 'recoil';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
// TODO: refactor with scoped state later
export const useUpsertRecordFromState = () =>
useRecoilCallback(
({ set }) =>
<T extends { id: string }>(record: T) =>
<T extends ObjectRecord>(record: T) =>
set(recordStoreFamilyState(record.id), (previousRecord) =>
isDeeplyEqual(previousRecord, record) ? previousRecord : record,
),