♻️ Export bot-engine code into its own package

This commit is contained in:
Baptiste Arnaud
2023-09-20 15:26:52 +02:00
parent 797685aa9d
commit 7d57e8dd06
242 changed files with 645 additions and 639 deletions

View File

@@ -0,0 +1,104 @@
import { publicProcedure } from '@/helpers/server/trpc'
import { TRPCError } from '@trpc/server'
import {
FileInputBlock,
InputBlockType,
LogicBlockType,
PublicTypebot,
TypebotLinkBlock,
} from '@typebot.io/schemas'
import { byId, isDefined } from '@typebot.io/lib'
import { z } from 'zod'
import { generatePresignedPostPolicy } from '@typebot.io/lib/s3/generatePresignedPostPolicy'
import { env } from '@typebot.io/env'
import prisma from '@typebot.io/lib/prisma'
export const getUploadUrl = publicProcedure
.meta({
openapi: {
method: 'GET',
path: '/typebots/{typebotId}/blocks/{blockId}/storage/upload-url',
summary: 'Get upload URL for a file',
description: 'Used for the web client to get the bucket upload file.',
deprecated: true,
},
})
.input(
z.object({
typebotId: z.string(),
blockId: z.string(),
filePath: z.string(),
fileType: z.string().optional(),
})
)
.output(
z.object({
presignedUrl: z.string(),
formData: z.record(z.string(), z.any()),
hasReachedStorageLimit: z.boolean(),
})
)
.query(async ({ input: { typebotId, blockId, filePath, fileType } }) => {
if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY)
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message:
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY',
})
const publicTypebot = (await prisma.publicTypebot.findFirst({
where: { typebotId },
select: {
groups: true,
typebotId: true,
},
})) as Pick<PublicTypebot, 'groups' | 'typebotId'>
const fileUploadBlock = await getFileUploadBlock(publicTypebot, blockId)
if (!fileUploadBlock)
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'File upload block not found',
})
const presignedPostPolicy = await generatePresignedPostPolicy({
fileType,
filePath,
maxFileSize: env.NEXT_PUBLIC_BOT_FILE_UPLOAD_MAX_SIZE,
})
return {
presignedUrl: `${presignedPostPolicy.postURL}/${presignedPostPolicy.formData.key}`,
formData: presignedPostPolicy.formData,
hasReachedStorageLimit: false,
}
})
const getFileUploadBlock = async (
publicTypebot: Pick<PublicTypebot, 'groups' | 'typebotId'>,
blockId: string
): Promise<FileInputBlock | null> => {
const fileUploadBlock = publicTypebot.groups
.flatMap((group) => group.blocks)
.find(byId(blockId))
if (fileUploadBlock?.type === InputBlockType.FILE) return fileUploadBlock
const linkedTypebotIds = publicTypebot.groups
.flatMap((group) => group.blocks)
.filter((block) => block.type === LogicBlockType.TYPEBOT_LINK)
.flatMap((block) => (block as TypebotLinkBlock).options.typebotId)
.filter(isDefined)
const linkedTypebots = (await prisma.publicTypebot.findMany({
where: { typebotId: { in: linkedTypebotIds } },
select: {
groups: true,
},
})) as Pick<PublicTypebot, 'groups'>[]
const fileUploadBlockFromLinkedTypebots = linkedTypebots
.flatMap((typebot) => typebot.groups)
.flatMap((group) => group.blocks)
.find(byId(blockId))
if (fileUploadBlockFromLinkedTypebots?.type === InputBlockType.FILE)
return fileUploadBlockFromLinkedTypebots
return null
}

View File

@@ -0,0 +1,94 @@
import { publicProcedure } from '@/helpers/server/trpc'
import { TRPCError } from '@trpc/server'
import { z } from 'zod'
import { generatePresignedPostPolicy } from '@typebot.io/lib/s3/generatePresignedPostPolicy'
import { env } from '@typebot.io/env'
import { InputBlockType, publicTypebotSchema } from '@typebot.io/schemas'
import prisma from '@typebot.io/lib/prisma'
export const generateUploadUrl = publicProcedure
.meta({
openapi: {
method: 'POST',
path: '/generate-upload-url',
summary: 'Generate upload URL',
description: 'Used to upload anything from the client to S3 bucket',
},
})
.input(
z.object({
filePathProps: z.object({
typebotId: z.string(),
blockId: z.string(),
resultId: z.string(),
fileName: z.string(),
}),
fileType: z.string().optional(),
})
)
.output(
z.object({
presignedUrl: z.string(),
formData: z.record(z.string(), z.any()),
fileUrl: z.string(),
})
)
.mutation(async ({ input: { filePathProps, fileType } }) => {
if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY)
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message:
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY',
})
const publicTypebot = await prisma.publicTypebot.findFirst({
where: {
typebotId: filePathProps.typebotId,
},
select: {
groups: true,
typebot: {
select: {
workspaceId: true,
},
},
},
})
const workspaceId = publicTypebot?.typebot.workspaceId
if (!workspaceId)
throw new TRPCError({
code: 'BAD_REQUEST',
message: "Can't find workspaceId",
})
const filePath = `public/workspaces/${workspaceId}/typebots/${filePathProps.typebotId}/results/${filePathProps.resultId}/${filePathProps.fileName}`
const fileUploadBlock = publicTypebotSchema._def.schema.shape.groups
.parse(publicTypebot.groups)
.flatMap((group) => group.blocks)
.find((block) => block.id === filePathProps.blockId)
if (fileUploadBlock?.type !== InputBlockType.FILE)
throw new TRPCError({
code: 'BAD_REQUEST',
message: "Can't find file upload block",
})
const presignedPostPolicy = await generatePresignedPostPolicy({
fileType,
filePath,
maxFileSize:
fileUploadBlock.options.sizeLimit ??
env.NEXT_PUBLIC_BOT_FILE_UPLOAD_MAX_SIZE,
})
return {
presignedUrl: presignedPostPolicy.postURL,
formData: presignedPostPolicy.formData,
fileUrl: env.S3_PUBLIC_CUSTOM_DOMAIN
? `${env.S3_PUBLIC_CUSTOM_DOMAIN}/${filePath}`
: `${presignedPostPolicy.postURL}/${presignedPostPolicy.formData.key}`,
}
})