Rename serverlessFunction to logicFunction (#17494)
## Summary Rename "Serverless Function" to "Logic Function" across the codebase for clearer naming. ### Environment Variable Changes | Old | New | |-----|-----| | `SERVERLESS_TYPE` | `LOGIC_FUNCTION_TYPE` | | `SERVERLESS_LAMBDA_REGION` | `LOGIC_FUNCTION_LAMBDA_REGION` | | `SERVERLESS_LAMBDA_ROLE` | `LOGIC_FUNCTION_LAMBDA_ROLE` | | `SERVERLESS_LAMBDA_SUBHOSTING_URL` | `LOGIC_FUNCTION_LAMBDA_SUBHOSTING_URL` | | `SERVERLESS_LAMBDA_ACCESS_KEY_ID` | `LOGIC_FUNCTION_LAMBDA_ACCESS_KEY_ID` | | `SERVERLESS_LAMBDA_SECRET_ACCESS_KEY` | `LOGIC_FUNCTION_LAMBDA_SECRET_ACCESS_KEY` | ### Breaking Changes - Environment variables must be updated in production deployments - Database migration renames `serverlessFunction` → `logicFunction` tables
This commit is contained in:
@@ -4,7 +4,7 @@ import { RouterProvider } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const AppRouter = () => {
|
||||
// We want to disable serverless function settings but keep the code for now
|
||||
// We want to disable logic function settings but keep the code for now
|
||||
const isFunctionSettingsEnabled = false;
|
||||
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
@@ -105,12 +105,12 @@ const SettingsDevelopersApiKeysNew = lazy(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
const SettingsServerlessFunctionDetail = lazy(() =>
|
||||
import(
|
||||
'~/pages/settings/serverless-functions/SettingsServerlessFunctionDetail'
|
||||
).then((module) => ({
|
||||
default: module.SettingsServerlessFunctionDetail,
|
||||
})),
|
||||
const SettingsLogicFunctionDetail = lazy(() =>
|
||||
import('~/pages/settings/logic-functions/SettingsLogicFunctionDetail').then(
|
||||
(module) => ({
|
||||
default: module.SettingsLogicFunctionDetail,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const SettingsWorkspace = lazy(() =>
|
||||
@@ -447,8 +447,8 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
|
||||
element={<SettingsSkillForm mode="edit" />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.ServerlessFunctionDetail}
|
||||
element={<SettingsServerlessFunctionDetail />}
|
||||
path={SettingsPath.LogicFunctionDetail}
|
||||
element={<SettingsLogicFunctionDetail />}
|
||||
/>
|
||||
<Route path={SettingsPath.Billing} element={<SettingsBilling />} />
|
||||
<Route path={SettingsPath.Domain} element={<SettingsDomain />} />
|
||||
@@ -582,8 +582,8 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
|
||||
element={<SettingsApplicationDetails />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.ApplicationServerlessFunctionDetail}
|
||||
element={<SettingsServerlessFunctionDetail />}
|
||||
path={SettingsPath.ApplicationLogicFunctionDetail}
|
||||
element={<SettingsLogicFunctionDetail />}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { AGENT_FRAGMENT } from '@/ai/graphql/fragments/agentFragment';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
import { OBJECT_METADATA_FRAGMENT } from '@/object-metadata/graphql/fragment';
|
||||
|
||||
export const APPLICATION_FRAGMENT = gql`
|
||||
${AGENT_FRAGMENT}
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
${OBJECT_METADATA_FRAGMENT}
|
||||
fragment ApplicationFields on Application {
|
||||
id
|
||||
@@ -27,8 +27,8 @@ export const APPLICATION_FRAGMENT = gql`
|
||||
objects {
|
||||
...ObjectMetadataFields
|
||||
}
|
||||
serverlessFunctions {
|
||||
...ServerlessFunctionFields
|
||||
logicFunctions {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
+4
-4
@@ -23,8 +23,8 @@ import { emitSidePanelCloseEvent } from '@/ui/layout/right-drawer/utils/emitSide
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowServerlessFunctionTabListComponentId';
|
||||
import { WorkflowServerlessFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowServerlessFunctionTabId';
|
||||
import { WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowLogicFunctionTabListComponentId';
|
||||
import { WorkflowLogicFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowLogicFunctionTabId';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -114,9 +114,9 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
set(isCommandMenuClosingState, false);
|
||||
set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
instanceId: WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
}),
|
||||
WorkflowServerlessFunctionTabId.CODE,
|
||||
WorkflowLogicFunctionTabId.CODE,
|
||||
);
|
||||
|
||||
for (const [pageId, morphItems] of snapshot
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
type ExecutionStatus,
|
||||
WorkflowStepExecutionResult,
|
||||
} from '@/workflow/components/WorkflowStepExecutionResult';
|
||||
import { type LogicFunctionTestData } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
|
||||
import { LogicFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
export const LogicFunctionExecutionResult = ({
|
||||
logicFunctionTestData,
|
||||
maxHeight,
|
||||
isTesting = false,
|
||||
}: {
|
||||
logicFunctionTestData: LogicFunctionTestData;
|
||||
maxHeight?: number;
|
||||
isTesting?: boolean;
|
||||
}) => {
|
||||
const result =
|
||||
logicFunctionTestData.output.data ||
|
||||
logicFunctionTestData.output.error ||
|
||||
'';
|
||||
|
||||
const isSuccess =
|
||||
logicFunctionTestData.output.status ===
|
||||
LogicFunctionExecutionStatus.SUCCESS;
|
||||
|
||||
const isError =
|
||||
logicFunctionTestData.output.status === LogicFunctionExecutionStatus.ERROR;
|
||||
|
||||
const duration = logicFunctionTestData.output.duration;
|
||||
const status: ExecutionStatus = {
|
||||
isSuccess,
|
||||
isError,
|
||||
successMessage: isSuccess ? t`200 OK - ${duration}ms` : undefined,
|
||||
errorMessage: isError ? t`500 Error - ${duration}ms` : undefined,
|
||||
};
|
||||
|
||||
return (
|
||||
<WorkflowStepExecutionResult
|
||||
result={result}
|
||||
language={logicFunctionTestData.language}
|
||||
height={Math.min(
|
||||
logicFunctionTestData.height,
|
||||
maxHeight ?? logicFunctionTestData.height,
|
||||
)}
|
||||
status={status}
|
||||
isTesting={isTesting}
|
||||
loadingMessage={t`Running function`}
|
||||
idleMessage={t`Output`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
import { useExecuteOneLogicFunction } from '@/settings/logic-functions/hooks/useExecuteOneLogicFunction';
|
||||
import { logicFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
|
||||
export const useTestLogicFunction = ({
|
||||
logicFunctionId,
|
||||
callback,
|
||||
}: {
|
||||
logicFunctionId: string;
|
||||
callback?: (testResult: object) => void;
|
||||
}) => {
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
const { executeOneLogicFunction } = useExecuteOneLogicFunction();
|
||||
const [logicFunctionTestData, setLogicFunctionTestData] = useRecoilState(
|
||||
logicFunctionTestDataFamilyState(logicFunctionId),
|
||||
);
|
||||
|
||||
const testLogicFunction = async () => {
|
||||
try {
|
||||
setIsTesting(true);
|
||||
await sleep(200); // Delay artificially to avoid flashing the UI
|
||||
const result = await executeOneLogicFunction({
|
||||
id: logicFunctionId,
|
||||
payload: logicFunctionTestData.input,
|
||||
version: 'draft',
|
||||
});
|
||||
|
||||
setIsTesting(false);
|
||||
|
||||
if (isDefined(result?.data?.executeOneLogicFunction?.data)) {
|
||||
callback?.(result?.data?.executeOneLogicFunction?.data);
|
||||
}
|
||||
|
||||
setLogicFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
language: 'json',
|
||||
height: 300,
|
||||
output: {
|
||||
data: result?.data?.executeOneLogicFunction?.data
|
||||
? JSON.stringify(
|
||||
result?.data?.executeOneLogicFunction?.data,
|
||||
null,
|
||||
4,
|
||||
)
|
||||
: undefined,
|
||||
logs: result?.data?.executeOneLogicFunction?.logs || '',
|
||||
duration: result?.data?.executeOneLogicFunction?.duration,
|
||||
status: result?.data?.executeOneLogicFunction?.status,
|
||||
error: result?.data?.executeOneLogicFunction?.error
|
||||
? JSON.stringify(
|
||||
result?.data?.executeOneLogicFunction?.error,
|
||||
null,
|
||||
4,
|
||||
)
|
||||
: undefined,
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
setIsTesting(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return { testLogicFunction, isTesting };
|
||||
};
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { computeNewSources } from '@/serverless-functions/utils/computeNewSources';
|
||||
import { computeNewSources } from '@/logic-functions/utils/computeNewSources';
|
||||
|
||||
describe('computeNewSources', () => {
|
||||
it('should compute new code input root 0', () => {
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// IA Generated
|
||||
|
||||
import { flattenSources } from '@/serverless-functions/utils/flattenSources';
|
||||
import { flattenSources } from '@/logic-functions/utils/flattenSources';
|
||||
import { type Sources } from 'twenty-shared/types';
|
||||
|
||||
describe('flattenSources', () => {
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { type InputSchema } from '@/workflow/types/InputSchema';
|
||||
import { getDefaultFunctionInputFromInputSchema } from '@/serverless-functions/utils/getDefaultFunctionInputFromInputSchema';
|
||||
import { getDefaultFunctionInputFromInputSchema } from '@/logic-functions/utils/getDefaultFunctionInputFromInputSchema';
|
||||
|
||||
describe('getDefaultFunctionInputFromInputSchema', () => {
|
||||
it('should init function input properly', () => {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { getFunctionInputFromSourceCode } from '@/serverless-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { getFunctionInputFromSourceCode } from '@/logic-functions/utils/getFunctionInputFromSourceCode';
|
||||
|
||||
describe('getFunctionInputFromSourceCode', () => {
|
||||
it('should return empty input if not parameter', async () => {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { getFunctionInputSchema } from '@/serverless-functions/utils/getFunctionInputSchema';
|
||||
import { getFunctionInputSchema } from '@/logic-functions/utils/getFunctionInputSchema';
|
||||
|
||||
describe('getFunctionInputSchema', () => {
|
||||
it('should analyze a simple function correctly', () => {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { mergeDefaultFunctionInputAndFunctionInput } from '@/serverless-functions/utils/mergeDefaultFunctionInputAndFunctionInput';
|
||||
import { mergeDefaultFunctionInputAndFunctionInput } from '@/logic-functions/utils/mergeDefaultFunctionInputAndFunctionInput';
|
||||
|
||||
describe('mergeDefaultFunctionInputAndFunctionInput', () => {
|
||||
it('should merge properly', () => {
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { getDefaultFunctionInputFromInputSchema } from '@/serverless-functions/utils/getDefaultFunctionInputFromInputSchema';
|
||||
import { getDefaultFunctionInputFromInputSchema } from '@/logic-functions/utils/getDefaultFunctionInputFromInputSchema';
|
||||
import { type FunctionInput } from '@/workflow/workflow-steps/workflow-actions/code-action/types/FunctionInput';
|
||||
import { isObject } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -11,7 +11,7 @@ export const getFunctionInputFromSourceCode = async (
|
||||
}
|
||||
|
||||
const { getFunctionInputSchema } = await import(
|
||||
'@/serverless-functions/utils/getFunctionInputSchema'
|
||||
'@/logic-functions/utils/getFunctionInputSchema'
|
||||
);
|
||||
const functionInputSchema = getFunctionInputSchema(sourceCode);
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ export const getToolInputSchemaFromSourceCode = async (
|
||||
const { getFunctionInputSchema } = await import('./getFunctionInputSchema');
|
||||
const inputSchema = getFunctionInputSchema(sourceCode);
|
||||
|
||||
// Serverless functions take a single params object
|
||||
// Logic functions take a single params object
|
||||
const firstParam = inputSchema[0];
|
||||
|
||||
if (firstParam?.type === 'object' && isDefined(firstParam.properties)) {
|
||||
+1
-4
@@ -28,10 +28,7 @@ export const useMetadataErrorHandler = () => {
|
||||
viewGroup: t`view group`,
|
||||
viewFilter: t`view filter`,
|
||||
index: t`index`,
|
||||
serverlessFunction: t`serverless function`,
|
||||
cronTrigger: t`cron trigger`,
|
||||
databaseEventTrigger: t`database trigger`,
|
||||
routeTrigger: t`route trigger`,
|
||||
logicFunction: t`logic function`,
|
||||
role: t`role`,
|
||||
roleTarget: t`role target`,
|
||||
agent: t`agent`,
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ export const CUSTOM_WORKSPACE_APPLICATION_MOCK = {
|
||||
description: 'workpace custom application',
|
||||
name: 'custom',
|
||||
objects: [],
|
||||
serverlessFunctions: [],
|
||||
logicFunctions: [],
|
||||
universalIdentifier: '66a698b6-f6c1-4d35-a6e7-20aeadc3cd95',
|
||||
version: '1.0.0',
|
||||
} as const satisfies Application;
|
||||
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
type ExecutionStatus,
|
||||
WorkflowStepExecutionResult,
|
||||
} from '@/workflow/components/WorkflowStepExecutionResult';
|
||||
import { type ServerlessFunctionTestData } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
export const ServerlessFunctionExecutionResult = ({
|
||||
serverlessFunctionTestData,
|
||||
maxHeight,
|
||||
isTesting = false,
|
||||
}: {
|
||||
serverlessFunctionTestData: ServerlessFunctionTestData;
|
||||
maxHeight?: number;
|
||||
isTesting?: boolean;
|
||||
}) => {
|
||||
const result =
|
||||
serverlessFunctionTestData.output.data ||
|
||||
serverlessFunctionTestData.output.error ||
|
||||
'';
|
||||
|
||||
const isSuccess =
|
||||
serverlessFunctionTestData.output.status ===
|
||||
ServerlessFunctionExecutionStatus.SUCCESS;
|
||||
|
||||
const isError =
|
||||
serverlessFunctionTestData.output.status ===
|
||||
ServerlessFunctionExecutionStatus.ERROR;
|
||||
|
||||
const duration = serverlessFunctionTestData.output.duration;
|
||||
const status: ExecutionStatus = {
|
||||
isSuccess,
|
||||
isError,
|
||||
successMessage: isSuccess ? t`200 OK - ${duration}ms` : undefined,
|
||||
errorMessage: isError ? t`500 Error - ${duration}ms` : undefined,
|
||||
};
|
||||
|
||||
return (
|
||||
<WorkflowStepExecutionResult
|
||||
result={result}
|
||||
language={serverlessFunctionTestData.language}
|
||||
height={Math.min(
|
||||
serverlessFunctionTestData.height,
|
||||
maxHeight ?? serverlessFunctionTestData.height,
|
||||
)}
|
||||
status={status}
|
||||
isTesting={isTesting}
|
||||
loadingMessage={t`Running function`}
|
||||
idleMessage={t`Output`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
|
||||
export const useTestServerlessFunction = ({
|
||||
serverlessFunctionId,
|
||||
callback,
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
callback?: (testResult: object) => void;
|
||||
}) => {
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
const { executeOneServerlessFunction } = useExecuteOneServerlessFunction();
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
|
||||
const testServerlessFunction = async () => {
|
||||
try {
|
||||
setIsTesting(true);
|
||||
await sleep(200); // Delay artificially to avoid flashing the UI
|
||||
const result = await executeOneServerlessFunction({
|
||||
id: serverlessFunctionId,
|
||||
payload: serverlessFunctionTestData.input,
|
||||
version: 'draft',
|
||||
});
|
||||
|
||||
setIsTesting(false);
|
||||
|
||||
if (isDefined(result?.data?.executeOneServerlessFunction?.data)) {
|
||||
callback?.(result?.data?.executeOneServerlessFunction?.data);
|
||||
}
|
||||
|
||||
setServerlessFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
language: 'json',
|
||||
height: 300,
|
||||
output: {
|
||||
data: result?.data?.executeOneServerlessFunction?.data
|
||||
? JSON.stringify(
|
||||
result?.data?.executeOneServerlessFunction?.data,
|
||||
null,
|
||||
4,
|
||||
)
|
||||
: undefined,
|
||||
logs: result?.data?.executeOneServerlessFunction?.logs || '',
|
||||
duration: result?.data?.executeOneServerlessFunction?.duration,
|
||||
status: result?.data?.executeOneServerlessFunction?.status,
|
||||
error: result?.data?.executeOneServerlessFunction?.error
|
||||
? JSON.stringify(
|
||||
result?.data?.executeOneServerlessFunction?.error,
|
||||
null,
|
||||
4,
|
||||
)
|
||||
: undefined,
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
setIsTesting(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return { testServerlessFunction, isTesting };
|
||||
};
|
||||
+6
-9
@@ -1,4 +1,4 @@
|
||||
import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages';
|
||||
import { useGetAvailablePackages } from '@/settings/logic-functions/hooks/useGetAvailablePackages';
|
||||
import { type EditorProps, type Monaco } from '@monaco-editor/react';
|
||||
import { type editor } from 'monaco-editor';
|
||||
import { AutoTypings } from 'monaco-editor-auto-typings';
|
||||
@@ -12,25 +12,22 @@ export type File = {
|
||||
path: string;
|
||||
};
|
||||
|
||||
type SettingsServerlessFunctionCodeEditorProps = Omit<
|
||||
EditorProps,
|
||||
'onChange'
|
||||
> & {
|
||||
type SettingsLogicFunctionCodeEditorProps = Omit<EditorProps, 'onChange'> & {
|
||||
currentFilePath: string;
|
||||
files: File[];
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
export const SettingsServerlessFunctionCodeEditor = ({
|
||||
export const SettingsLogicFunctionCodeEditor = ({
|
||||
currentFilePath,
|
||||
files,
|
||||
onChange,
|
||||
height = 450,
|
||||
options = undefined,
|
||||
}: SettingsServerlessFunctionCodeEditorProps) => {
|
||||
const { serverlessFunctionId = '' } = useParams();
|
||||
}: SettingsLogicFunctionCodeEditorProps) => {
|
||||
const { logicFunctionId = '' } = useParams();
|
||||
const { availablePackages } = useGetAvailablePackages({
|
||||
id: serverlessFunctionId,
|
||||
id: logicFunctionId,
|
||||
});
|
||||
|
||||
const currentFile = files.find((file) => file.path === currentFilePath);
|
||||
+4
-4
@@ -13,19 +13,19 @@ const StyledHeaderTitle = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
type SettingsServerlessFunctionLabelContainerProps = {
|
||||
type SettingsLogicFunctionLabelContainerProps = {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
export const SettingsServerlessFunctionLabelContainer = ({
|
||||
export const SettingsLogicFunctionLabelContainer = ({
|
||||
value,
|
||||
onChange,
|
||||
}: SettingsServerlessFunctionLabelContainerProps) => {
|
||||
}: SettingsLogicFunctionLabelContainerProps) => {
|
||||
return (
|
||||
<StyledHeaderTitle>
|
||||
<TitleInput
|
||||
instanceId="serverless-function-name-input"
|
||||
instanceId="logic-function-name-input"
|
||||
sizeVariant="md"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { type ServerlessFunctionNewFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { type LogicFunctionNewFormValues } from '@/settings/logic-functions/hooks/useLogicFunctionUpdateFormState';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { TextArea } from '@/ui/input/components/TextArea';
|
||||
import styled from '@emotion/styled';
|
||||
@@ -12,12 +12,12 @@ const StyledInputsContainer = styled.div`
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionNewForm = ({
|
||||
export const SettingsLogicFunctionNewForm = ({
|
||||
formValues,
|
||||
onChange,
|
||||
readonly = false,
|
||||
}: {
|
||||
formValues: ServerlessFunctionNewFormValues;
|
||||
formValues: LogicFunctionNewFormValues;
|
||||
onChange: (key: string) => (value: string) => void;
|
||||
readonly?: boolean;
|
||||
}) => {
|
||||
+1
-1
@@ -7,7 +7,7 @@ import { useParams } from 'react-router-dom';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
export const SettingsServerlessFunctionTabEnvironmentVariablesSection = () => {
|
||||
export const SettingsLogicFunctionTabEnvironmentVariablesSection = () => {
|
||||
const { applicationId = '' } = useParams<{ applicationId: string }>();
|
||||
return (
|
||||
<Section>
|
||||
+7
-9
@@ -1,9 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { type ServerlessFunction } from '~/generated-metadata/graphql';
|
||||
import { type LogicFunction } from '~/generated-metadata/graphql';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { IconChevronRight } from 'twenty-ui/display';
|
||||
import { StyledTableRow } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTable';
|
||||
import { StyledTableRow } from '@/settings/logic-functions/components/SettingsLogicFunctionsTable';
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
@@ -24,21 +24,19 @@ const StyledIconChevronRight = styled(IconChevronRight)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionsFieldItemTableRow = ({
|
||||
serverlessFunction,
|
||||
export const SettingsLogicFunctionsFieldItemTableRow = ({
|
||||
logicFunction,
|
||||
to,
|
||||
}: {
|
||||
serverlessFunction: ServerlessFunction;
|
||||
logicFunction: LogicFunction;
|
||||
to: string;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledTableRow to={to}>
|
||||
<StyledNameTableCell>{serverlessFunction.name}</StyledNameTableCell>
|
||||
<StyledNameTableCell>{logicFunction.name}</StyledNameTableCell>
|
||||
<StyledNameTableCell></StyledNameTableCell>
|
||||
<StyledRuntimeTableCell>
|
||||
{serverlessFunction.runtime}
|
||||
</StyledRuntimeTableCell>
|
||||
<StyledRuntimeTableCell>{logicFunction.runtime}</StyledRuntimeTableCell>
|
||||
<StyledIconTableCell>
|
||||
<StyledIconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
+14
-17
@@ -1,4 +1,4 @@
|
||||
import { SettingsServerlessFunctionsFieldItemTableRow } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow';
|
||||
import { SettingsLogicFunctionsFieldItemTableRow } from '@/settings/logic-functions/components/SettingsLogicFunctionsFieldItemTableRow';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
@@ -6,7 +6,7 @@ import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import styled from '@emotion/styled';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { type ServerlessFunction } from '~/generated-metadata/graphql';
|
||||
import { type LogicFunction } from '~/generated-metadata/graphql';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
@@ -18,16 +18,16 @@ const StyledTableBody = styled(TableBody)`
|
||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionsTable = ({
|
||||
serverlessFunctions,
|
||||
export const SettingsLogicFunctionsTable = ({
|
||||
logicFunctions,
|
||||
}: {
|
||||
serverlessFunctions: ServerlessFunction[];
|
||||
logicFunctions: LogicFunction[];
|
||||
}) => {
|
||||
const { applicationId = '' } = useParams();
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
if (serverlessFunctions.length === 0) {
|
||||
if (logicFunctions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -40,17 +40,14 @@ export const SettingsServerlessFunctionsTable = ({
|
||||
<TableHeader></TableHeader>
|
||||
</StyledTableRow>
|
||||
<StyledTableBody>
|
||||
{serverlessFunctions.map((serverlessFunction: ServerlessFunction) => (
|
||||
<SettingsServerlessFunctionsFieldItemTableRow
|
||||
key={serverlessFunction.id}
|
||||
serverlessFunction={serverlessFunction}
|
||||
to={getSettingsPath(
|
||||
SettingsPath.ApplicationServerlessFunctionDetail,
|
||||
{
|
||||
applicationId,
|
||||
serverlessFunctionId: serverlessFunction.id,
|
||||
},
|
||||
)}
|
||||
{logicFunctions.map((logicFunction: LogicFunction) => (
|
||||
<SettingsLogicFunctionsFieldItemTableRow
|
||||
key={logicFunction.id}
|
||||
logicFunction={logicFunction}
|
||||
to={getSettingsPath(SettingsPath.ApplicationLogicFunctionDetail, {
|
||||
applicationId,
|
||||
logicFunctionId: logicFunction.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</StyledTableBody>
|
||||
+11
-9
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
type File,
|
||||
SettingsServerlessFunctionCodeEditor,
|
||||
} from '@/settings/serverless-functions/components/SettingsServerlessFunctionCodeEditor';
|
||||
import { SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/settings/serverless-functions/constants/SettingsServerlessFunctionTabListComponentId';
|
||||
SettingsLogicFunctionCodeEditor,
|
||||
} from '@/settings/logic-functions/components/SettingsLogicFunctionCodeEditor';
|
||||
import { SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/settings/logic-functions/constants/SettingsLogicFunctionTabListComponentId';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
@@ -16,7 +16,7 @@ const StyledTabList = styled(TabList)`
|
||||
border-bottom: none;
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionCodeEditorTab = ({
|
||||
export const SettingsLogicFunctionCodeEditorTab = ({
|
||||
files,
|
||||
handleExecute,
|
||||
onChange,
|
||||
@@ -31,7 +31,7 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
|
||||
}) => {
|
||||
const activeTabId = useRecoilComponentValue(
|
||||
activeTabIdComponentState,
|
||||
SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
);
|
||||
const TestButton = (
|
||||
<Button
|
||||
@@ -50,7 +50,7 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
|
||||
tabs={files.map((file) => {
|
||||
return { id: file.path, title: file.path.split('/').at(-1) || '' };
|
||||
})}
|
||||
componentInstanceId={SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID}
|
||||
componentInstanceId={SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -62,16 +62,18 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
|
||||
/>
|
||||
<CoreEditorHeader leftNodes={[HeaderTabList]} rightNodes={[TestButton]} />
|
||||
{activeTabId && (
|
||||
<SettingsServerlessFunctionCodeEditor
|
||||
<SettingsLogicFunctionCodeEditor
|
||||
files={files}
|
||||
currentFilePath={activeTabId}
|
||||
onChange={(newCodeValue) => onChange(activeTabId, newCodeValue)}
|
||||
onChange={(newCodeValue: string) =>
|
||||
onChange(activeTabId, newCodeValue)
|
||||
}
|
||||
options={
|
||||
isManaged
|
||||
? {
|
||||
readOnly: true,
|
||||
readOnlyMessage: {
|
||||
value: t`Managed serverless functions are not editable`,
|
||||
value: t`Managed logic functions are not editable`,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { SettingsLogicFunctionNewForm } from '@/settings/logic-functions/components/SettingsLogicFunctionNewForm';
|
||||
import { SettingsLogicFunctionTabEnvironmentVariablesSection } from '@/settings/logic-functions/components/SettingsLogicFunctionTabEnvironmentVariablesSection';
|
||||
import { type LogicFunctionFormValues } from '@/settings/logic-functions/hooks/useLogicFunctionUpdateFormState';
|
||||
|
||||
export const SettingsLogicFunctionSettingsTab = ({
|
||||
formValues,
|
||||
onChange,
|
||||
}: {
|
||||
formValues: LogicFunctionFormValues;
|
||||
onChange: (key: string) => (value: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<SettingsLogicFunctionNewForm
|
||||
formValues={formValues}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<SettingsLogicFunctionTabEnvironmentVariablesSection />
|
||||
</>
|
||||
);
|
||||
};
|
||||
+1
-1
@@ -28,7 +28,7 @@ const StyledTableRow = styled(TableRow)`
|
||||
grid-template-columns: 180px 300px 32px;
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
|
||||
export const SettingsLogicFunctionTabEnvironmentVariableTableRow = ({
|
||||
envVariable,
|
||||
onChange,
|
||||
onDelete,
|
||||
+20
-15
@@ -1,5 +1,8 @@
|
||||
import { ServerlessFunctionExecutionResult } from '@/serverless-functions/components/ServerlessFunctionExecutionResult';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { LogicFunctionExecutionResult } from '@/logic-functions/components/LogicFunctionExecutionResult';
|
||||
import {
|
||||
type LogicFunctionTestData,
|
||||
logicFunctionTestDataFamilyState,
|
||||
} from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilState } from 'recoil';
|
||||
@@ -20,27 +23,29 @@ const StyledCodeEditorContainer = styled.div`
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionTestTab = ({
|
||||
export const SettingsLogicFunctionTestTab = ({
|
||||
handleExecute,
|
||||
serverlessFunctionId,
|
||||
logicFunctionId,
|
||||
isTesting = false,
|
||||
}: {
|
||||
handleExecute: () => void;
|
||||
serverlessFunctionId: string;
|
||||
logicFunctionId: string;
|
||||
isTesting?: boolean;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
const [logicFunctionTestData, setLogicFunctionTestData] =
|
||||
useRecoilState<LogicFunctionTestData>(
|
||||
logicFunctionTestDataFamilyState(logicFunctionId),
|
||||
);
|
||||
|
||||
const onChange = (newInput: string) => {
|
||||
setServerlessFunctionTestData((prev) => ({
|
||||
setLogicFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
input: JSON.parse(newInput),
|
||||
}));
|
||||
};
|
||||
|
||||
const testLogsTextAreaId = `${serverlessFunctionId}-test-logs`;
|
||||
const testLogsTextAreaId = `${logicFunctionId}-test-logs`;
|
||||
|
||||
return (
|
||||
<Section>
|
||||
@@ -65,26 +70,26 @@ export const SettingsServerlessFunctionTestTab = ({
|
||||
]}
|
||||
/>
|
||||
<CodeEditor
|
||||
value={JSON.stringify(serverlessFunctionTestData.input, null, 4)}
|
||||
value={JSON.stringify(logicFunctionTestData.input, null, 4)}
|
||||
language="json"
|
||||
height={100}
|
||||
onChange={onChange}
|
||||
variant="with-header"
|
||||
/>
|
||||
</StyledCodeEditorContainer>
|
||||
<ServerlessFunctionExecutionResult
|
||||
serverlessFunctionTestData={serverlessFunctionTestData}
|
||||
<LogicFunctionExecutionResult
|
||||
logicFunctionTestData={logicFunctionTestData}
|
||||
maxHeight={
|
||||
serverlessFunctionTestData.output.logs.length > 0 ? 200 : undefined
|
||||
logicFunctionTestData.output.logs.length > 0 ? 200 : undefined
|
||||
}
|
||||
isTesting={isTesting}
|
||||
/>
|
||||
{serverlessFunctionTestData.output.logs.length > 0 && (
|
||||
{logicFunctionTestData.output.logs.length > 0 && (
|
||||
<StyledCodeEditorContainer>
|
||||
<InputLabel>{t`Logs`}</InputLabel>
|
||||
<TextArea
|
||||
textAreaId={testLogsTextAreaId}
|
||||
value={isTesting ? '' : serverlessFunctionTestData.output.logs}
|
||||
value={isTesting ? '' : logicFunctionTestData.output.logs}
|
||||
maxRows={20}
|
||||
disabled
|
||||
/>
|
||||
+4
-4
@@ -7,7 +7,7 @@ import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { type ServerlessFunction } from '~/generated/graphql';
|
||||
import { type LogicFunction } from '~/generated/graphql';
|
||||
|
||||
export const StyledRouteTriggerTableRow = styled(TableRow)`
|
||||
grid-template-columns: 1fr 120px 120px;
|
||||
@@ -35,10 +35,10 @@ const StyledEmptyState = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
export const SettingsServerlessFunctionTriggersTab = ({
|
||||
serverlessFunction: _serverlessFunction,
|
||||
export const SettingsLogicFunctionTriggersTab = ({
|
||||
logicFunction: _logicFunction,
|
||||
}: {
|
||||
serverlessFunction: ServerlessFunction;
|
||||
logicFunction: LogicFunction;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export const SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID =
|
||||
'settings-logic-function-editor-tab-list';
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const SERVERLESS_FUNCTION_FRAGMENT = gql`
|
||||
fragment ServerlessFunctionFields on ServerlessFunction {
|
||||
export const LOGIC_FUNCTION_FRAGMENT = gql`
|
||||
fragment LogicFunctionFields on LogicFunction {
|
||||
id
|
||||
name
|
||||
description
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const CREATE_ONE_LOGIC_FUNCTION = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
mutation CreateOneLogicFunctionItem($input: CreateLogicFunctionInput!) {
|
||||
createOneLogicFunction(input: $input) {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const DELETE_ONE_LOGIC_FUNCTION = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
mutation DeleteOneLogicFunction($input: LogicFunctionIdInput!) {
|
||||
deleteOneLogicFunction(input: $input) {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const EXECUTE_ONE_LOGIC_FUNCTION = gql`
|
||||
mutation ExecuteOneLogicFunction($input: ExecuteLogicFunctionInput!) {
|
||||
executeOneLogicFunction(input: $input) {
|
||||
data
|
||||
logs
|
||||
duration
|
||||
status
|
||||
error
|
||||
}
|
||||
}
|
||||
`;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const PUBLISH_ONE_LOGIC_FUNCTION = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
mutation PublishOneLogicFunction($input: PublishLogicFunctionInput!) {
|
||||
publishLogicFunction(input: $input) {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const UPDATE_ONE_LOGIC_FUNCTION = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
mutation UpdateOneLogicFunction($input: UpdateLogicFunctionInput!) {
|
||||
updateOneLogicFunction(input: $input) {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const FIND_MANY_AVAILABLE_PACKAGES = gql`
|
||||
query FindManyAvailablePackages($input: ServerlessFunctionIdInput!) {
|
||||
query FindManyAvailablePackages($input: LogicFunctionIdInput!) {
|
||||
getAvailablePackages(input: $input)
|
||||
}
|
||||
`;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const FIND_MANY_LOGIC_FUNCTIONS = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
query GetManyLogicFunctions {
|
||||
findManyLogicFunctions {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { LOGIC_FUNCTION_FRAGMENT } from '@/settings/logic-functions/graphql/fragments/logicFunctionFragment';
|
||||
|
||||
export const FIND_ONE_LOGIC_FUNCTION = gql`
|
||||
${LOGIC_FUNCTION_FRAGMENT}
|
||||
query GetOneLogicFunction($input: LogicFunctionIdInput!) {
|
||||
findOneLogicFunction(input: $input) {
|
||||
...LogicFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE = gql`
|
||||
query FindOneLogicFunctionSourceCode(
|
||||
$input: GetLogicFunctionSourceCodeInput!
|
||||
) {
|
||||
getLogicFunctionSourceCode(input: $input)
|
||||
}
|
||||
`;
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
import { useLogicFunctionUpdateFormState } from '@/settings/logic-functions/hooks/useLogicFunctionUpdateFormState';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
jest.mock('@/settings/logic-functions/hooks/useGetOneLogicFunction', () => ({
|
||||
useGetOneLogicFunction: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
'@/settings/logic-functions/hooks/useGetOneLogicFunctionSourceCode',
|
||||
() => ({
|
||||
useGetOneLogicFunctionSourceCode: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
describe('useLogicFunctionUpdateFormState', () => {
|
||||
test('should return a form', () => {
|
||||
const logicFunctionId = 'logicFunctionId';
|
||||
const useGetOneLogicFunctionMock = jest.requireMock(
|
||||
'@/settings/logic-functions/hooks/useGetOneLogicFunction',
|
||||
);
|
||||
useGetOneLogicFunctionMock.useGetOneLogicFunction.mockReturnValue({
|
||||
logicFunction: { name: 'name' },
|
||||
});
|
||||
const useGetOneLogicFunctionSourceCodeMock = jest.requireMock(
|
||||
'@/settings/logic-functions/hooks/useGetOneLogicFunctionSourceCode',
|
||||
);
|
||||
useGetOneLogicFunctionSourceCodeMock.useGetOneLogicFunctionSourceCode.mockReturnValue(
|
||||
{
|
||||
code: { src: { 'index.ts': 'export const handler = () => {}' } },
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(
|
||||
() => useLogicFunctionUpdateFormState({ logicFunctionId }),
|
||||
{
|
||||
wrapper: RecoilRoot,
|
||||
},
|
||||
);
|
||||
|
||||
const { formValues } = result.current;
|
||||
|
||||
expect(formValues).toEqual({
|
||||
name: '',
|
||||
description: '',
|
||||
code: { src: { 'index.ts': '' } },
|
||||
});
|
||||
});
|
||||
});
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { EXECUTE_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/mutations/executeOneLogicFunction';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import {
|
||||
type ExecuteOneLogicFunctionMutation,
|
||||
type ExecuteOneLogicFunctionMutationVariables,
|
||||
type ExecuteLogicFunctionInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useExecuteOneLogicFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const [mutate] = useMutation<
|
||||
ExecuteOneLogicFunctionMutation,
|
||||
ExecuteOneLogicFunctionMutationVariables
|
||||
>(EXECUTE_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const executeOneLogicFunction = async (input: ExecuteLogicFunctionInput) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
});
|
||||
};
|
||||
return { executeOneLogicFunction };
|
||||
};
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { FIND_MANY_AVAILABLE_PACKAGES } from '@/settings/serverless-functions/graphql/queries/findManyAvailablePackages';
|
||||
import { FIND_MANY_AVAILABLE_PACKAGES } from '@/settings/logic-functions/graphql/queries/findManyAvailablePackages';
|
||||
import {
|
||||
type FindManyAvailablePackagesQuery,
|
||||
type FindManyAvailablePackagesQueryVariables,
|
||||
type ServerlessFunctionIdInput,
|
||||
type LogicFunctionIdInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetAvailablePackages = (input: ServerlessFunctionIdInput) => {
|
||||
export const useGetAvailablePackages = (input: LogicFunctionIdInput) => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { data } = useQuery<
|
||||
FindManyAvailablePackagesQuery,
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_MANY_LOGIC_FUNCTIONS } from '@/settings/logic-functions/graphql/queries/findManyLogicFunctions';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import {
|
||||
type GetManyLogicFunctionsQuery,
|
||||
type GetManyLogicFunctionsQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetManyLogicFunctions = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
|
||||
const { data, loading, error } = useQuery<
|
||||
GetManyLogicFunctionsQuery,
|
||||
GetManyLogicFunctionsQueryVariables
|
||||
>(FIND_MANY_LOGIC_FUNCTIONS, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
});
|
||||
|
||||
return {
|
||||
logicFunctions: data?.findManyLogicFunctions || [],
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/queries/findOneLogicFunction';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import {
|
||||
type GetOneLogicFunctionQuery,
|
||||
type GetOneLogicFunctionQueryVariables,
|
||||
type LogicFunctionIdInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetOneLogicFunction = ({
|
||||
id,
|
||||
onCompleted,
|
||||
}: LogicFunctionIdInput & {
|
||||
onCompleted?: (data: GetOneLogicFunctionQuery) => void;
|
||||
}) => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { data, loading } = useQuery<
|
||||
GetOneLogicFunctionQuery,
|
||||
GetOneLogicFunctionQueryVariables
|
||||
>(FIND_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
variables: {
|
||||
input: { id },
|
||||
},
|
||||
onCompleted,
|
||||
});
|
||||
return {
|
||||
logicFunction: data?.findOneLogicFunction || null,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE } from '@/settings/logic-functions/graphql/queries/findOneLogicFunctionSourceCode';
|
||||
import {
|
||||
type FindOneLogicFunctionSourceCodeQuery,
|
||||
type FindOneLogicFunctionSourceCodeQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetOneLogicFunctionSourceCode = ({
|
||||
id,
|
||||
version,
|
||||
onCompleted,
|
||||
}: {
|
||||
id: string;
|
||||
version: string;
|
||||
onCompleted?: (data: FindOneLogicFunctionSourceCodeQuery) => void;
|
||||
}) => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { data, loading } = useQuery<
|
||||
FindOneLogicFunctionSourceCodeQuery,
|
||||
FindOneLogicFunctionSourceCodeQueryVariables
|
||||
>(FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
variables: {
|
||||
input: { id, version },
|
||||
},
|
||||
onCompleted,
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
return { code: data?.getLogicFunctionSourceCode, loading };
|
||||
};
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { flattenSources } from '@/logic-functions/utils/flattenSources';
|
||||
import { getFunctionInputFromSourceCode } from '@/logic-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { useGetOneLogicFunction } from '@/settings/logic-functions/hooks/useGetOneLogicFunction';
|
||||
import { useGetOneLogicFunctionSourceCode } from '@/settings/logic-functions/hooks/useGetOneLogicFunctionSourceCode';
|
||||
import { logicFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
|
||||
import { type Dispatch, type SetStateAction, useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { type Sources } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type FindOneLogicFunctionSourceCodeQuery,
|
||||
type GetOneLogicFunctionQuery,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { type LogicFunction } from '~/generated/graphql';
|
||||
|
||||
export type LogicFunctionNewFormValues = {
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type LogicFunctionFormValues = LogicFunctionNewFormValues & {
|
||||
code: Sources;
|
||||
};
|
||||
|
||||
type SetLogicFunctionFormValues = Dispatch<
|
||||
SetStateAction<LogicFunctionFormValues>
|
||||
>;
|
||||
|
||||
export const useLogicFunctionUpdateFormState = ({
|
||||
logicFunctionId,
|
||||
logicFunctionVersion = 'draft',
|
||||
}: {
|
||||
logicFunctionId: string;
|
||||
logicFunctionVersion?: string;
|
||||
}): {
|
||||
formValues: LogicFunctionFormValues;
|
||||
logicFunction: LogicFunction | null;
|
||||
setFormValues: SetLogicFunctionFormValues;
|
||||
loading: boolean;
|
||||
} => {
|
||||
const [formValues, setFormValues] = useState<LogicFunctionFormValues>({
|
||||
name: '',
|
||||
description: '',
|
||||
code: { src: { 'index.ts': '' } },
|
||||
});
|
||||
|
||||
const [logicFunctionTestData, setLogicFunctionTestData] = useRecoilState(
|
||||
logicFunctionTestDataFamilyState(logicFunctionId),
|
||||
);
|
||||
|
||||
const { logicFunction, loading: logicFunctionLoading } =
|
||||
useGetOneLogicFunction({
|
||||
id: logicFunctionId,
|
||||
onCompleted: (data: GetOneLogicFunctionQuery) => {
|
||||
const fn = data?.findOneLogicFunction;
|
||||
|
||||
if (isDefined(fn)) {
|
||||
setFormValues((prevState) => ({
|
||||
...prevState,
|
||||
name: fn.name || '',
|
||||
description: fn.description || '',
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { loading: logicFunctionSourceCodeLoading } =
|
||||
useGetOneLogicFunctionSourceCode({
|
||||
id: logicFunctionId,
|
||||
version: logicFunctionVersion,
|
||||
onCompleted: async (data: FindOneLogicFunctionSourceCodeQuery) => {
|
||||
const code = data?.getLogicFunctionSourceCode;
|
||||
|
||||
setFormValues((prevState) => ({
|
||||
...prevState,
|
||||
code: code || prevState.code,
|
||||
}));
|
||||
|
||||
if (logicFunctionTestData.shouldInitInput) {
|
||||
const flattenedCode = flattenSources(code);
|
||||
|
||||
const sourceCode = flattenedCode.find(
|
||||
(flatCode) => flatCode.path === logicFunction?.sourceHandlerPath,
|
||||
);
|
||||
|
||||
if (isDefined(sourceCode)) {
|
||||
const functionInput = await getFunctionInputFromSourceCode(
|
||||
sourceCode.content,
|
||||
);
|
||||
|
||||
setLogicFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
input: functionInput,
|
||||
shouldInitInput: false,
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
formValues,
|
||||
setFormValues,
|
||||
logicFunction,
|
||||
loading: logicFunctionSourceCodeLoading || logicFunctionLoading,
|
||||
};
|
||||
};
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { CREATE_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/mutations/createOneLogicFunction';
|
||||
import { DELETE_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/mutations/deleteOneLogicFunction';
|
||||
import { UPDATE_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/mutations/updateOneLogicFunction';
|
||||
import { FIND_MANY_LOGIC_FUNCTIONS } from '@/settings/logic-functions/graphql/queries/findManyLogicFunctions';
|
||||
import { FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE } from '@/settings/logic-functions/graphql/queries/findOneLogicFunctionSourceCode';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ApolloError, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import {
|
||||
type CreateOneLogicFunctionItemMutation,
|
||||
type CreateOneLogicFunctionItemMutationVariables,
|
||||
type DeleteOneLogicFunctionMutation,
|
||||
type DeleteOneLogicFunctionMutationVariables,
|
||||
type UpdateOneLogicFunctionMutation,
|
||||
type UpdateOneLogicFunctionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePersistLogicFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const [createLogicFunctionMutation] = useMutation<
|
||||
CreateOneLogicFunctionItemMutation,
|
||||
CreateOneLogicFunctionItemMutationVariables
|
||||
>(CREATE_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const [updateLogicFunctionMutation] = useMutation<
|
||||
UpdateOneLogicFunctionMutation,
|
||||
UpdateOneLogicFunctionMutationVariables
|
||||
>(UPDATE_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const [deleteLogicFunctionMutation] = useMutation<
|
||||
DeleteOneLogicFunctionMutation,
|
||||
DeleteOneLogicFunctionMutationVariables
|
||||
>(DELETE_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const createLogicFunction = useCallback(
|
||||
async (
|
||||
variables: CreateOneLogicFunctionItemMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof createLogicFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await createLogicFunctionMutation({
|
||||
variables,
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_LOGIC_FUNCTIONS) ?? ''],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'logicFunction',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[createLogicFunctionMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const updateLogicFunction = useCallback(
|
||||
async (
|
||||
variables: UpdateOneLogicFunctionMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateLogicFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await updateLogicFunctionMutation({
|
||||
variables,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'logicFunction',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[updateLogicFunctionMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const deleteLogicFunction = useCallback(
|
||||
async (
|
||||
variables: DeleteOneLogicFunctionMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteLogicFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await deleteLogicFunctionMutation({
|
||||
variables,
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'logicFunction',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[deleteLogicFunctionMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
return {
|
||||
createLogicFunction,
|
||||
updateLogicFunction,
|
||||
deleteLogicFunction,
|
||||
};
|
||||
};
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { PUBLISH_ONE_LOGIC_FUNCTION } from '@/settings/logic-functions/graphql/mutations/publishOneLogicFunction';
|
||||
import { FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE } from '@/settings/logic-functions/graphql/queries/findOneLogicFunctionSourceCode';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import {
|
||||
type PublishOneLogicFunctionMutation,
|
||||
type PublishOneLogicFunctionMutationVariables,
|
||||
type PublishLogicFunctionInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePublishOneLogicFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const [mutate] = useMutation<
|
||||
PublishOneLogicFunctionMutation,
|
||||
PublishOneLogicFunctionMutationVariables
|
||||
>(PUBLISH_ONE_LOGIC_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const publishOneLogicFunction = async (input: PublishLogicFunctionInput) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_LOGIC_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
return { publishOneLogicFunction };
|
||||
};
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm';
|
||||
import { SettingsServerlessFunctionTabEnvironmentVariablesSection } from '@/settings/serverless-functions/components/SettingsServerlessFunctionTabEnvironmentVariablesSection';
|
||||
import { type ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
|
||||
export const SettingsServerlessFunctionSettingsTab = ({
|
||||
formValues,
|
||||
onChange,
|
||||
}: {
|
||||
formValues: ServerlessFunctionFormValues;
|
||||
onChange: (key: string) => (value: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<SettingsServerlessFunctionNewForm
|
||||
formValues={formValues}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<SettingsServerlessFunctionTabEnvironmentVariablesSection />
|
||||
</>
|
||||
);
|
||||
};
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export const SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID =
|
||||
'settings-serverless-function-editor-tab-list';
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const CREATE_ONE_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
mutation CreateOneServerlessFunctionItem(
|
||||
$input: CreateServerlessFunctionInput!
|
||||
) {
|
||||
createOneServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const DELETE_ONE_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
mutation DeleteOneServerlessFunction($input: ServerlessFunctionIdInput!) {
|
||||
deleteOneServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const EXECUTE_ONE_SERVERLESS_FUNCTION = gql`
|
||||
mutation ExecuteOneServerlessFunction(
|
||||
$input: ExecuteServerlessFunctionInput!
|
||||
) {
|
||||
executeOneServerlessFunction(input: $input) {
|
||||
data
|
||||
logs
|
||||
duration
|
||||
status
|
||||
error
|
||||
}
|
||||
}
|
||||
`;
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const PUBLISH_ONE_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
mutation PublishOneServerlessFunction(
|
||||
$input: PublishServerlessFunctionInput!
|
||||
) {
|
||||
publishServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const UPDATE_ONE_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
mutation UpdateOneServerlessFunction($input: UpdateServerlessFunctionInput!) {
|
||||
updateOneServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const FIND_MANY_SERVERLESS_FUNCTIONS = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
query GetManyServerlessFunctions {
|
||||
findManyServerlessFunctions {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { SERVERLESS_FUNCTION_FRAGMENT } from '@/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment';
|
||||
|
||||
export const FIND_ONE_SERVERLESS_FUNCTION = gql`
|
||||
${SERVERLESS_FUNCTION_FRAGMENT}
|
||||
query GetOneServerlessFunction($input: ServerlessFunctionIdInput!) {
|
||||
findOneServerlessFunction(input: $input) {
|
||||
...ServerlessFunctionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE = gql`
|
||||
query FindOneServerlessFunctionSourceCode(
|
||||
$input: GetServerlessFunctionSourceCodeInput!
|
||||
) {
|
||||
getServerlessFunctionSourceCode(input: $input)
|
||||
}
|
||||
`;
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
jest.mock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunction',
|
||||
() => ({
|
||||
useGetOneServerlessFunction: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode',
|
||||
() => ({
|
||||
useGetOneServerlessFunctionSourceCode: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
describe('useServerlessFunctionUpdateFormState', () => {
|
||||
test('should return a form', () => {
|
||||
const serverlessFunctionId = 'serverlessFunctionId';
|
||||
const useGetOneServerlessFunctionMock = jest.requireMock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunction',
|
||||
);
|
||||
useGetOneServerlessFunctionMock.useGetOneServerlessFunction.mockReturnValue(
|
||||
{
|
||||
serverlessFunction: { name: 'name' },
|
||||
},
|
||||
);
|
||||
const useGetOneServerlessFunctionSourceCodeMock = jest.requireMock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode',
|
||||
);
|
||||
useGetOneServerlessFunctionSourceCodeMock.useGetOneServerlessFunctionSourceCode.mockReturnValue(
|
||||
{
|
||||
code: { src: { 'index.ts': 'export const handler = () => {}' } },
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(
|
||||
() => useServerlessFunctionUpdateFormState({ serverlessFunctionId }),
|
||||
{
|
||||
wrapper: RecoilRoot,
|
||||
},
|
||||
);
|
||||
|
||||
const { formValues } = result.current;
|
||||
|
||||
expect(formValues).toEqual({
|
||||
name: '',
|
||||
description: '',
|
||||
code: { src: { 'index.ts': '' } },
|
||||
});
|
||||
});
|
||||
});
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { EXECUTE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import {
|
||||
type ExecuteOneServerlessFunctionMutation,
|
||||
type ExecuteOneServerlessFunctionMutationVariables,
|
||||
type ExecuteServerlessFunctionInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useExecuteOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const [mutate] = useMutation<
|
||||
ExecuteOneServerlessFunctionMutation,
|
||||
ExecuteOneServerlessFunctionMutationVariables
|
||||
>(EXECUTE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const executeOneServerlessFunction = async (
|
||||
input: ExecuteServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
});
|
||||
};
|
||||
return { executeOneServerlessFunction };
|
||||
};
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import {
|
||||
type GetManyServerlessFunctionsQuery,
|
||||
type GetManyServerlessFunctionsQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetManyServerlessFunctions = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
|
||||
const { data, loading, error } = useQuery<
|
||||
GetManyServerlessFunctionsQuery,
|
||||
GetManyServerlessFunctionsQueryVariables
|
||||
>(FIND_MANY_SERVERLESS_FUNCTIONS, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
});
|
||||
|
||||
return {
|
||||
serverlessFunctions: data?.findManyServerlessFunctions || [],
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/queries/findOneServerlessFunction';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import {
|
||||
type GetOneServerlessFunctionQuery,
|
||||
type GetOneServerlessFunctionQueryVariables,
|
||||
type ServerlessFunctionIdInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetOneServerlessFunction = ({
|
||||
id,
|
||||
onCompleted,
|
||||
}: ServerlessFunctionIdInput & {
|
||||
onCompleted?: (data: GetOneServerlessFunctionQuery) => void;
|
||||
}) => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { data, loading } = useQuery<
|
||||
GetOneServerlessFunctionQuery,
|
||||
GetOneServerlessFunctionQueryVariables
|
||||
>(FIND_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
variables: {
|
||||
input: { id },
|
||||
},
|
||||
onCompleted,
|
||||
});
|
||||
return {
|
||||
serverlessFunction: data?.findOneServerlessFunction || null,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE } from '@/settings/serverless-functions/graphql/queries/findOneServerlessFunctionSourceCode';
|
||||
import {
|
||||
type FindOneServerlessFunctionSourceCodeQuery,
|
||||
type FindOneServerlessFunctionSourceCodeQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetOneServerlessFunctionSourceCode = ({
|
||||
id,
|
||||
version,
|
||||
onCompleted,
|
||||
}: {
|
||||
id: string;
|
||||
version: string;
|
||||
onCompleted?: (data: FindOneServerlessFunctionSourceCodeQuery) => void;
|
||||
}) => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { data, loading } = useQuery<
|
||||
FindOneServerlessFunctionSourceCodeQuery,
|
||||
FindOneServerlessFunctionSourceCodeQueryVariables
|
||||
>(FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
variables: {
|
||||
input: { id, version },
|
||||
},
|
||||
onCompleted,
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
return { code: data?.getServerlessFunctionSourceCode, loading };
|
||||
};
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { CREATE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/createOneServerlessFunction';
|
||||
import { DELETE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/deleteOneServerlessFunction';
|
||||
import { UPDATE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/updateOneServerlessFunction';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
import { FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE } from '@/settings/serverless-functions/graphql/queries/findOneServerlessFunctionSourceCode';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ApolloError, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import {
|
||||
type CreateOneServerlessFunctionItemMutation,
|
||||
type CreateOneServerlessFunctionItemMutationVariables,
|
||||
type DeleteOneServerlessFunctionMutation,
|
||||
type DeleteOneServerlessFunctionMutationVariables,
|
||||
type UpdateOneServerlessFunctionMutation,
|
||||
type UpdateOneServerlessFunctionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePersistServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const [createServerlessFunctionMutation] = useMutation<
|
||||
CreateOneServerlessFunctionItemMutation,
|
||||
CreateOneServerlessFunctionItemMutationVariables
|
||||
>(CREATE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const [updateServerlessFunctionMutation] = useMutation<
|
||||
UpdateOneServerlessFunctionMutation,
|
||||
UpdateOneServerlessFunctionMutationVariables
|
||||
>(UPDATE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const [deleteServerlessFunctionMutation] = useMutation<
|
||||
DeleteOneServerlessFunctionMutation,
|
||||
DeleteOneServerlessFunctionMutationVariables
|
||||
>(DELETE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const createServerlessFunction = useCallback(
|
||||
async (
|
||||
variables: CreateOneServerlessFunctionItemMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof createServerlessFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await createServerlessFunctionMutation({
|
||||
variables,
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_MANY_SERVERLESS_FUNCTIONS) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
createServerlessFunctionMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const updateServerlessFunction = useCallback(
|
||||
async (
|
||||
variables: UpdateOneServerlessFunctionMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateServerlessFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await updateServerlessFunctionMutation({
|
||||
variables,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
updateServerlessFunctionMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const deleteServerlessFunction = useCallback(
|
||||
async (
|
||||
variables: DeleteOneServerlessFunctionMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteServerlessFunctionMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const result = await deleteServerlessFunctionMutation({
|
||||
variables,
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
deleteServerlessFunctionMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
createServerlessFunction,
|
||||
updateServerlessFunction,
|
||||
deleteServerlessFunction,
|
||||
};
|
||||
};
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { PUBLISH_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/publishOneServerlessFunction';
|
||||
import { FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE } from '@/settings/serverless-functions/graphql/queries/findOneServerlessFunctionSourceCode';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import {
|
||||
type PublishOneServerlessFunctionMutation,
|
||||
type PublishOneServerlessFunctionMutationVariables,
|
||||
type PublishServerlessFunctionInput,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePublishOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloCoreClient();
|
||||
const [mutate] = useMutation<
|
||||
PublishOneServerlessFunctionMutation,
|
||||
PublishOneServerlessFunctionMutationVariables
|
||||
>(PUBLISH_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient,
|
||||
});
|
||||
|
||||
const publishOneServerlessFunction = async (
|
||||
input: PublishServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [
|
||||
getOperationName(FIND_ONE_SERVERLESS_FUNCTION_SOURCE_CODE) ?? '',
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
return { publishOneServerlessFunction };
|
||||
};
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
import { flattenSources } from '@/serverless-functions/utils/flattenSources';
|
||||
import { getFunctionInputFromSourceCode } from '@/serverless-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { useGetOneServerlessFunction } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunction';
|
||||
import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { type Dispatch, type SetStateAction, useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { type Sources } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type FindOneServerlessFunctionSourceCodeQuery,
|
||||
type GetOneServerlessFunctionQuery,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { type ServerlessFunction } from '~/generated/graphql';
|
||||
|
||||
export type ServerlessFunctionNewFormValues = {
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type ServerlessFunctionFormValues = ServerlessFunctionNewFormValues & {
|
||||
code: Sources;
|
||||
};
|
||||
|
||||
type SetServerlessFunctionFormValues = Dispatch<
|
||||
SetStateAction<ServerlessFunctionFormValues>
|
||||
>;
|
||||
|
||||
export const useServerlessFunctionUpdateFormState = ({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion = 'draft',
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
serverlessFunctionVersion?: string;
|
||||
}): {
|
||||
formValues: ServerlessFunctionFormValues;
|
||||
serverlessFunction: ServerlessFunction | null;
|
||||
setFormValues: SetServerlessFunctionFormValues;
|
||||
loading: boolean;
|
||||
} => {
|
||||
const [formValues, setFormValues] = useState<ServerlessFunctionFormValues>({
|
||||
name: '',
|
||||
description: '',
|
||||
code: { src: { 'index.ts': '' } },
|
||||
});
|
||||
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
|
||||
const { serverlessFunction, loading: serverlessFunctionLoading } =
|
||||
useGetOneServerlessFunction({
|
||||
id: serverlessFunctionId,
|
||||
onCompleted: (data: GetOneServerlessFunctionQuery) => {
|
||||
const fn = data?.findOneServerlessFunction;
|
||||
|
||||
if (isDefined(fn)) {
|
||||
setFormValues((prevState) => ({
|
||||
...prevState,
|
||||
name: fn.name || '',
|
||||
description: fn.description || '',
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { loading: serverlessFunctionSourceCodeLoading } =
|
||||
useGetOneServerlessFunctionSourceCode({
|
||||
id: serverlessFunctionId,
|
||||
version: serverlessFunctionVersion,
|
||||
onCompleted: async (data: FindOneServerlessFunctionSourceCodeQuery) => {
|
||||
const code = data?.getServerlessFunctionSourceCode;
|
||||
|
||||
setFormValues((prevState) => ({
|
||||
...prevState,
|
||||
code: code || prevState.code,
|
||||
}));
|
||||
|
||||
if (serverlessFunctionTestData.shouldInitInput) {
|
||||
const flattenedCode = flattenSources(code);
|
||||
|
||||
const sourceCode = flattenedCode.find(
|
||||
(flatCode) =>
|
||||
flatCode.path === serverlessFunction?.sourceHandlerPath,
|
||||
);
|
||||
|
||||
if (isDefined(sourceCode)) {
|
||||
const functionInput = await getFunctionInputFromSourceCode(
|
||||
sourceCode.content,
|
||||
);
|
||||
|
||||
setServerlessFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
input: functionInput,
|
||||
shouldInitInput: false,
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
formValues,
|
||||
setFormValues,
|
||||
serverlessFunction,
|
||||
loading: serverlessFunctionSourceCodeLoading || serverlessFunctionLoading,
|
||||
};
|
||||
};
|
||||
+27
-27
@@ -54,9 +54,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -73,9 +73,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -133,9 +133,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -152,9 +152,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -200,9 +200,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -219,9 +219,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -267,9 +267,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -286,9 +286,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -305,9 +305,9 @@ describe('generateWorkflowDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
|
||||
+39
-39
@@ -35,9 +35,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -54,9 +54,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -73,9 +73,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -272,9 +272,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -291,9 +291,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -310,9 +310,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -511,9 +511,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -530,9 +530,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -549,9 +549,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -750,9 +750,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -769,9 +769,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -788,9 +788,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
@@ -807,9 +807,9 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
|
||||
+3
-3
@@ -126,9 +126,9 @@ describe('getWorkflowVersionDiagram', () => {
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import {
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow';
|
||||
import { WorkflowEditActionAiAgent } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent';
|
||||
import { WorkflowActionServerlessFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowActionServerlessFunction';
|
||||
import { WorkflowActionLogicFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowActionLogicFunction';
|
||||
import { WorkflowEditActionCreateRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionCreateRecord';
|
||||
import { WorkflowEditActionDeleteRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionDeleteRecord';
|
||||
import { WorkflowEditActionEmpty } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmpty';
|
||||
@@ -106,7 +106,7 @@ export const WorkflowRunStepNodeDetail = ({
|
||||
switch (stepDefinition.definition.type) {
|
||||
case 'CODE': {
|
||||
return (
|
||||
<WorkflowActionServerlessFunction
|
||||
<WorkflowActionLogicFunction
|
||||
key={stepId}
|
||||
action={stepDefinition.definition}
|
||||
actionOptions={{
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import {
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow';
|
||||
import { WorkflowEditActionAiAgent } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent';
|
||||
import { WorkflowActionServerlessFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowActionServerlessFunction';
|
||||
import { WorkflowActionLogicFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowActionLogicFunction';
|
||||
import { WorkflowEditActionCreateRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionCreateRecord';
|
||||
import { WorkflowEditActionDeleteRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionDeleteRecord';
|
||||
import { WorkflowEditActionEmpty } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmpty';
|
||||
@@ -108,7 +108,7 @@ export const WorkflowStepDetail = ({
|
||||
switch (stepDefinition.definition.type) {
|
||||
case 'CODE': {
|
||||
return (
|
||||
<WorkflowActionServerlessFunction
|
||||
<WorkflowActionLogicFunction
|
||||
key={stepId}
|
||||
action={stepDefinition.definition}
|
||||
actionOptions={props}
|
||||
|
||||
+3
-3
@@ -41,9 +41,9 @@ describe('useUpdateStep', () => {
|
||||
type: 'CODE' as const,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'id',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'id',
|
||||
logicFunctionVersion: '1',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+9
-9
@@ -28,9 +28,9 @@ describe('getIsDescendantOfIterator', () => {
|
||||
nextStepIds: ['iterator1'],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func2',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func2',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -48,9 +48,9 @@ describe('getIsDescendantOfIterator', () => {
|
||||
nextStepIds: [],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func3',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func3',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -89,9 +89,9 @@ describe('getIsDescendantOfIterator', () => {
|
||||
nextStepIds: [],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func4',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func4',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+3
-3
@@ -27,9 +27,9 @@ describe('getStepInfoHistoryItem', () => {
|
||||
nextStepIds: [],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+12
-12
@@ -12,9 +12,9 @@ describe('getWorkflowPreviousSteps', () => {
|
||||
nextStepIds: ['step2', 'step3'],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func1',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func1',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -31,9 +31,9 @@ describe('getWorkflowPreviousSteps', () => {
|
||||
nextStepIds: ['step4'],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func2',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func2',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -50,9 +50,9 @@ describe('getWorkflowPreviousSteps', () => {
|
||||
nextStepIds: ['step4'],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func3',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func3',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -69,9 +69,9 @@ describe('getWorkflowPreviousSteps', () => {
|
||||
nextStepIds: [],
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'func4',
|
||||
serverlessFunctionVersion: '1.0.0',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: 'func4',
|
||||
logicFunctionVersion: '1.0.0',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+12
-12
@@ -17,9 +17,9 @@ const mockFlow = {
|
||||
valid: true,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionInput: {},
|
||||
serverlessFunctionVersion: '',
|
||||
logicFunctionId: '',
|
||||
logicFunctionInput: {},
|
||||
logicFunctionVersion: '',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -36,9 +36,9 @@ const mockFlow = {
|
||||
valid: true,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionInput: {},
|
||||
serverlessFunctionVersion: '',
|
||||
logicFunctionId: '',
|
||||
logicFunctionInput: {},
|
||||
logicFunctionVersion: '',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -139,9 +139,9 @@ describe('getWorkflowRunStepContext', () => {
|
||||
valid: true,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionInput: {},
|
||||
serverlessFunctionVersion: '',
|
||||
logicFunctionId: '',
|
||||
logicFunctionInput: {},
|
||||
logicFunctionVersion: '',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -176,9 +176,9 @@ describe('getWorkflowRunStepContext', () => {
|
||||
valid: true,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionInput: {},
|
||||
serverlessFunctionVersion: '',
|
||||
logicFunctionId: '',
|
||||
logicFunctionInput: {},
|
||||
logicFunctionVersion: '',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+16
-20
@@ -21,18 +21,17 @@ describe('getWorkflowRunStepExecutionStatus', () => {
|
||||
steps: [
|
||||
{
|
||||
id: stepId,
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId:
|
||||
'5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
logicFunctionInput: {
|
||||
a: null,
|
||||
b: null,
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {
|
||||
link: {
|
||||
@@ -87,18 +86,17 @@ describe('getWorkflowRunStepExecutionStatus', () => {
|
||||
steps: [
|
||||
{
|
||||
id: stepId,
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId:
|
||||
'5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
logicFunctionInput: {
|
||||
a: null,
|
||||
b: null,
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {
|
||||
link: {
|
||||
@@ -154,18 +152,17 @@ describe('getWorkflowRunStepExecutionStatus', () => {
|
||||
steps: [
|
||||
{
|
||||
id: stepId,
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId:
|
||||
'5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
logicFunctionInput: {
|
||||
a: null,
|
||||
b: null,
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {
|
||||
link: {
|
||||
@@ -188,18 +185,17 @@ describe('getWorkflowRunStepExecutionStatus', () => {
|
||||
},
|
||||
{
|
||||
id: secondStepId,
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId:
|
||||
'5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c',
|
||||
logicFunctionInput: {
|
||||
a: null,
|
||||
b: null,
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {
|
||||
link: {
|
||||
|
||||
+12
-12
@@ -5,16 +5,16 @@ describe('getWorkflowVariablesUsedInStep', () => {
|
||||
it('returns the variables used in a one-level object', () => {
|
||||
const step: WorkflowStep = {
|
||||
id: '42e8b60e-dd44-417a-875f-823d63f16819',
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
logicFunctionInput: {
|
||||
a: '{{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a.b.c.d}}',
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -97,16 +97,16 @@ Set {
|
||||
it('returns all the variables used in a single field', () => {
|
||||
const step: WorkflowStep = {
|
||||
id: '42e8b60e-dd44-417a-875f-823d63f16819',
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
logicFunctionInput: {
|
||||
a: '{{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.b}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.c}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.d}}',
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -137,16 +137,16 @@ Set {
|
||||
it('returns the variables used many times only once', () => {
|
||||
const step: WorkflowStep = {
|
||||
id: '42e8b60e-dd44-417a-875f-823d63f16819',
|
||||
name: 'Code - Serverless Function',
|
||||
name: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: '5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2d',
|
||||
logicFunctionInput: {
|
||||
a: '{{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a}} {{5f7b9b44-bb07-41ba-aef8-ec0eaa5eea2c.a}}',
|
||||
},
|
||||
serverlessFunctionVersion: 'draft',
|
||||
logicFunctionVersion: 'draft',
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
|
||||
+11
-11
@@ -2,7 +2,7 @@ import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { RightDrawerSkeletonLoader } from '~/loading/components/RightDrawerSkeletonLoader';
|
||||
|
||||
type WorkflowActionServerlessFunctionProps = {
|
||||
type WorkflowActionLogicFunctionProps = {
|
||||
action: WorkflowCodeAction;
|
||||
actionOptions:
|
||||
| {
|
||||
@@ -14,32 +14,32 @@ type WorkflowActionServerlessFunctionProps = {
|
||||
};
|
||||
};
|
||||
|
||||
const WorkflowEditActionServerlessFunction = lazy(() =>
|
||||
const WorkflowEditActionLogicFunction = lazy(() =>
|
||||
import(
|
||||
'@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionServerlessFunction'
|
||||
'@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionLogicFunction'
|
||||
).then((module) => ({
|
||||
default: module.WorkflowEditActionServerlessFunction,
|
||||
default: module.WorkflowEditActionLogicFunction,
|
||||
})),
|
||||
);
|
||||
|
||||
const WorkflowReadonlyActionServerlessFunction = lazy(() =>
|
||||
const WorkflowReadonlyActionLogicFunction = lazy(() =>
|
||||
import(
|
||||
'@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowReadonlyActionServerlessFunction'
|
||||
'@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowReadonlyActionLogicFunction'
|
||||
).then((module) => ({
|
||||
default: module.WorkflowReadonlyActionServerlessFunction,
|
||||
default: module.WorkflowReadonlyActionLogicFunction,
|
||||
})),
|
||||
);
|
||||
|
||||
export const WorkflowActionServerlessFunction = ({
|
||||
export const WorkflowActionLogicFunction = ({
|
||||
action,
|
||||
actionOptions,
|
||||
}: WorkflowActionServerlessFunctionProps) => {
|
||||
}: WorkflowActionLogicFunctionProps) => {
|
||||
return (
|
||||
<Suspense fallback={<RightDrawerSkeletonLoader />}>
|
||||
{actionOptions.readonly ? (
|
||||
<WorkflowReadonlyActionServerlessFunction action={action} />
|
||||
<WorkflowReadonlyActionLogicFunction action={action} />
|
||||
) : (
|
||||
<WorkflowEditActionServerlessFunction
|
||||
<WorkflowEditActionLogicFunction
|
||||
action={action}
|
||||
actionOptions={actionOptions}
|
||||
/>
|
||||
+71
-67
@@ -1,5 +1,8 @@
|
||||
import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages';
|
||||
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { useGetAvailablePackages } from '@/settings/logic-functions/hooks/useGetAvailablePackages';
|
||||
import {
|
||||
type LogicFunctionFormValues,
|
||||
useLogicFunctionUpdateFormState,
|
||||
} from '@/settings/logic-functions/hooks/useLogicFunctionUpdateFormState';
|
||||
import { useFullScreenModal } from '@/ui/layout/fullscreen/hooks/useFullScreenModal';
|
||||
import { type BreadcrumbProps } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
@@ -9,11 +12,11 @@ import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
import { setNestedValue } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/setNestedValue';
|
||||
|
||||
import { CmdEnterActionButton } from '@/action-menu/components/CmdEnterActionButton';
|
||||
import { ServerlessFunctionExecutionResult } from '@/serverless-functions/components/ServerlessFunctionExecutionResult';
|
||||
import { INDEX_FILE_NAME } from '@/serverless-functions/constants/IndexFileName';
|
||||
import { useTestServerlessFunction } from '@/serverless-functions/hooks/useTestServerlessFunction';
|
||||
import { getFunctionInputFromSourceCode } from '@/serverless-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { mergeDefaultFunctionInputAndFunctionInput } from '@/serverless-functions/utils/mergeDefaultFunctionInputAndFunctionInput';
|
||||
import { LogicFunctionExecutionResult } from '@/logic-functions/components/LogicFunctionExecutionResult';
|
||||
import { INDEX_FILE_NAME } from '@/logic-functions/constants/IndexFileName';
|
||||
import { useTestLogicFunction } from '@/logic-functions/hooks/useTestLogicFunction';
|
||||
import { getFunctionInputFromSourceCode } from '@/logic-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { mergeDefaultFunctionInputAndFunctionInput } from '@/logic-functions/utils/mergeDefaultFunctionInputAndFunctionInput';
|
||||
import { InputLabel } from '@/ui/input/components/InputLabel';
|
||||
import { TextArea } from '@/ui/input/components/TextArea';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
@@ -22,19 +25,22 @@ import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotke
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowEditActionServerlessFunctionFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionServerlessFunctionFields';
|
||||
import { WorkflowServerlessFunctionCodeEditor } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowServerlessFunctionCodeEditor';
|
||||
import { WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowServerlessFunctionTabListComponentId';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { WorkflowServerlessFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowServerlessFunctionTabId';
|
||||
import { WorkflowEditActionLogicFunctionFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionLogicFunctionFields';
|
||||
import { WorkflowLogicFunctionCodeEditor } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowLogicFunctionCodeEditor';
|
||||
import { WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowLogicFunctionTabListComponentId';
|
||||
import {
|
||||
type LogicFunctionTestData,
|
||||
logicFunctionTestDataFamilyState,
|
||||
} from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
|
||||
import { WorkflowLogicFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowLogicFunctionTabId';
|
||||
import { getWrongExportedFunctionMarkers } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/getWrongExportedFunctionMarkers';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
import { SOURCE_FOLDER_NAME } from '@/serverless-functions/constants/SourceFolderName';
|
||||
import { computeNewSources } from '@/serverless-functions/utils/computeNewSources';
|
||||
import { usePersistServerlessFunction } from '@/settings/serverless-functions/hooks/usePersistServerlessFunction';
|
||||
import { SOURCE_FOLDER_NAME } from '@/logic-functions/constants/SourceFolderName';
|
||||
import { computeNewSources } from '@/logic-functions/utils/computeNewSources';
|
||||
import { usePersistLogicFunction } from '@/settings/logic-functions/hooks/usePersistLogicFunction';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { CODE_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/CodeAction';
|
||||
import { type Monaco } from '@monaco-editor/react';
|
||||
@@ -71,7 +77,7 @@ const StyledFullScreenCodeEditorContainer = styled.div`
|
||||
min-height: 0;
|
||||
`;
|
||||
|
||||
type WorkflowEditActionServerlessFunctionProps = {
|
||||
type WorkflowEditActionLogicFunctionProps = {
|
||||
action: WorkflowCodeAction;
|
||||
actionOptions:
|
||||
| {
|
||||
@@ -83,24 +89,24 @@ type WorkflowEditActionServerlessFunctionProps = {
|
||||
};
|
||||
};
|
||||
|
||||
type ServerlessFunctionInputFormData = {
|
||||
[field: string]: string | ServerlessFunctionInputFormData;
|
||||
type LogicFunctionInputFormData = {
|
||||
[field: string]: string | LogicFunctionInputFormData;
|
||||
};
|
||||
|
||||
export const WorkflowEditActionServerlessFunction = ({
|
||||
export const WorkflowEditActionLogicFunction = ({
|
||||
action,
|
||||
actionOptions,
|
||||
}: WorkflowEditActionServerlessFunctionProps) => {
|
||||
}: WorkflowEditActionLogicFunctionProps) => {
|
||||
const { t } = useLingui();
|
||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||
const isMobile = useIsMobile();
|
||||
const serverlessFunctionId = action.settings.input.serverlessFunctionId;
|
||||
const fullScreenFocusId = `code-editor-fullscreen-${serverlessFunctionId}`;
|
||||
const logicFunctionId = action.settings.input.logicFunctionId;
|
||||
const fullScreenFocusId = `code-editor-fullscreen-${logicFunctionId}`;
|
||||
const activeTabId = useRecoilComponentValue(
|
||||
activeTabIdComponentState,
|
||||
WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
);
|
||||
const { updateServerlessFunction } = usePersistServerlessFunction();
|
||||
const { updateLogicFunction } = usePersistLogicFunction();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
@@ -109,21 +115,23 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowVisualizerWorkflowId);
|
||||
const { availablePackages } = useGetAvailablePackages({
|
||||
id: serverlessFunctionId,
|
||||
id: logicFunctionId,
|
||||
});
|
||||
|
||||
const [serverlessFunctionTestData, setServerlessFunctionTestData] =
|
||||
useRecoilState(serverlessFunctionTestDataFamilyState(serverlessFunctionId));
|
||||
const [logicFunctionTestData, setLogicFunctionTestData] =
|
||||
useRecoilState<LogicFunctionTestData>(
|
||||
logicFunctionTestDataFamilyState(logicFunctionId),
|
||||
);
|
||||
|
||||
const [functionInput, setFunctionInput] =
|
||||
useState<ServerlessFunctionInputFormData>(
|
||||
action.settings.input.serverlessFunctionInput,
|
||||
useState<LogicFunctionInputFormData>(
|
||||
action.settings.input.logicFunctionInput,
|
||||
);
|
||||
|
||||
const { formValues, setFormValues, loading } =
|
||||
useServerlessFunctionUpdateFormState({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion: 'draft',
|
||||
useLogicFunctionUpdateFormState({
|
||||
logicFunctionId,
|
||||
logicFunctionVersion: 'draft',
|
||||
});
|
||||
|
||||
const updateOutputSchemaFromTestResult = async (testResult: object) => {
|
||||
@@ -137,15 +145,15 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
});
|
||||
};
|
||||
|
||||
const { testServerlessFunction, isTesting } = useTestServerlessFunction({
|
||||
serverlessFunctionId,
|
||||
const { testLogicFunction, isTesting } = useTestLogicFunction({
|
||||
logicFunctionId,
|
||||
callback: updateOutputSchemaFromTestResult,
|
||||
});
|
||||
|
||||
const handleSave = useDebouncedCallback(async () => {
|
||||
await updateServerlessFunction({
|
||||
await updateLogicFunction({
|
||||
input: {
|
||||
id: serverlessFunctionId,
|
||||
id: logicFunctionId,
|
||||
update: {
|
||||
name: formValues.name,
|
||||
description: formValues.description,
|
||||
@@ -159,7 +167,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
if (actionOptions.readonly === true) {
|
||||
return;
|
||||
}
|
||||
setFormValues((prevState) => {
|
||||
setFormValues((prevState: LogicFunctionFormValues) => {
|
||||
return {
|
||||
...prevState,
|
||||
code: computeNewSources({
|
||||
@@ -186,15 +194,15 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
const newFunctionInput = await getFunctionInputFromSourceCode(sourceCode);
|
||||
const newMergedInput = mergeDefaultFunctionInputAndFunctionInput({
|
||||
newInput: newFunctionInput,
|
||||
oldInput: action.settings.input.serverlessFunctionInput,
|
||||
oldInput: action.settings.input.logicFunctionInput,
|
||||
});
|
||||
const newMergedTestInput = mergeDefaultFunctionInputAndFunctionInput({
|
||||
newInput: newFunctionInput,
|
||||
oldInput: serverlessFunctionTestData.input,
|
||||
oldInput: logicFunctionTestData.input,
|
||||
});
|
||||
|
||||
setFunctionInput(newMergedInput);
|
||||
setServerlessFunctionTestData((prev) => ({
|
||||
setLogicFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
input: newMergedTestInput,
|
||||
}));
|
||||
@@ -214,7 +222,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
},
|
||||
input: {
|
||||
...action.settings.input,
|
||||
serverlessFunctionInput: newMergedInput,
|
||||
logicFunctionInput: newMergedInput,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -233,7 +241,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
...action.settings,
|
||||
input: {
|
||||
...action.settings.input,
|
||||
serverlessFunctionInput: updatedFunctionInput,
|
||||
logicFunctionInput: updatedFunctionInput,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -245,11 +253,11 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
}
|
||||
|
||||
const updatedTestFunctionInput = setNestedValue(
|
||||
serverlessFunctionTestData.input,
|
||||
logicFunctionTestData.input,
|
||||
path,
|
||||
value,
|
||||
);
|
||||
setServerlessFunctionTestData((prev) => ({
|
||||
setLogicFunctionTestData((prev) => ({
|
||||
...prev,
|
||||
input: updatedTestFunctionInput,
|
||||
}));
|
||||
@@ -261,7 +269,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
}
|
||||
|
||||
if (!isTesting) {
|
||||
await testServerlessFunction();
|
||||
await testLogicFunction();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -302,19 +310,19 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
id: WorkflowServerlessFunctionTabId.CODE,
|
||||
id: WorkflowLogicFunctionTabId.CODE,
|
||||
title: t`Code`,
|
||||
Icon: IconCode,
|
||||
},
|
||||
{
|
||||
id: WorkflowServerlessFunctionTabId.TEST,
|
||||
id: WorkflowLogicFunctionTabId.TEST,
|
||||
title: t`Test`,
|
||||
Icon: IconPlayerPlay,
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
setFunctionInput(action.settings.input.serverlessFunctionInput);
|
||||
setFunctionInput(action.settings.input.logicFunctionInput);
|
||||
}, [action]);
|
||||
|
||||
useHotkeysOnFocusedElement({
|
||||
@@ -328,7 +336,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
dependencies: [isFullScreen],
|
||||
});
|
||||
|
||||
const testLogsTextAreaId = `${serverlessFunctionId}-test-logs`;
|
||||
const testLogsTextAreaId = `${logicFunctionId}-test-logs`;
|
||||
|
||||
const breadcrumbLinks: BreadcrumbProps['links'] = [
|
||||
{
|
||||
@@ -358,7 +366,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
handleExitFullScreen();
|
||||
}
|
||||
},
|
||||
listenerId: `full-screen-overlay-${serverlessFunctionId}`,
|
||||
listenerId: `full-screen-overlay-${logicFunctionId}`,
|
||||
enabled: isFullScreen,
|
||||
});
|
||||
|
||||
@@ -383,7 +391,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
|
||||
const fullScreenOverlay = renderFullScreenModal(
|
||||
<div data-globally-prevent-click-outside="true">
|
||||
<WorkflowEditActionServerlessFunctionFields
|
||||
<WorkflowEditActionLogicFunctionFields
|
||||
functionInput={functionInput}
|
||||
VariablePicker={WorkflowVariablePicker}
|
||||
onInputChange={handleInputChange}
|
||||
@@ -415,20 +423,18 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
<StyledTabList
|
||||
tabs={tabs}
|
||||
behaveAsLinks={false}
|
||||
componentInstanceId={
|
||||
WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID
|
||||
}
|
||||
componentInstanceId={WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
{activeTabId === WorkflowServerlessFunctionTabId.CODE && (
|
||||
{activeTabId === WorkflowLogicFunctionTabId.CODE && (
|
||||
<>
|
||||
<WorkflowEditActionServerlessFunctionFields
|
||||
<WorkflowEditActionLogicFunctionFields
|
||||
functionInput={functionInput}
|
||||
VariablePicker={WorkflowVariablePicker}
|
||||
onInputChange={handleInputChange}
|
||||
readonly={actionOptions.readonly}
|
||||
/>
|
||||
<WorkflowServerlessFunctionCodeEditor
|
||||
<WorkflowLogicFunctionCodeEditor
|
||||
value={indexFileContent}
|
||||
onChange={handleCodeChange}
|
||||
onMount={handleEditorDidMount}
|
||||
@@ -444,28 +450,26 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{activeTabId === WorkflowServerlessFunctionTabId.TEST && (
|
||||
{activeTabId === WorkflowLogicFunctionTabId.TEST && (
|
||||
<>
|
||||
<WorkflowEditActionServerlessFunctionFields
|
||||
functionInput={serverlessFunctionTestData.input}
|
||||
<WorkflowEditActionLogicFunctionFields
|
||||
functionInput={logicFunctionTestData.input}
|
||||
onInputChange={handleTestInputChange}
|
||||
readonly={actionOptions.readonly}
|
||||
/>
|
||||
<StyledCodeEditorContainer>
|
||||
<InputLabel>{t`Result`}</InputLabel>
|
||||
<ServerlessFunctionExecutionResult
|
||||
serverlessFunctionTestData={serverlessFunctionTestData}
|
||||
<LogicFunctionExecutionResult
|
||||
logicFunctionTestData={logicFunctionTestData}
|
||||
isTesting={isTesting}
|
||||
/>
|
||||
</StyledCodeEditorContainer>
|
||||
{serverlessFunctionTestData.output.logs.length > 0 && (
|
||||
{logicFunctionTestData.output.logs.length > 0 && (
|
||||
<StyledCodeEditorContainer>
|
||||
<InputLabel>{t`Logs`}</InputLabel>
|
||||
<TextArea
|
||||
textAreaId={testLogsTextAreaId}
|
||||
value={
|
||||
isTesting ? '' : serverlessFunctionTestData.output.logs
|
||||
}
|
||||
value={isTesting ? '' : logicFunctionTestData.output.logs}
|
||||
maxRows={20}
|
||||
disabled
|
||||
/>
|
||||
@@ -478,7 +482,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
<WorkflowStepFooter
|
||||
stepId={action.id}
|
||||
additionalActions={
|
||||
activeTabId === WorkflowServerlessFunctionTabId.TEST
|
||||
activeTabId === WorkflowLogicFunctionTabId.TEST
|
||||
? [
|
||||
<CmdEnterActionButton
|
||||
title={t`Test`}
|
||||
+4
-4
@@ -18,7 +18,7 @@ const StyledContainer = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
type WorkflowEditActionServerlessFunctionFieldsProps = {
|
||||
type WorkflowEditActionLogicFunctionFieldsProps = {
|
||||
functionInput: FunctionInput;
|
||||
path?: string[];
|
||||
readonly?: boolean;
|
||||
@@ -26,13 +26,13 @@ type WorkflowEditActionServerlessFunctionFieldsProps = {
|
||||
VariablePicker?: VariablePickerComponent;
|
||||
};
|
||||
|
||||
export const WorkflowEditActionServerlessFunctionFields = ({
|
||||
export const WorkflowEditActionLogicFunctionFields = ({
|
||||
functionInput,
|
||||
path = [],
|
||||
readonly,
|
||||
onInputChange,
|
||||
VariablePicker,
|
||||
}: WorkflowEditActionServerlessFunctionFieldsProps) => {
|
||||
}: WorkflowEditActionLogicFunctionFieldsProps) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
{Object.entries(functionInput).map(([inputKey, inputValue]) => {
|
||||
@@ -44,7 +44,7 @@ export const WorkflowEditActionServerlessFunctionFields = ({
|
||||
<div key={pathKey}>
|
||||
<InputLabel>{inputKey}</InputLabel>
|
||||
<FormNestedFieldInputContainer>
|
||||
<WorkflowEditActionServerlessFunctionFields
|
||||
<WorkflowEditActionLogicFunctionFields
|
||||
functionInput={inputValue}
|
||||
path={currentPath}
|
||||
readonly={readonly}
|
||||
+3
-3
@@ -24,7 +24,7 @@ const StyledFullScreenButtonContainer = styled.div`
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
type WorkflowServerlessFunctionCodeEditorProps = {
|
||||
type WorkflowLogicFunctionCodeEditorProps = {
|
||||
value?: string;
|
||||
onChange: (value: string) => void;
|
||||
onMount: (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void;
|
||||
@@ -34,7 +34,7 @@ type WorkflowServerlessFunctionCodeEditorProps = {
|
||||
onEnterFullScreen?: () => void;
|
||||
};
|
||||
|
||||
export const WorkflowServerlessFunctionCodeEditor = ({
|
||||
export const WorkflowLogicFunctionCodeEditor = ({
|
||||
value,
|
||||
onChange,
|
||||
onMount,
|
||||
@@ -42,7 +42,7 @@ export const WorkflowServerlessFunctionCodeEditor = ({
|
||||
readonly = false,
|
||||
fullScreenMode = false,
|
||||
onEnterFullScreen,
|
||||
}: WorkflowServerlessFunctionCodeEditorProps) => {
|
||||
}: WorkflowLogicFunctionCodeEditorProps) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
+16
-17
@@ -1,41 +1,40 @@
|
||||
import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages';
|
||||
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { useGetAvailablePackages } from '@/settings/logic-functions/hooks/useGetAvailablePackages';
|
||||
import { useLogicFunctionUpdateFormState } from '@/settings/logic-functions/hooks/useLogicFunctionUpdateFormState';
|
||||
import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
|
||||
import { INDEX_FILE_NAME } from '@/serverless-functions/constants/IndexFileName';
|
||||
import { INDEX_FILE_NAME } from '@/logic-functions/constants/IndexFileName';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowEditActionServerlessFunctionFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionServerlessFunctionFields';
|
||||
import { WorkflowEditActionLogicFunctionFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionLogicFunctionFields';
|
||||
import { getWrongExportedFunctionMarkers } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/getWrongExportedFunctionMarkers';
|
||||
import styled from '@emotion/styled';
|
||||
import { type Monaco } from '@monaco-editor/react';
|
||||
import { type editor } from 'monaco-editor';
|
||||
import { AutoTypings } from 'monaco-editor-auto-typings';
|
||||
import { CodeEditor } from 'twenty-ui/input';
|
||||
import { SOURCE_FOLDER_NAME } from '@/serverless-functions/constants/SourceFolderName';
|
||||
import { SOURCE_FOLDER_NAME } from '@/logic-functions/constants/SourceFolderName';
|
||||
|
||||
const StyledCodeEditorContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
type WorkflowReadonlyActionServerlessFunctionProps = {
|
||||
type WorkflowReadonlyActionLogicFunctionProps = {
|
||||
action: WorkflowCodeAction;
|
||||
};
|
||||
|
||||
export const WorkflowReadonlyActionServerlessFunction = ({
|
||||
export const WorkflowReadonlyActionLogicFunction = ({
|
||||
action,
|
||||
}: WorkflowReadonlyActionServerlessFunctionProps) => {
|
||||
const serverlessFunctionId = action.settings.input.serverlessFunctionId;
|
||||
const serverlessFunctionVersion =
|
||||
action.settings.input.serverlessFunctionVersion;
|
||||
}: WorkflowReadonlyActionLogicFunctionProps) => {
|
||||
const logicFunctionId = action.settings.input.logicFunctionId;
|
||||
const logicFunctionVersion = action.settings.input.logicFunctionVersion;
|
||||
|
||||
const { availablePackages } = useGetAvailablePackages({
|
||||
id: serverlessFunctionId,
|
||||
id: logicFunctionId,
|
||||
});
|
||||
|
||||
const { formValues, loading } = useServerlessFunctionUpdateFormState({
|
||||
serverlessFunctionId,
|
||||
serverlessFunctionVersion,
|
||||
const { formValues, loading } = useLogicFunctionUpdateFormState({
|
||||
logicFunctionId,
|
||||
logicFunctionVersion,
|
||||
});
|
||||
|
||||
const handleEditorDidMount = async (
|
||||
@@ -64,8 +63,8 @@ export const WorkflowReadonlyActionServerlessFunction = ({
|
||||
return (
|
||||
<>
|
||||
<WorkflowStepBody>
|
||||
<WorkflowEditActionServerlessFunctionFields
|
||||
functionInput={action.settings.input.serverlessFunctionInput}
|
||||
<WorkflowEditActionLogicFunctionFields
|
||||
functionInput={action.settings.input.logicFunctionInput}
|
||||
readonly
|
||||
/>
|
||||
<StyledCodeEditorContainer>
|
||||
+19
-19
@@ -1,5 +1,5 @@
|
||||
import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowEditActionServerlessFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionServerlessFunction';
|
||||
import { WorkflowEditActionLogicFunction } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionLogicFunction';
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { graphql, HttpResponse } from 'msw';
|
||||
import { fn } from 'storybook/test';
|
||||
@@ -19,9 +19,9 @@ const DEFAULT_ACTION: WorkflowCodeAction = {
|
||||
valid: false,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionVersion: 'draft',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: '',
|
||||
logicFunctionVersion: 'draft',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -42,9 +42,9 @@ const CONFIGURED_ACTION: WorkflowCodeAction = {
|
||||
valid: true,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'test-function-id',
|
||||
serverlessFunctionVersion: 'draft',
|
||||
serverlessFunctionInput: {
|
||||
logicFunctionId: 'test-function-id',
|
||||
logicFunctionVersion: 'draft',
|
||||
logicFunctionInput: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
score: 95,
|
||||
@@ -75,21 +75,21 @@ const CONFIGURED_ACTION: WorkflowCodeAction = {
|
||||
},
|
||||
};
|
||||
|
||||
const meta: Meta<typeof WorkflowEditActionServerlessFunction> = {
|
||||
const meta: Meta<typeof WorkflowEditActionLogicFunction> = {
|
||||
title: 'Modules/Workflow/Actions/Code/EditAction',
|
||||
component: WorkflowEditActionServerlessFunction,
|
||||
component: WorkflowEditActionLogicFunction,
|
||||
parameters: {
|
||||
msw: {
|
||||
handlers: [
|
||||
...graphqlMocks.handlers,
|
||||
graphql.query('FindManyServerlessFunctions', () => {
|
||||
graphql.query('GetManyLogicFunctions', () => {
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
findManyServerlessFunctions: [
|
||||
findManyLogicFunctions: [
|
||||
{
|
||||
id: 'test-function-id',
|
||||
name: 'Test Function',
|
||||
description: 'A test serverless function',
|
||||
description: 'A test logic function',
|
||||
runtime: 'nodejs22.x',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
@@ -98,13 +98,13 @@ const meta: Meta<typeof WorkflowEditActionServerlessFunction> = {
|
||||
},
|
||||
});
|
||||
}),
|
||||
graphql.query('FindOneServerlessFunction', () => {
|
||||
graphql.query('GetOneLogicFunction', () => {
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
findOneServerlessFunction: {
|
||||
findOneLogicFunction: {
|
||||
id: 'test-function-id',
|
||||
name: 'Test Function',
|
||||
description: 'A test serverless function',
|
||||
description: 'A test logic function',
|
||||
runtime: 'nodejs22.x',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
@@ -138,7 +138,7 @@ const meta: Meta<typeof WorkflowEditActionServerlessFunction> = {
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof WorkflowEditActionServerlessFunction>;
|
||||
type Story = StoryObj<typeof WorkflowEditActionLogicFunction>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
@@ -207,9 +207,9 @@ export const EmptyFunction: Story = {
|
||||
settings: {
|
||||
...DEFAULT_ACTION.settings,
|
||||
input: {
|
||||
serverlessFunctionId: '',
|
||||
serverlessFunctionVersion: 'draft',
|
||||
serverlessFunctionInput: {},
|
||||
logicFunctionId: '',
|
||||
logicFunctionVersion: 'draft',
|
||||
logicFunctionInput: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export const WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID =
|
||||
'workflow-logic-function-tab-list-component-id';
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export const WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID =
|
||||
'workflow-serverless-function-tab-list-component-id';
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
||||
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
import { LogicFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
export type ServerlessFunctionTestData = {
|
||||
export type LogicFunctionTestData = {
|
||||
input: { [field: string]: any };
|
||||
shouldInitInput: boolean;
|
||||
output: {
|
||||
data?: string;
|
||||
logs: string;
|
||||
duration?: number;
|
||||
status?: ServerlessFunctionExecutionStatus;
|
||||
status?: LogicFunctionExecutionStatus;
|
||||
error?: string;
|
||||
};
|
||||
language: 'plaintext' | 'json';
|
||||
@@ -18,14 +18,14 @@ export type ServerlessFunctionTestData = {
|
||||
export const DEFAULT_OUTPUT_VALUE = {
|
||||
data: 'Enter an input above then press "Test"',
|
||||
logs: '',
|
||||
status: ServerlessFunctionExecutionStatus.IDLE,
|
||||
status: LogicFunctionExecutionStatus.IDLE,
|
||||
};
|
||||
|
||||
export const serverlessFunctionTestDataFamilyState = createFamilyState<
|
||||
ServerlessFunctionTestData,
|
||||
export const logicFunctionTestDataFamilyState = createFamilyState<
|
||||
LogicFunctionTestData,
|
||||
string
|
||||
>({
|
||||
key: 'serverlessFunctionTestDataFamilyState',
|
||||
key: 'logicFunctionTestDataFamilyState',
|
||||
defaultValue: {
|
||||
language: 'plaintext',
|
||||
height: 64,
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export type WorkflowLogicFunctionTabIdType = 'code' | 'test';
|
||||
|
||||
export enum WorkflowLogicFunctionTabId {
|
||||
CODE = 'code',
|
||||
TEST = 'test',
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
export type WorkflowServerlessFunctionTabIdType = 'code' | 'test';
|
||||
|
||||
export enum WorkflowServerlessFunctionTabId {
|
||||
CODE = 'code',
|
||||
TEST = 'test',
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ export const CODE_ACTION: {
|
||||
type: Extract<WorkflowActionType, 'CODE'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Code - Serverless Function',
|
||||
defaultLabel: 'Code - Logic Function',
|
||||
type: 'CODE',
|
||||
icon: 'IconCode',
|
||||
};
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ export const useVariableDropdown = ({
|
||||
);
|
||||
const setActiveTabId = useSetRecoilComponentState(
|
||||
activeTabIdComponentState,
|
||||
'workflow-serverless-function-tab-list-component-id',
|
||||
'workflow-logic-function-tab-list-component-id',
|
||||
);
|
||||
const setWorkflowDiagram = useSetRecoilComponentState(
|
||||
workflowDiagramComponentState,
|
||||
|
||||
Reference in New Issue
Block a user