From 4036933c84f3fe45d53c15f4826cd050d109a5a5 Mon Sep 17 00:00:00 2001 From: martmull Date: Wed, 12 Mar 2025 10:40:59 +0100 Subject: [PATCH] Add console logs to code step (#10786) Works for local and lambda drivers ## After ![image](https://github.com/user-attachments/assets/ec082cf6-4159-4a15-99b6-243c73a13773) ![image](https://github.com/user-attachments/assets/f42e3f43-5ea4-4167-b4b5-9a17826fd224) --- .../src/generated-metadata/gql.ts | 4 +- .../src/generated-metadata/graphql.ts | 90 +++++++++++++++++-- .../hooks/useTestServerlessFunction.ts | 1 + .../mutations/executeOneServerlessFunction.ts | 1 + .../modules/ui/input/components/TextArea.tsx | 6 +- .../serverlessFunctionTestDataFamilyState.ts | 2 + ...rkflowEditActionFormServerlessFunction.tsx | 11 +++ .../interfaces/serverless-driver.interface.ts | 1 + .../serverless/drivers/lambda.driver.ts | 21 +++++ .../serverless/drivers/local.driver.ts | 58 ++++++++++++ ...erverless-function-execution-result.dto.ts | 3 + 11 files changed, 189 insertions(+), 9 deletions(-) diff --git a/packages/twenty-front/src/generated-metadata/gql.ts b/packages/twenty-front/src/generated-metadata/gql.ts index 7c40921ca..2655e36e8 100644 --- a/packages/twenty-front/src/generated-metadata/gql.ts +++ b/packages/twenty-front/src/generated-metadata/gql.ts @@ -36,7 +36,7 @@ const documents = { "\n fragment ServerlessFunctionFields on ServerlessFunction {\n id\n name\n description\n runtime\n timeoutSeconds\n syncStatus\n latestVersion\n latestVersionInputSchema\n publishedVersions\n createdAt\n updatedAt\n }\n": types.ServerlessFunctionFieldsFragmentDoc, "\n \n mutation CreateOneServerlessFunctionItem(\n $input: CreateServerlessFunctionInput!\n ) {\n createOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.CreateOneServerlessFunctionItemDocument, "\n \n mutation DeleteOneServerlessFunction($input: ServerlessFunctionIdInput!) {\n deleteOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.DeleteOneServerlessFunctionDocument, - "\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n duration\n status\n error\n }\n }\n": types.ExecuteOneServerlessFunctionDocument, + "\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n logs\n duration\n status\n error\n }\n }\n": types.ExecuteOneServerlessFunctionDocument, "\n \n mutation PublishOneServerlessFunction(\n $input: PublishServerlessFunctionInput!\n ) {\n publishServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.PublishOneServerlessFunctionDocument, "\n \n mutation UpdateOneServerlessFunction($input: UpdateServerlessFunctionInput!) {\n updateOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.UpdateOneServerlessFunctionDocument, "\n query FindManyAvailablePackages($input: ServerlessFunctionIdInput!) {\n getAvailablePackages(input: $input)\n }\n": types.FindManyAvailablePackagesDocument, @@ -154,7 +154,7 @@ export function graphql(source: "\n \n mutation DeleteOneServerlessFunction($i /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n duration\n status\n error\n }\n }\n"): (typeof documents)["\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n duration\n status\n error\n }\n }\n"]; +export function graphql(source: "\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n logs\n duration\n status\n error\n }\n }\n"): (typeof documents)["\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n logs\n duration\n status\n error\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 241964966..d103ff152 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -16,6 +16,8 @@ export type Scalars = { Float: { input: number; output: number; } /** Cursor for paging through collections */ ConnectionCursor: { input: any; output: any; } + /** Date custom scalar type */ + Date: { input: any; output: any; } /** A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. */ DateTime: { input: any; output: any; } /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ @@ -36,6 +38,7 @@ export type AdminPanelHealthServiceData = { __typename?: 'AdminPanelHealthServiceData'; description: Scalars['String']['output']; details?: Maybe; + errorMessage?: Maybe; id: Scalars['String']['output']; label: Scalars['String']['output']; queues?: Maybe>; @@ -50,10 +53,8 @@ export enum AdminPanelHealthServiceStatus { export type AdminPanelWorkerQueueHealth = { __typename?: 'AdminPanelWorkerQueueHealth'; id: Scalars['String']['output']; - metrics: WorkerQueueMetrics; queueName: Scalars['String']['output']; status: AdminPanelHealthServiceStatus; - workers: Scalars['Float']['output']; }; export type Analytics = { @@ -421,6 +422,17 @@ export type CustomDomainValidRecords = { records: Array; }; +export type DateFilter = { + eq?: InputMaybe; + gt?: InputMaybe; + gte?: InputMaybe; + in?: InputMaybe>; + is?: InputMaybe; + lt?: InputMaybe; + lte?: InputMaybe; + neq?: InputMaybe; +}; + export type DeleteApprovedAccessDomainInput = { id: Scalars['String']['input']; }; @@ -648,6 +660,11 @@ export enum FileFolder { WorkspaceLogo = 'WorkspaceLogo' } +export enum FilterIs { + NotNull = 'NotNull', + Null = 'Null' +} + export type FindAvailableSsoidpOutput = { __typename?: 'FindAvailableSSOIDPOutput'; id: Scalars['String']['output']; @@ -701,12 +718,24 @@ export type GlobalSearchRecord = { }; export enum HealthIndicatorId { + app = 'app', connectedAccount = 'connectedAccount', database = 'database', redis = 'redis', worker = 'worker' } +export type IdFilter = { + eq?: InputMaybe; + gt?: InputMaybe; + gte?: InputMaybe; + in?: InputMaybe>; + is?: InputMaybe; + lt?: InputMaybe; + lte?: InputMaybe; + neq?: InputMaybe; +}; + export enum IdentityProviderType { OIDC = 'OIDC', SAML = 'SAML' @@ -1339,6 +1368,16 @@ export type ObjectIndexMetadatasConnection = { pageInfo: PageInfo; }; +export type ObjectRecordFilterInput = { + and?: InputMaybe>; + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + id?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + updatedAt?: InputMaybe; +}; + /** Onboarding status */ export enum OnboardingStatus { COMPLETED = 'COMPLETED', @@ -1432,6 +1471,7 @@ export type Query = { getIndicatorHealthStatus: AdminPanelHealthServiceData; getPostgresCredentials?: Maybe; getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; + getQueueMetrics: QueueMetricsData; getRoles: Array; getSSOIdentityProviders: Array; getServerlessFunctionSourceCode?: Maybe; @@ -1513,6 +1553,11 @@ export type QueryGetIndicatorHealthStatusArgs = { }; +export type QueryGetQueueMetricsArgs = { + queueName: Scalars['String']['input']; + timeRange?: InputMaybe; +}; + export type QueryGetServerlessFunctionSourceCodeArgs = { input: GetServerlessFunctionSourceCodeInput; @@ -1549,6 +1594,8 @@ export type QueryGetTimelineThreadsFromPersonIdArgs = { export type QueryGlobalSearchArgs = { excludedObjectNameSingulars?: InputMaybe>; + filter?: InputMaybe; + includedObjectNameSingulars?: InputMaybe>; limit: Scalars['Int']['input']; searchInput: Scalars['String']['input']; }; @@ -1585,6 +1632,35 @@ export type QueryValidatePasswordResetTokenArgs = { passwordResetToken: Scalars['String']['input']; }; +export type QueueMetricsData = { + __typename?: 'QueueMetricsData'; + data: Array; + details?: Maybe; + queueName: Scalars['String']['output']; + timeRange: QueueMetricsTimeRange; + workers: Scalars['Float']['output']; +}; + +export type QueueMetricsDataPoint = { + __typename?: 'QueueMetricsDataPoint'; + x: Scalars['Float']['output']; + y: Scalars['Float']['output']; +}; + +export type QueueMetricsSeries = { + __typename?: 'QueueMetricsSeries'; + data: Array; + id: Scalars['String']['output']; +}; + +export enum QueueMetricsTimeRange { + FourHours = 'FourHours', + OneDay = 'OneDay', + OneHour = 'OneHour', + SevenDays = 'SevenDays', + TwelveHours = 'TwelveHours' +} + export type Relation = { __typename?: 'Relation'; sourceFieldMetadata: Field; @@ -1787,6 +1863,8 @@ export type ServerlessFunctionExecutionResult = { duration: Scalars['Float']['output']; /** Execution error in JSON format */ error?: Maybe; + /** Execution Logs */ + logs: Scalars['String']['output']; /** Execution status */ status: ServerlessFunctionExecutionStatus; }; @@ -2174,9 +2252,11 @@ export type WorkerQueueMetrics = { __typename?: 'WorkerQueueMetrics'; active: Scalars['Float']['output']; completed: Scalars['Float']['output']; + completedData?: Maybe>; delayed: Scalars['Float']['output']; failed: Scalars['Float']['output']; - prioritized: Scalars['Float']['output']; + failedData?: Maybe>; + failureRate: Scalars['Float']['output']; waiting: Scalars['Float']['output']; }; @@ -2468,7 +2548,7 @@ export type ExecuteOneServerlessFunctionMutationVariables = Exact<{ }>; -export type ExecuteOneServerlessFunctionMutation = { __typename?: 'Mutation', executeOneServerlessFunction: { __typename?: 'ServerlessFunctionExecutionResult', data?: any | null, duration: number, status: ServerlessFunctionExecutionStatus, error?: any | null } }; +export type ExecuteOneServerlessFunctionMutation = { __typename?: 'Mutation', executeOneServerlessFunction: { __typename?: 'ServerlessFunctionExecutionResult', data?: any | null, logs: string, duration: number, status: ServerlessFunctionExecutionStatus, error?: any | null } }; export type PublishOneServerlessFunctionMutationVariables = Exact<{ input: PublishServerlessFunctionInput; @@ -2533,7 +2613,7 @@ export const DeleteOneRelationMetadataItemDocument = {"kind":"Document","definit export const ObjectMetadataItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ObjectMetadataItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"shortcut"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"duplicateCriteria"}},{"kind":"Field","name":{"kind":"Name","value":"indexMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"indexWhereClause"}},{"kind":"Field","name":{"kind":"Name","value":"indexType"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"indexFieldMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fieldsList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"relationDefinition"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"relationId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateOneServerlessFunctionItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneServerlessFunctionItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersionInputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const DeleteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunctionIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersionInputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; -export const ExecuteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ExecuteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ExecuteServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"executeOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode; +export const ExecuteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ExecuteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ExecuteServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"executeOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"logs"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode; export const PublishOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"PublishOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PublishServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"publishServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersionInputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const UpdateOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersionInputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const FindManyAvailablePackagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyAvailablePackages"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunctionIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAvailablePackages"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/serverless-functions/hooks/useTestServerlessFunction.ts b/packages/twenty-front/src/modules/serverless-functions/hooks/useTestServerlessFunction.ts index 84e21b676..8166d57e2 100644 --- a/packages/twenty-front/src/modules/serverless-functions/hooks/useTestServerlessFunction.ts +++ b/packages/twenty-front/src/modules/serverless-functions/hooks/useTestServerlessFunction.ts @@ -45,6 +45,7 @@ export const useTestServerlessFunction = ({ 4, ) : undefined, + logs: result?.data?.executeOneServerlessFunction?.logs || '', duration: result?.data?.executeOneServerlessFunction?.duration, status: result?.data?.executeOneServerlessFunction?.status, error: result?.data?.executeOneServerlessFunction?.error diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction.ts b/packages/twenty-front/src/modules/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction.ts index 09d4518b0..08cd67acd 100644 --- a/packages/twenty-front/src/modules/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction.ts +++ b/packages/twenty-front/src/modules/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction.ts @@ -6,6 +6,7 @@ export const EXECUTE_ONE_SERVERLESS_FUNCTION = gql` ) { executeOneServerlessFunction(input: $input) { data + logs duration status error diff --git a/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx b/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx index 477a54d4a..04ef27fa7 100644 --- a/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx @@ -14,6 +14,7 @@ export type TextAreaProps = { label?: string; disabled?: boolean; minRows?: number; + maxRows?: number; onChange?: (value: string) => void; placeholder?: string; value?: string; @@ -73,12 +74,13 @@ export const TextArea = ({ disabled, placeholder, minRows = 1, + maxRows = MAX_ROWS, value = '', className, onChange, onBlur, }: TextAreaProps) => { - const computedMinRows = Math.min(minRows, MAX_ROWS); + const computedMinRows = Math.min(minRows, maxRows); const inputId = useId(); @@ -103,7 +105,7 @@ export const TextArea = ({ diff --git a/packages/twenty-front/src/modules/workflow/states/serverlessFunctionTestDataFamilyState.ts b/packages/twenty-front/src/modules/workflow/states/serverlessFunctionTestDataFamilyState.ts index 65050a520..a59accd0d 100644 --- a/packages/twenty-front/src/modules/workflow/states/serverlessFunctionTestDataFamilyState.ts +++ b/packages/twenty-front/src/modules/workflow/states/serverlessFunctionTestDataFamilyState.ts @@ -5,6 +5,7 @@ export type ServerlessFunctionTestData = { input: { [field: string]: any }; output: { data?: string; + logs: string; duration?: number; status?: ServerlessFunctionExecutionStatus; error?: string; @@ -15,6 +16,7 @@ export type ServerlessFunctionTestData = { export const DEFAULT_OUTPUT_VALUE = { data: 'Enter an input above then press "Test"', + logs: '', status: ServerlessFunctionExecutionStatus.IDLE, }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx index 8b757c76c..8e4ac2474 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx @@ -37,6 +37,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; import { CodeEditor, IconCode, IconPlayerPlay, useIcons } from 'twenty-ui'; import { useDebouncedCallback } from 'use-debounce'; +import { TextArea } from '@/ui/input/components/TextArea'; const StyledContainer = styled.div` display: flex; @@ -340,6 +341,16 @@ export const WorkflowEditActionFormServerlessFunction = ({ isTesting={isTesting} /> + + Logs +