diff --git a/packages/backend/src/apps/twitter/client/endpoints/search-tweets.ts b/packages/backend/src/apps/twitter/client/endpoints/search-tweets.ts index 634c66cf..89eddeba 100644 --- a/packages/backend/src/apps/twitter/client/endpoints/search-tweets.ts +++ b/packages/backend/src/apps/twitter/client/endpoints/search-tweets.ts @@ -19,7 +19,13 @@ export default class SearchTweets { }; let response; - const tweets: IJSONObject[] = []; + const tweets: { + data: IJSONObject[]; + error: IJSONObject | null; + } = { + data: [], + error: null, + }; do { const params: IJSONObject = { @@ -47,10 +53,15 @@ export default class SearchTweets { headers: { ...authHeader }, }); + if (response.integrationError) { + tweets.error = response.integrationError; + return tweets; + } + if (response.data.meta.result_count > 0) { response.data.data.forEach((tweet: IJSONObject) => { if (!lastInternalId || Number(tweet.id) > Number(lastInternalId)) { - tweets.push(tweet); + tweets.data.push(tweet); } else { return; } @@ -58,16 +69,6 @@ export default class SearchTweets { } } while (response.data.meta.next_token && lastInternalId); - if (response.data?.errors) { - const errorMessages = response.data.errors - .map((error: IJSONObject) => error.detail) - .join(' '); - - throw new Error( - `Error occured while fetching user data: ${errorMessages}` - ); - } - return tweets; } } diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 195ee1b7..a6f97dc9 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -188,6 +188,7 @@ type ExecutionStep { status: String dataIn: JSONObject dataOut: JSONObject + errorDetails: JSONObject createdAt: String updatedAt: String } diff --git a/packages/backend/src/helpers/http-client/index.ts b/packages/backend/src/helpers/http-client/index.ts index 505ab46e..8c0861c7 100644 --- a/packages/backend/src/helpers/http-client/index.ts +++ b/packages/backend/src/helpers/http-client/index.ts @@ -1,6 +1,8 @@ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosInstance, AxiosResponse } from 'axios'; import { IJSONObject, IHttpClientParams } from '@automatisch/types'; +type ExtendedAxiosResponse = AxiosResponse & { integrationError: IJSONObject }; + export default class HttpClient { instance: AxiosInstance; @@ -8,13 +10,25 @@ export default class HttpClient { this.instance = axios.create({ baseURL: params.baseURL, }); + + this.instance.interceptors.response.use( + (response) => response, + (error) => { + error.response.integrationError = error.response.data; + return error.response; + } + ); } async get(path: string, options?: IJSONObject) { - return await this.instance.get(path, options); + return (await this.instance.get(path, options)) as ExtendedAxiosResponse; } async post(path: string, body: IJSONObject | string, options?: IJSONObject) { - return await this.instance.post(path, body, options); + return (await this.instance.post( + path, + body, + options + )) as ExtendedAxiosResponse; } } diff --git a/packages/backend/src/services/processor.ts b/packages/backend/src/services/processor.ts index da4ddbe2..b54ec6f7 100644 --- a/packages/backend/src/services/processor.ts +++ b/packages/backend/src/services/processor.ts @@ -33,9 +33,9 @@ class Processor { const triggerStep = steps.find((step) => step.type === 'trigger'); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - let initialTriggerData = await this.getInitialTriggerData(triggerStep!); + const initialTriggerData = await this.getInitialTriggerData(triggerStep!); - if (initialTriggerData.length === 0) { + if (!initialTriggerData.error && initialTriggerData.data.length === 0) { const lastInternalId = await this.flow.lastInternalId(); const executionData: Partial = { @@ -52,12 +52,12 @@ class Processor { return; } - if (this.testRun) { - initialTriggerData = [initialTriggerData[0]]; + if (this.testRun && initialTriggerData.data.length > 0) { + initialTriggerData.data = [initialTriggerData.data[0]]; } - if (initialTriggerData.length > 1) { - initialTriggerData = initialTriggerData.sort( + if (initialTriggerData.data.length > 1) { + initialTriggerData.data = initialTriggerData.data.sort( (item: IJSONObject, nextItem: IJSONObject) => { return (item.id as number) - (nextItem.id as number); } @@ -66,7 +66,7 @@ class Processor { const executions: Execution[] = []; - for await (const data of initialTriggerData) { + for await (const data of initialTriggerData.data) { const execution = await Execution.query().insert({ flowId: this.flow.id, testRun: this.testRun, @@ -118,6 +118,22 @@ class Processor { } } + if (initialTriggerData.error) { + const executionWithError = await Execution.query().insert({ + flowId: this.flow.id, + testRun: this.testRun, + }); + + executions.push(executionWithError); + + await executionWithError.$relatedQuery('executionSteps').insertAndFetch({ + stepId: triggerStep.id, + status: 'failure', + dataIn: triggerStep.parameters, + errorDetails: initialTriggerData.error, + }); + } + if (!this.testRun) return; const lastExecutionStepFromFirstExecution = await executions[0] @@ -125,7 +141,11 @@ class Processor { .orderBy('created_at', 'desc') .first(); - return lastExecutionStepFromFirstExecution?.dataOut; + if (lastExecutionStepFromFirstExecution.errorDetails) { + return lastExecutionStepFromFirstExecution.errorDetails; + } else { + return lastExecutionStepFromFirstExecution?.dataOut; + } } async getInitialTriggerData(step: Step) { diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index cac3c3a7..49ec37c4 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -26,6 +26,7 @@ export interface IExecutionStep { step: IStep; dataIn: IJSONObject; dataOut: IJSONObject; + errorDetails: IJSONObject; status: string; createdAt: string; updatedAt: string; diff --git a/packages/web/src/components/ExecutionStep/index.tsx b/packages/web/src/components/ExecutionStep/index.tsx index 3016fc84..abddaa23 100644 --- a/packages/web/src/components/ExecutionStep/index.tsx +++ b/packages/web/src/components/ExecutionStep/index.tsx @@ -73,6 +73,7 @@ export default function ExecutionStep(props: ExecutionStepProps): React.ReactEle setActiveTabIndex(tabIndex)}> + @@ -86,6 +87,10 @@ export default function ExecutionStep(props: ExecutionStepProps): React.ReactEle + + + + diff --git a/packages/web/src/graphql/queries/get-execution-steps.ts b/packages/web/src/graphql/queries/get-execution-steps.ts index 8c3d3b82..00b42ff0 100644 --- a/packages/web/src/graphql/queries/get-execution-steps.ts +++ b/packages/web/src/graphql/queries/get-execution-steps.ts @@ -14,6 +14,7 @@ export const GET_EXECUTION_STEPS = gql` status dataIn dataOut + errorDetails createdAt updatedAt step {