WIP function create (#2319)

* WIP function create

* feat: add function creation integration

---------

Co-authored-by: Gergő Jedlicska <gergo@jedlicska.com>
This commit is contained in:
Kristaps Fabians Geikins
2024-06-06 12:36:17 +03:00
committed by GitHub
parent eb1efce0eb
commit 2eb704ca4d
9 changed files with 66 additions and 25 deletions
@@ -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--
},
@@ -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<CreateFunctionResponse> => {
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<CreateFunctionResponse>({
url,
method: 'post',
body,
retry: false
})
}
export type UpdateFunctionBody = {
@@ -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! }))
@@ -1,4 +1,4 @@
import { createStoredAuthCode } from '@/modules/automate/services/executionEngine'
import { createStoredAuthCode } from '@/modules/automate/services/authCode'
import {
handleAutomateFunctionCreatorAuthCallback,
startAutomateFunctionCreatorAuth
@@ -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,
@@ -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<typeof createStoredAuthCode>
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
@@ -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'
@@ -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'