From 0fe7b318f86d2a84164c7c7c3a5abdfe9f542c79 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 7 Apr 2026 17:34:32 +0200 Subject: [PATCH 1/4] ref(tsc): move automations to apiOptions --- static/app/views/automations/hooks/index.tsx | 137 ++++++------------ static/app/views/automations/list.tsx | 36 ++--- .../components/connectAutomationsDrawer.tsx | 42 +++--- .../components/connectedAutomationList.tsx | 33 ++--- .../components/details/common/automations.tsx | 41 +++--- .../detectorListConnectedAutomations.tsx | 11 +- 6 files changed, 121 insertions(+), 179 deletions(-) diff --git a/static/app/views/automations/hooks/index.tsx b/static/app/views/automations/hooks/index.tsx index 6b93a4ee4037fc..ee44fbc23d617d 100644 --- a/static/app/views/automations/hooks/index.tsx +++ b/static/app/views/automations/hooks/index.tsx @@ -1,5 +1,8 @@ +import {queryOptions} from '@tanstack/react-query'; + import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {t, tn} from 'sentry/locale'; +import type {Organization} from 'sentry/types/organization'; import type {Action, ActionHandler} from 'sentry/types/workflowEngine/actions'; import type { Automation, @@ -10,6 +13,7 @@ import type { DataConditionHandler, DataConditionHandlerGroupType, } from 'sentry/types/workflowEngine/dataConditions'; +import {apiOptions} from 'sentry/utils/api/apiOptions'; import {getApiUrl} from 'sentry/utils/api/getApiUrl'; import type { ApiQueryKey, @@ -26,43 +30,41 @@ import type {RequestError} from 'sentry/utils/requestError/requestError'; import {useApi} from 'sentry/utils/useApi'; import {useOrganization} from 'sentry/utils/useOrganization'; -export const makeAutomationsQueryKey = ({ - orgSlug, - query, - sortBy, - priorityDetector, - ids, - limit, - cursor, - projects, - detector, -}: { - orgSlug: string; - cursor?: string; - detector?: string[]; - ids?: string[]; - limit?: number; - priorityDetector?: string; - projects?: number[]; - query?: string; - sortBy?: string; -}): ApiQueryKey => [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: orgSlug}, - }), - { - query: { +export const automationsApiOptions = ( + organization: Organization, + options?: { + cursor?: string; + detector?: string[]; + ids?: string[]; + limit?: number; + priorityDetector?: string; + projects?: number[]; + query?: string; + sortBy?: string; + } +) => { + const query = options + ? { + query: options.query, + sortBy: options.sortBy, + priorityDetector: options.priorityDetector, + id: options.ids, + per_page: options.limit, + cursor: options.cursor, + project: options.projects, + detector: options.detector, + } + : undefined; + + return queryOptions({ + ...apiOptions.as()('/organizations/$organizationIdOrSlug/workflows/', { + path: {organizationIdOrSlug: organization.slug}, query, - sortBy, - priorityDetector, - id: ids, - per_page: limit, - cursor, - project: projects, - detector, - }, - }, -]; + staleTime: 0, + }), + retry: false, + }); +}; const makeAutomationQueryKey = (orgSlug: string, automationId: string): ApiQueryKey => [ getApiUrl('/organizations/$organizationIdOrSlug/workflows/$workflowId/', { @@ -70,29 +72,6 @@ const makeAutomationQueryKey = (orgSlug: string, automationId: string): ApiQuery }), ]; -interface UseAutomationsQueryOptions { - cursor?: string; - detector?: string[]; - ids?: string[]; - limit?: number; - priorityDetector?: string; - projects?: number[]; - query?: string; - sortBy?: string; -} -export function useAutomationsQuery( - options: UseAutomationsQueryOptions = {}, - queryOptions: Partial> = {} -) { - const {slug: orgSlug} = useOrganization(); - - return useApiQuery(makeAutomationsQueryKey({orgSlug, ...options}), { - staleTime: 0, - retry: false, - ...queryOptions, - }); -} - export function useAutomationQuery(automationId: string) { const {slug} = useOrganization(); @@ -129,7 +108,7 @@ interface UseAutomationFireHistoryQueryOptions { } export function useAutomationFireHistoryQuery( options: UseAutomationFireHistoryQueryOptions, - queryOptions: Partial> = {} + useApiQueryOptions: Partial> = {} ) { const {slug} = useOrganization(); @@ -138,7 +117,7 @@ export function useAutomationFireHistoryQuery( { staleTime: 5 * 60 * 1000, // 5 minutes retry: false, - ...queryOptions, + ...useApiQueryOptions, } ); } @@ -194,11 +173,7 @@ export function useCreateAutomation() { ), onSuccess: _ => { queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); }, onError: _ => { @@ -224,11 +199,7 @@ export function useDeleteAutomationMutation() { ), onSuccess: () => { queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); addSuccessMessage(t('Alert deleted')); }, @@ -266,11 +237,7 @@ export function useDeleteAutomationsMutation() { }, onSuccess: () => { queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); addSuccessMessage(t('Alerts deleted')); }, @@ -313,11 +280,7 @@ export function useUpdateAutomation() { ); // Invalidate list query queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); }, onError: _ => { @@ -355,11 +318,7 @@ export function useUpdateAutomationsMutation() { }, onSuccess: (_, variables) => { queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); addSuccessMessage(variables.enabled ? t('Alerts enabled') : t('Alerts disabled')); }, @@ -396,11 +355,7 @@ export function useSendTestNotification( ...options, onSuccess: (data, variables, onMutateResult, context) => { queryClient.invalidateQueries({ - queryKey: [ - getApiUrl('/organizations/$organizationIdOrSlug/workflows/', { - path: {organizationIdOrSlug: org.slug}, - }), - ], + queryKey: automationsApiOptions(org).queryKey, }); addSuccessMessage( tn('Notification fired!', 'Notifications sent!', variables.length) diff --git a/static/app/views/automations/list.tsx b/static/app/views/automations/list.tsx index 7f9554dfda4e0e..70879cc03b53d5 100644 --- a/static/app/views/automations/list.tsx +++ b/static/app/views/automations/list.tsx @@ -1,4 +1,5 @@ import {useCallback} from 'react'; +import {useQuery} from '@tanstack/react-query'; import {LinkButton} from '@sentry/scraps/button'; import {Flex} from '@sentry/scraps/layout'; @@ -10,6 +11,7 @@ import {SentryDocumentTitle} from 'sentry/components/sentryDocumentTitle'; import {WorkflowEngineListLayout as ListLayout} from 'sentry/components/workflowEngine/layout/list'; import {IconAdd} from 'sentry/icons'; import {t} from 'sentry/locale'; +import {selectJsonWithHeaders} from 'sentry/utils/api/apiOptions'; import {parseLinkHeader} from 'sentry/utils/parseLinkHeader'; import {VisuallyCompleteWithData} from 'sentry/utils/performanceForSentry'; import {decodeScalar, decodeSorts} from 'sentry/utils/queryString'; @@ -21,11 +23,12 @@ import {AutomationFeedbackButton} from 'sentry/views/automations/components/auto import {AutomationListTable} from 'sentry/views/automations/components/automationListTable'; import {AutomationSearch} from 'sentry/views/automations/components/automationListTable/search'; import {AUTOMATION_LIST_PAGE_LIMIT} from 'sentry/views/automations/constants'; -import {useAutomationsQuery} from 'sentry/views/automations/hooks'; +import {automationsApiOptions} from 'sentry/views/automations/hooks'; import {makeAutomationCreatePathname} from 'sentry/views/automations/pathnames'; import {AlertsRedirectNotice} from 'sentry/views/detectors/list/common/alertsRedirectNotice'; export default function AutomationsList() { + const organization = useOrganization(); const location = useLocation(); const navigate = useNavigate(); const {selection, isReady} = usePageFilters(); @@ -43,30 +46,23 @@ export default function AutomationsList() { }); const sort = sorts[0] ?? {kind: 'desc', field: 'lastTriggered'}; - const { - data: automations, - isLoading, - isError, - isSuccess, - getResponseHeader, - } = useAutomationsQuery( - { - cursor, + const {data, isLoading, isError, isSuccess} = useQuery({ + ...automationsApiOptions(organization, { query, sortBy: sort ? `${sort?.kind === 'asc' ? '' : '-'}${sort?.field}` : undefined, projects: selection.projects, limit: AUTOMATION_LIST_PAGE_LIMIT, - }, - {enabled: isReady} - ); + cursor, + }), + select: selectJsonWithHeaders, + enabled: isReady, + }); - const hits = getResponseHeader?.('X-Hits') || ''; - const hitsInt = hits ? parseInt(hits, 10) || 0 : 0; + const automations = data?.json; + const hits = data?.headers['X-Hits'] ?? 0; // If maxHits is not set, we assume there is no max - const maxHits = getResponseHeader?.('X-Max-Hits') || ''; - const maxHitsInt = maxHits ? parseInt(maxHits, 10) || Infinity : Infinity; - - const pageLinks = getResponseHeader?.('Link'); + const maxHits = data?.headers['X-Max-Hits'] ?? Infinity; + const pageLinks = data?.headers.Link; const allResultsVisible = useCallback(() => { if (!pageLinks) { @@ -102,7 +98,7 @@ export default function AutomationsList() { isError={isError} isSuccess={isSuccess} sort={sort} - queryCount={hitsInt > maxHitsInt ? `${maxHits}+` : hits} + queryCount={hits > maxHits ? `${maxHits}+` : `${hits}`} allResultsVisible={allResultsVisible()} /> diff --git a/static/app/views/detectors/components/connectAutomationsDrawer.tsx b/static/app/views/detectors/components/connectAutomationsDrawer.tsx index ec23423099bb16..6996a021d5d654 100644 --- a/static/app/views/detectors/components/connectAutomationsDrawer.tsx +++ b/static/app/views/detectors/components/connectAutomationsDrawer.tsx @@ -5,10 +5,10 @@ import {DrawerHeader} from 'sentry/components/globalDrawer/components'; import {DetailSection} from 'sentry/components/workflowEngine/ui/detailSection'; import {t} from 'sentry/locale'; import type {Automation} from 'sentry/types/workflowEngine/automations'; -import {getApiQueryData, setApiQueryData, useQueryClient} from 'sentry/utils/queryClient'; +import {useQueryClient} from 'sentry/utils/queryClient'; import {useOrganization} from 'sentry/utils/useOrganization'; import {AutomationSearch} from 'sentry/views/automations/components/automationListTable/search'; -import {makeAutomationsQueryKey} from 'sentry/views/automations/hooks'; +import {automationsApiOptions} from 'sentry/views/automations/hooks'; import {ConnectedAutomationsList} from 'sentry/views/detectors/components/connectedAutomationList'; function ConnectedAutomations({ @@ -80,31 +80,27 @@ export function ConnectAutomationsDrawer({ const [localWorkflowIds, setLocalWorkflowIds] = useState(initialWorkflowIds); const toggleConnected = ({automation}: {automation: Automation}) => { - const oldAutomationsData = - getApiQueryData( - queryClient, - makeAutomationsQueryKey({ + const newAutomations = + queryClient.setQueryData( + automationsApiOptions({ orgSlug: organization.slug, ids: localWorkflowIds, - }) - ) ?? []; - - const newAutomations = ( - oldAutomationsData.some(a => a.id === automation.id) - ? oldAutomationsData.filter(a => a.id !== automation.id) - : [...oldAutomationsData, automation] - ).sort((a, b) => a.id.localeCompare(b.id)); + }).queryKey, + oldAutomations => { + if (!oldAutomations) { + return oldAutomations; + } + return { + ...oldAutomations, + json: (oldAutomations.json.some(a => a.id === automation.id) + ? oldAutomations.json.filter(a => a.id !== automation.id) + : [...oldAutomations.json, automation] + ).sort((a, b) => a.id.localeCompare(b.id)), + }; + } + )?.json ?? []; const newWorkflowIds = newAutomations.map(a => a.id); - setApiQueryData( - queryClient, - makeAutomationsQueryKey({ - orgSlug: organization.slug, - ids: newWorkflowIds, - }), - newAutomations - ); - setLocalWorkflowIds(newWorkflowIds); setWorkflowIds(newWorkflowIds); }; diff --git a/static/app/views/detectors/components/connectedAutomationList.tsx b/static/app/views/detectors/components/connectedAutomationList.tsx index ba20d4662bab7e..f5ec5b76e266cf 100644 --- a/static/app/views/detectors/components/connectedAutomationList.tsx +++ b/static/app/views/detectors/components/connectedAutomationList.tsx @@ -1,5 +1,6 @@ import {Fragment, useMemo} from 'react'; import styled from '@emotion/styled'; +import {useQuery} from '@tanstack/react-query'; import {Button} from '@sentry/scraps/button'; @@ -14,8 +15,10 @@ import {TimeAgoCell} from 'sentry/components/workflowEngine/gridCell/timeAgoCell import {t, tct} from 'sentry/locale'; import type {Automation} from 'sentry/types/workflowEngine/automations'; import type {Detector} from 'sentry/types/workflowEngine/detectors'; +import {selectJsonWithHeaders} from 'sentry/utils/api/apiOptions'; import {parseCursor} from 'sentry/utils/cursor'; -import {useAutomationsQuery} from 'sentry/views/automations/hooks'; +import {useOrganization} from 'sentry/utils/useOrganization'; +import {automationsApiOptions} from 'sentry/views/automations/hooks'; import {getAutomationActions} from 'sentry/views/automations/hooks/utils'; const DEFAULT_AUTOMATIONS_PER_PAGE = 10; @@ -72,29 +75,25 @@ export function ConnectedAutomationsList({ openInNewTab, ...props }: Props) { + const organization = useOrganization(); const canEdit = Boolean( connectedAutomationIds && typeof toggleConnected === 'function' ); - const { - data: automations, - isLoading, - isError, - isSuccess, - getResponseHeader, - } = useAutomationsQuery( - { + const {data, isLoading, isError, isSuccess} = useQuery({ + ...automationsApiOptions(organization, { ids: automationIds ?? undefined, limit: limit ?? undefined, cursor, query, - }, - {enabled: automationIds === null || automationIds.length > 0} - ); + }), + select: selectJsonWithHeaders, + enabled: automationIds === null || automationIds.length > 0, + }); - const pageLinks = getResponseHeader?.('Link'); - const totalCount = getResponseHeader?.('X-Hits'); - const totalCountInt = totalCount ? parseInt(totalCount, 10) : 0; + const automations = data?.json; + const pageLinks = data?.headers.Link; + const totalCountInt = data?.headers['X-Hits'] ?? 0; const paginationCaption = useMemo(() => { if (!automations || automations.length === 0 || isLoading || limit === null) { @@ -137,12 +136,12 @@ export function ConnectedAutomationsList({ /> )} {isError && } - {((isSuccess && automations.length === 0) || + {((isSuccess && automations?.length === 0) || (automationIds !== null && automationIds.length === 0)) && ( {emptyMessage} )} {isSuccess && - automations.map(automation => ( + automations?.map(automation => ( { if (!automations || automations.length === 0 || isPending) { @@ -161,11 +158,11 @@ function DetectorAutomationsTable({ {isPending && } {isError && } - {isSuccess && automations.length === 0 && ( + {isSuccess && automations?.length === 0 && ( {emptyMessage} )} {isSuccess && - automations.map(automation => ( + automations?.map(automation => ( { diff --git a/static/app/views/detectors/components/detectorListConnectedAutomations.tsx b/static/app/views/detectors/components/detectorListConnectedAutomations.tsx index 1fd7c88a5e5ee4..4f34de32721e99 100644 --- a/static/app/views/detectors/components/detectorListConnectedAutomations.tsx +++ b/static/app/views/detectors/components/detectorListConnectedAutomations.tsx @@ -1,6 +1,7 @@ import {useMemo} from 'react'; import {ClassNames} from '@emotion/react'; import styled from '@emotion/styled'; +import {useQuery} from '@tanstack/react-query'; import InteractionStateLayer from '@sentry/scraps/interactionStateLayer'; import {Stack} from '@sentry/scraps/layout'; @@ -13,7 +14,7 @@ import {EmptyCell} from 'sentry/components/workflowEngine/gridCell/emptyCell'; import {tn} from 'sentry/locale'; import {useOrganization} from 'sentry/utils/useOrganization'; import {AutomationActionSummary} from 'sentry/views/automations/components/automationActionSummary'; -import {useAutomationsQuery} from 'sentry/views/automations/hooks'; +import {automationsApiOptions} from 'sentry/views/automations/hooks'; import {getAutomationActions} from 'sentry/views/automations/hooks/utils'; import {makeAutomationDetailsPathname} from 'sentry/views/automations/pathnames'; import {useIssueStreamDetectorsForProject} from 'sentry/views/detectors/utils/useIssueStreamDetectorsForProject'; @@ -26,9 +27,11 @@ type DetectorListConnectedAutomationsProps = { function ConnectedAutomationsHoverBody({automationIds}: {automationIds: string[]}) { const organization = useOrganization(); const shownAutomations = automationIds.slice(0, 5); - const {data, isPending, isError} = useAutomationsQuery({ - ids: automationIds.slice(0, 5), - }); + const {data, isPending, isError} = useQuery( + automationsApiOptions(organization, { + ids: automationIds.slice(0, 5), + }) + ); const hasMore = automationIds.length > 5; const hasMoreText = hasMore ? ( {tn('%s more', '%s more', automationIds.length - 5)} From 15c790c068b90dbf2c61fec72688c50dcd9d7c99 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 7 Apr 2026 17:38:34 +0200 Subject: [PATCH 2/4] fix: types --- .../views/detectors/components/connectAutomationsDrawer.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/static/app/views/detectors/components/connectAutomationsDrawer.tsx b/static/app/views/detectors/components/connectAutomationsDrawer.tsx index 6996a021d5d654..adebe6fc74ce32 100644 --- a/static/app/views/detectors/components/connectAutomationsDrawer.tsx +++ b/static/app/views/detectors/components/connectAutomationsDrawer.tsx @@ -82,8 +82,7 @@ export function ConnectAutomationsDrawer({ const toggleConnected = ({automation}: {automation: Automation}) => { const newAutomations = queryClient.setQueryData( - automationsApiOptions({ - orgSlug: organization.slug, + automationsApiOptions(organization, { ids: localWorkflowIds, }).queryKey, oldAutomations => { From 7983d5669d2a81634e9c7a2240162eee63221cd0 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 7 Apr 2026 17:54:45 +0200 Subject: [PATCH 3/4] fix: cache update --- .../components/connectAutomationsDrawer.tsx | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/static/app/views/detectors/components/connectAutomationsDrawer.tsx b/static/app/views/detectors/components/connectAutomationsDrawer.tsx index adebe6fc74ce32..eff13c7e6caa38 100644 --- a/static/app/views/detectors/components/connectAutomationsDrawer.tsx +++ b/static/app/views/detectors/components/connectAutomationsDrawer.tsx @@ -80,26 +80,24 @@ export function ConnectAutomationsDrawer({ const [localWorkflowIds, setLocalWorkflowIds] = useState(initialWorkflowIds); const toggleConnected = ({automation}: {automation: Automation}) => { - const newAutomations = - queryClient.setQueryData( - automationsApiOptions(organization, { - ids: localWorkflowIds, - }).queryKey, - oldAutomations => { - if (!oldAutomations) { - return oldAutomations; - } - return { - ...oldAutomations, - json: (oldAutomations.json.some(a => a.id === automation.id) - ? oldAutomations.json.filter(a => a.id !== automation.id) - : [...oldAutomations.json, automation] - ).sort((a, b) => a.id.localeCompare(b.id)), - }; - } - )?.json ?? []; + const queryKey = automationsApiOptions(organization, { + ids: localWorkflowIds, + }).queryKey; + + const oldAutomationsData = queryClient.getQueryData(queryKey)?.json ?? []; + + const newAutomations = ( + oldAutomationsData.some(a => a.id === automation.id) + ? oldAutomationsData.filter(a => a.id !== automation.id) + : [...oldAutomationsData, automation] + ).sort((a, b) => a.id.localeCompare(b.id)); const newWorkflowIds = newAutomations.map(a => a.id); + queryClient.setQueryData( + automationsApiOptions(organization, {ids: newWorkflowIds}).queryKey, + old => (old ? {...old, json: newAutomations} : old) + ); + setLocalWorkflowIds(newWorkflowIds); setWorkflowIds(newWorkflowIds); }; From 9d99cabdbf4244d13dde9eff977f9c88aa84439e Mon Sep 17 00:00:00 2001 From: TkDodo Date: Wed, 8 Apr 2026 16:12:14 +0200 Subject: [PATCH 4/4] fix: optimistic update --- static/app/utils/api/apiFetch.tsx | 6 +++--- static/app/utils/api/apiOptions.spec.tsx | 6 +++--- .../components/connectAutomationsDrawer.tsx | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/static/app/utils/api/apiFetch.tsx b/static/app/utils/api/apiFetch.tsx index 8231c17c8666f7..eab8061edda325 100644 --- a/static/app/utils/api/apiFetch.tsx +++ b/static/app/utils/api/apiFetch.tsx @@ -8,9 +8,9 @@ import {QUERY_API_CLIENT, type UseInfiniteQueryResult} from 'sentry/utils/queryC export type ApiResponse = { headers: { - Link: string | undefined; - 'X-Hits': number | undefined; - 'X-Max-Hits': number | undefined; + Link?: string; + 'X-Hits'?: number; + 'X-Max-Hits'?: number; }; json: TResponseData; }; diff --git a/static/app/utils/api/apiOptions.spec.tsx b/static/app/utils/api/apiOptions.spec.tsx index 84060810722ab8..60a98eaab78bf6 100644 --- a/static/app/utils/api/apiOptions.spec.tsx +++ b/static/app/utils/api/apiOptions.spec.tsx @@ -154,9 +154,9 @@ describe('apiOptions', () => { }); expectTypeOf(result.current.data!.headers).toEqualTypeOf<{ - Link: string | undefined; - 'X-Hits': number | undefined; - 'X-Max-Hits': number | undefined; + Link?: string; + 'X-Hits'?: number; + 'X-Max-Hits'?: number; }>(); }); diff --git a/static/app/views/detectors/components/connectAutomationsDrawer.tsx b/static/app/views/detectors/components/connectAutomationsDrawer.tsx index eff13c7e6caa38..346219aa865f6b 100644 --- a/static/app/views/detectors/components/connectAutomationsDrawer.tsx +++ b/static/app/views/detectors/components/connectAutomationsDrawer.tsx @@ -80,11 +80,12 @@ export function ConnectAutomationsDrawer({ const [localWorkflowIds, setLocalWorkflowIds] = useState(initialWorkflowIds); const toggleConnected = ({automation}: {automation: Automation}) => { - const queryKey = automationsApiOptions(organization, { - ids: localWorkflowIds, - }).queryKey; - - const oldAutomationsData = queryClient.getQueryData(queryKey)?.json ?? []; + const oldAutomationsData = + queryClient.getQueryData( + automationsApiOptions(organization, { + ids: localWorkflowIds, + }).queryKey + )?.json ?? []; const newAutomations = ( oldAutomationsData.some(a => a.id === automation.id) @@ -95,7 +96,7 @@ export function ConnectAutomationsDrawer({ queryClient.setQueryData( automationsApiOptions(organization, {ids: newWorkflowIds}).queryKey, - old => (old ? {...old, json: newAutomations} : old) + old => ({headers: old?.headers ?? {}, json: newAutomations}) ); setLocalWorkflowIds(newWorkflowIds);