diff --git a/packages/frontend-2/components/automate/function/CreateDialog.vue b/packages/frontend-2/components/automate/function/CreateDialog.vue index f628984db..5409ee087 100644 --- a/packages/frontend-2/components/automate/function/CreateDialog.vue +++ b/packages/frontend-2/components/automate/function/CreateDialog.vue @@ -187,7 +187,7 @@ const buttons = computed((): LayoutDialogButton[] => { text: 'Next', props: { iconRight: ChevronRightIcon, - disabled: !selectedTemplate.value || true // TODO: Remove once fns work + disabled: !selectedTemplate.value }, onClick: () => step.value++ } @@ -200,8 +200,7 @@ const buttons = computed((): LayoutDialogButton[] => { props: { color: 'secondary', iconLeft: ChevronLeftIcon, - textColor: 'primary', - disabled: true // TODO: Remove once fns work + textColor: 'primary' }, onClick: () => step.value-- }, diff --git a/packages/server/modules/automate/clients/executionEngine.ts b/packages/server/modules/automate/clients/executionEngine.ts index 1ef0f27d6..db20c4c1a 100644 --- a/packages/server/modules/automate/clients/executionEngine.ts +++ b/packages/server/modules/automate/clients/executionEngine.ts @@ -236,8 +236,11 @@ export enum ExecutionEngineFunctionTemplateId { } export type CreateFunctionBody = { + speckleServerOrigin: string + speckleUserId: string + authenticationCode: string template: ExecutionEngineFunctionTemplateId - functionname: string + functionName: string description: string supportedSourceApps: SourceAppName[] tags: string[] @@ -258,11 +261,18 @@ export type CreateFunctionResponse = { } } -export const createFunction = async (params: { +export const createFunction = async ({ + body +}: { body: CreateFunctionBody }): Promise => { - throw new Error('Not implemented! Needs re-thinking by Gergo & Iain') - console.log(params.body) + const url = getApiUrl('/api/v2/functions/from-template') + return invokeJsonRequest({ + url, + method: 'post', + body, + retry: false + }) } export type UpdateFunctionBody = { diff --git a/packages/server/modules/automate/graph/resolvers/automate.ts b/packages/server/modules/automate/graph/resolvers/automate.ts index 3e7a99fb1..777b33916 100644 --- a/packages/server/modules/automate/graph/resolvers/automate.ts +++ b/packages/server/modules/automate/graph/resolvers/automate.ts @@ -37,7 +37,7 @@ import { import { createStoredAuthCode, validateStoredAuthCode -} from '@/modules/automate/services/executionEngine' +} from '@/modules/automate/services/authCode' import { convertFunctionReleaseToGraphQLReturn, convertFunctionToGraphQLReturn, @@ -427,7 +427,8 @@ export = (FF_AUTOMATE_MODULE_ENABLED async createFunction(_parent, args, ctx) { const create = createFunctionFromTemplate({ createExecutionEngineFn: createFunction, - getUser + getUser, + createStoredAuthCode: createStoredAuthCode({ redis: getGenericRedis() }) }) return (await create({ input: args.input, userId: ctx.userId! })) diff --git a/packages/server/modules/automate/rest/authGithubApp.ts b/packages/server/modules/automate/rest/authGithubApp.ts index e8a334f89..f1c726588 100644 --- a/packages/server/modules/automate/rest/authGithubApp.ts +++ b/packages/server/modules/automate/rest/authGithubApp.ts @@ -1,4 +1,4 @@ -import { createStoredAuthCode } from '@/modules/automate/services/executionEngine' +import { createStoredAuthCode } from '@/modules/automate/services/authCode' import { handleAutomateFunctionCreatorAuthCallback, startAutomateFunctionCreatorAuth diff --git a/packages/server/modules/automate/services/executionEngine.ts b/packages/server/modules/automate/services/authCode.ts similarity index 100% rename from packages/server/modules/automate/services/executionEngine.ts rename to packages/server/modules/automate/services/authCode.ts diff --git a/packages/server/modules/automate/services/automationManagement.ts b/packages/server/modules/automate/services/automationManagement.ts index 466e1560f..887587797 100644 --- a/packages/server/modules/automate/services/automationManagement.ts +++ b/packages/server/modules/automate/services/automationManagement.ts @@ -19,7 +19,7 @@ import { } from '@/modules/automate/clients/executionEngine' import { validateStreamAccess } from '@/modules/core/services/streams/streamAccessService' import { Automate, Roles, removeNullOrUndefinedKeys } from '@speckle/shared' -import { createStoredAuthCode } from '@/modules/automate/services/executionEngine' +import { createStoredAuthCode } from '@/modules/automate/services/authCode' import { ProjectAutomationCreateInput, ProjectAutomationRevisionCreateInput, diff --git a/packages/server/modules/automate/services/functionManagement.ts b/packages/server/modules/automate/services/functionManagement.ts index 65da68548..2b5299ab1 100644 --- a/packages/server/modules/automate/services/functionManagement.ts +++ b/packages/server/modules/automate/services/functionManagement.ts @@ -1,6 +1,7 @@ /* eslint-disable camelcase */ import { CreateFunctionBody, + ExecutionEngineFunctionTemplateId, createFunction, getFunction, updateFunction as updateExecEngineFunction @@ -13,7 +14,8 @@ import { import { BasicGitRepositoryMetadata, UpdateAutomateFunctionInput, - CreateAutomateFunctionInput + CreateAutomateFunctionInput, + AutomateFunctionTemplateLanguage } from '@/modules/core/graph/generated/graphql' import { getUser } from '@/modules/core/repositories/users' import { @@ -33,10 +35,25 @@ import { } from '@/modules/automate/helpers/executionEngine' import { Request, Response } from 'express' import { UnauthorizedError } from '@/modules/shared/errors' -import { createStoredAuthCode } from '@/modules/automate/services/executionEngine' +import { createStoredAuthCode } from '@/modules/automate/services/authCode' import { getServerOrigin, speckleAutomateUrl } from '@/modules/shared/helpers/envHelper' import { getFunctionsMarketplaceUrl } from '@/modules/core/helpers/routeHelper' +const mapGqlTemplateIdToExecEngineTemplateId = ( + id: AutomateFunctionTemplateLanguage +): ExecutionEngineFunctionTemplateId => { + switch (id) { + case AutomateFunctionTemplateLanguage.Python: + return ExecutionEngineFunctionTemplateId.Python + case AutomateFunctionTemplateLanguage.DotNet: + return ExecutionEngineFunctionTemplateId.DotNet + case AutomateFunctionTemplateLanguage.Typescript: + return ExecutionEngineFunctionTemplateId.TypeScript + default: + throw new Error('Unknown template id') + } +} + const repoUrlToBasicGitRepositoryMetadata = ( url: string ): BasicGitRepositoryMetadata => { @@ -91,6 +108,7 @@ export const convertFunctionReleaseToGraphQLReturn = ( } export type CreateFunctionDeps = { + createStoredAuthCode: ReturnType createExecutionEngineFn: typeof createFunction getUser: typeof getUser } @@ -99,7 +117,7 @@ export const createFunctionFromTemplate = (deps: CreateFunctionDeps) => async (params: { input: CreateAutomateFunctionInput; userId: string }) => { const { input, userId } = params - const { createExecutionEngineFn, getUser } = deps + const { createExecutionEngineFn, getUser, createStoredAuthCode } = deps // Validate user const user = await getUser(userId) @@ -107,25 +125,36 @@ export const createFunctionFromTemplate = throw new AutomateFunctionCreationError('Speckle user not found') } - const created = await createExecutionEngineFn({ - body: input as unknown as CreateFunctionBody - }) + const authCode = await createStoredAuthCode() + const body: CreateFunctionBody = { + ...input, + speckleServerOrigin: new URL(getServerOrigin()).origin, + speckleUserId: user.id, + authenticationCode: authCode, + functionName: input.name, + template: mapGqlTemplateIdToExecEngineTemplateId(input.template), + supportedSourceApps: input.supportedSourceApps as SourceAppName[], + logo: cleanFunctionLogo(input.logo), + org: input.org || null + } + + const created = await createExecutionEngineFn({ body }) // Don't want to pull the function w/ another req, so we'll just return the input const gqlReturn: AutomateFunctionGraphQLReturn = { id: created.functionId, - name: input.name, + name: body.functionName, repo: { id: created.repo.htmlUrl, url: created.repo.htmlUrl, name: created.repo.name, owner: created.repo.owner }, - isFeatured: false, // TODO: Is this ok? Probably not featured right after creation - description: input.description, - logo: cleanFunctionLogo(input.logo), - tags: input.tags, - supportedSourceApps: input.supportedSourceApps + isFeatured: false, + description: body.description, + logo: body.logo, + tags: body.tags, + supportedSourceApps: body.supportedSourceApps } return { @@ -142,6 +171,8 @@ export type UpdateFunctionDeps = { export const updateFunction = (deps: UpdateFunctionDeps) => async (params: { input: UpdateAutomateFunctionInput; userId: string }) => { + throw new AutomateFunctionUpdateError('Function update not supported yet') + const { updateFunction } = deps const { input } = params diff --git a/packages/server/modules/automate/tests/automations.spec.ts b/packages/server/modules/automate/tests/automations.spec.ts index 43029bff3..5b19407c5 100644 --- a/packages/server/modules/automate/tests/automations.spec.ts +++ b/packages/server/modules/automate/tests/automations.spec.ts @@ -7,7 +7,7 @@ import { updateAutomation as updateDbAutomation } from '@/modules/automate/repositories/automations' import { updateAutomation } from '@/modules/automate/services/automationManagement' -import { createStoredAuthCode } from '@/modules/automate/services/executionEngine' +import { createStoredAuthCode } from '@/modules/automate/services/authCode' import { getGenericRedis } from '@/modules/core' import { ProjectAutomationRevisionCreateInput } from '@/modules/core/graph/generated/graphql' import { BranchRecord } from '@/modules/core/helpers/types' diff --git a/packages/server/test/speckle-helpers/automationHelper.ts b/packages/server/test/speckle-helpers/automationHelper.ts index fc4f1377e..839a15ffd 100644 --- a/packages/server/test/speckle-helpers/automationHelper.ts +++ b/packages/server/test/speckle-helpers/automationHelper.ts @@ -10,7 +10,7 @@ import { createAutomation, createAutomationRevision } from '@/modules/automate/services/automationManagement' -import { createStoredAuthCode } from '@/modules/automate/services/executionEngine' +import { createStoredAuthCode } from '@/modules/automate/services/authCode' import { createInmemoryRedisClient } from '@/test/redisHelper' import cryptoRandomString from 'crypto-random-string' import { createAutomation as clientCreateAutomation } from '@/modules/automate/clients/executionEngine'