⚗️ Implement chat API
This commit is contained in:
@ -1,27 +1,34 @@
|
||||
import { z } from 'zod'
|
||||
import { schemaForType } from './utils'
|
||||
import { Answer as AnswerPrisma, Prisma } from 'db'
|
||||
|
||||
export const answerSchema = z.object({
|
||||
createdAt: z.date(),
|
||||
resultId: z.string(),
|
||||
blockId: z.string(),
|
||||
groupId: z.string(),
|
||||
variableId: z.string().nullable(),
|
||||
content: z.string(),
|
||||
storageUsed: z.number().nullable(),
|
||||
})
|
||||
|
||||
export const answerInputSchema = answerSchema
|
||||
.omit({
|
||||
createdAt: true,
|
||||
resultId: true,
|
||||
variableId: true,
|
||||
storageUsed: true,
|
||||
export const answerSchema = schemaForType<AnswerPrisma>()(
|
||||
z.object({
|
||||
createdAt: z.date(),
|
||||
resultId: z.string(),
|
||||
blockId: z.string(),
|
||||
groupId: z.string(),
|
||||
variableId: z.string().nullable(),
|
||||
content: z.string(),
|
||||
storageUsed: z.number().nullable(),
|
||||
})
|
||||
.and(
|
||||
z.object({
|
||||
variableId: z.string().nullish(),
|
||||
storageUsed: z.number().nullish(),
|
||||
})
|
||||
)
|
||||
|
||||
export const answerInputSchema =
|
||||
schemaForType<Prisma.AnswerUncheckedUpdateInput>()(
|
||||
answerSchema
|
||||
.omit({
|
||||
createdAt: true,
|
||||
resultId: true,
|
||||
variableId: true,
|
||||
storageUsed: true,
|
||||
})
|
||||
.and(
|
||||
z.object({
|
||||
variableId: z.string().nullish(),
|
||||
storageUsed: z.number().nullish(),
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
export type Stats = {
|
||||
|
101
packages/models/src/features/chat.ts
Normal file
101
packages/models/src/features/chat.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
audioBubbleContentSchema,
|
||||
BubbleBlockType,
|
||||
embedBubbleContentSchema,
|
||||
googleAnalyticsOptionsSchema,
|
||||
imageBubbleContentSchema,
|
||||
inputBlockSchema,
|
||||
textBubbleContentSchema,
|
||||
videoBubbleContentSchema,
|
||||
} from './blocks'
|
||||
import { publicTypebotSchema } from './publicTypebot'
|
||||
import { ChatSession as ChatSessionPrisma } from 'db'
|
||||
import { schemaForType } from './utils'
|
||||
import { resultSchema } from './result'
|
||||
|
||||
const typebotInSessionStateSchema = publicTypebotSchema.pick({
|
||||
id: true,
|
||||
groups: true,
|
||||
edges: true,
|
||||
variables: true,
|
||||
})
|
||||
|
||||
export const sessionStateSchema = z.object({
|
||||
typebot: typebotInSessionStateSchema,
|
||||
linkedTypebots: z.object({
|
||||
typebots: z.array(typebotInSessionStateSchema),
|
||||
queue: z.array(z.object({ edgeId: z.string(), typebotId: z.string() })),
|
||||
}),
|
||||
currentTypebotId: z.string(),
|
||||
result: resultSchema.pick({ id: true, variables: true, hasStarted: true }),
|
||||
isPreview: z.boolean(),
|
||||
currentBlock: z
|
||||
.object({
|
||||
blockId: z.string(),
|
||||
groupId: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
const chatSessionSchema = schemaForType<ChatSessionPrisma>()(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
state: sessionStateSchema,
|
||||
})
|
||||
)
|
||||
|
||||
const simplifiedTextBubbleContentSchema = textBubbleContentSchema.pick({
|
||||
plainText: true,
|
||||
html: true,
|
||||
})
|
||||
|
||||
const chatMessageContentSchema = simplifiedTextBubbleContentSchema
|
||||
.or(imageBubbleContentSchema)
|
||||
.or(videoBubbleContentSchema)
|
||||
.or(embedBubbleContentSchema)
|
||||
.or(audioBubbleContentSchema)
|
||||
|
||||
const codeToExecuteSchema = z.object({
|
||||
content: z.string(),
|
||||
args: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
value: z.string().or(z.number()).or(z.boolean()).nullish(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const chatReplySchema = z.object({
|
||||
messages: z.array(
|
||||
z.object({
|
||||
type: z.nativeEnum(BubbleBlockType),
|
||||
content: chatMessageContentSchema,
|
||||
})
|
||||
),
|
||||
input: inputBlockSchema.optional(),
|
||||
logic: z
|
||||
.object({
|
||||
redirectUrl: z.string().optional(),
|
||||
codeToExecute: codeToExecuteSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
integrations: z
|
||||
.object({
|
||||
chatwoot: z
|
||||
.object({
|
||||
codeToExecute: codeToExecuteSchema,
|
||||
})
|
||||
.optional(),
|
||||
googleAnalytics: googleAnalyticsOptionsSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export type ChatSession = z.infer<typeof chatSessionSchema>
|
||||
export type SessionState = z.infer<typeof sessionStateSchema>
|
||||
export type TypebotInSession = z.infer<typeof typebotInSessionStateSchema>
|
||||
export type ChatReply = z.infer<typeof chatReplySchema>
|
||||
export type ChatMessageContent = z.infer<typeof chatMessageContentSchema>
|
@ -1,21 +1,32 @@
|
||||
import { Group, Edge, Settings, Theme, Variable } from './typebot'
|
||||
import { PublicTypebot as PublicTypebotFromPrisma } from 'db'
|
||||
import {
|
||||
groupSchema,
|
||||
edgeSchema,
|
||||
variableSchema,
|
||||
themeSchema,
|
||||
settingsSchema,
|
||||
typebotSchema,
|
||||
} from './typebot'
|
||||
import { PublicTypebot as PublicTypebotPrisma } from 'db'
|
||||
import { z } from 'zod'
|
||||
import { schemaForType } from './utils'
|
||||
|
||||
export type PublicTypebot = Omit<
|
||||
PublicTypebotFromPrisma,
|
||||
| 'groups'
|
||||
| 'theme'
|
||||
| 'settings'
|
||||
| 'variables'
|
||||
| 'edges'
|
||||
| 'createdAt'
|
||||
| 'updatedAt'
|
||||
> & {
|
||||
groups: Group[]
|
||||
variables: Variable[]
|
||||
edges: Edge[]
|
||||
theme: Theme
|
||||
settings: Settings
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
export const publicTypebotSchema = schemaForType<PublicTypebotPrisma>()(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
typebotId: z.string(),
|
||||
groups: z.array(groupSchema),
|
||||
edges: z.array(edgeSchema),
|
||||
variables: z.array(variableSchema),
|
||||
theme: themeSchema,
|
||||
settings: settingsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
const publicTypebotWithName = publicTypebotSchema.and(
|
||||
typebotSchema.pick({ name: true, isArchived: true, isClosed: true })
|
||||
)
|
||||
|
||||
export type PublicTypebot = z.infer<typeof publicTypebotSchema>
|
||||
export type PublicTypebotWithName = z.infer<typeof publicTypebotWithName>
|
||||
|
@ -2,17 +2,21 @@ import { z } from 'zod'
|
||||
import { answerInputSchema, answerSchema } from './answer'
|
||||
import { InputBlockType } from './blocks'
|
||||
import { variableWithValueSchema } from './typebot/variable'
|
||||
import { Result as ResultPrisma, Log as LogPrisma } from 'db'
|
||||
import { schemaForType } from './utils'
|
||||
|
||||
export const resultSchema = z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
typebotId: z.string(),
|
||||
variables: z.array(variableWithValueSchema),
|
||||
isCompleted: z.boolean(),
|
||||
hasStarted: z.boolean().nullable(),
|
||||
isArchived: z.boolean().nullable(),
|
||||
})
|
||||
export const resultSchema = schemaForType<ResultPrisma>()(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
typebotId: z.string(),
|
||||
variables: z.array(variableWithValueSchema),
|
||||
isCompleted: z.boolean(),
|
||||
hasStarted: z.boolean().nullable(),
|
||||
isArchived: z.boolean().nullable(),
|
||||
})
|
||||
)
|
||||
|
||||
export const resultWithAnswersSchema = resultSchema.and(
|
||||
z.object({
|
||||
@ -26,23 +30,22 @@ export const resultWithAnswersInputSchema = resultSchema.and(
|
||||
})
|
||||
)
|
||||
|
||||
export const logSchema = z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
resultId: z.string(),
|
||||
status: z.string(),
|
||||
description: z.string(),
|
||||
details: z.string().nullable(),
|
||||
})
|
||||
export const logSchema = schemaForType<LogPrisma>()(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
resultId: z.string(),
|
||||
status: z.string(),
|
||||
description: z.string(),
|
||||
details: z.string().nullable(),
|
||||
})
|
||||
)
|
||||
|
||||
export type Result = z.infer<typeof resultSchema>
|
||||
|
||||
export type ResultWithAnswers = z.infer<typeof resultWithAnswersSchema>
|
||||
|
||||
export type ResultWithAnswersInput = z.infer<
|
||||
typeof resultWithAnswersInputSchema
|
||||
>
|
||||
|
||||
export type Log = z.infer<typeof logSchema>
|
||||
|
||||
export type ResultValues = Pick<
|
||||
|
@ -3,8 +3,10 @@ import { settingsSchema } from './settings'
|
||||
import { blockSchema } from '../blocks'
|
||||
import { themeSchema } from './theme'
|
||||
import { variableSchema } from './variable'
|
||||
import { Typebot as TypebotPrisma } from 'db'
|
||||
import { schemaForType } from '../utils'
|
||||
|
||||
const groupSchema = z.object({
|
||||
export const groupSchema = z.object({
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
graphCoordinates: z.object({
|
||||
@ -25,7 +27,7 @@ const targetSchema = z.object({
|
||||
blockId: z.string().optional(),
|
||||
})
|
||||
|
||||
const edgeSchema = z.object({
|
||||
export const edgeSchema = z.object({
|
||||
id: z.string(),
|
||||
from: sourceSchema,
|
||||
to: targetSchema,
|
||||
@ -37,27 +39,29 @@ const resultsTablePreferencesSchema = z.object({
|
||||
columnsWidth: z.record(z.string(), z.number()),
|
||||
})
|
||||
|
||||
const typebotSchema = z.object({
|
||||
version: z.enum(['2']).optional(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
groups: z.array(groupSchema),
|
||||
edges: z.array(edgeSchema),
|
||||
variables: z.array(variableSchema),
|
||||
theme: themeSchema,
|
||||
settings: settingsSchema,
|
||||
createdAt: z.string(),
|
||||
updatedAt: z.string(),
|
||||
icon: z.string().nullable(),
|
||||
publishedTypebotId: z.string().nullable(),
|
||||
folderId: z.string().nullable(),
|
||||
publicId: z.string().nullable(),
|
||||
customDomain: z.string().nullable(),
|
||||
workspaceId: z.string(),
|
||||
resultsTablePreferences: resultsTablePreferencesSchema.optional(),
|
||||
isArchived: z.boolean(),
|
||||
isClosed: z.boolean(),
|
||||
})
|
||||
export const typebotSchema = schemaForType<TypebotPrisma>()(
|
||||
z.object({
|
||||
version: z.enum(['2']).optional(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
groups: z.array(groupSchema),
|
||||
edges: z.array(edgeSchema),
|
||||
variables: z.array(variableSchema),
|
||||
theme: themeSchema,
|
||||
settings: settingsSchema,
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
icon: z.string().nullable(),
|
||||
publishedTypebotId: z.string().nullable(),
|
||||
folderId: z.string().nullable(),
|
||||
publicId: z.string().nullable(),
|
||||
customDomain: z.string().nullable(),
|
||||
workspaceId: z.string(),
|
||||
resultsTablePreferences: resultsTablePreferencesSchema.nullable(),
|
||||
isArchived: z.boolean(),
|
||||
isClosed: z.boolean(),
|
||||
})
|
||||
)
|
||||
|
||||
export type Typebot = z.infer<typeof typebotSchema>
|
||||
export type Target = z.infer<typeof targetSchema>
|
||||
|
@ -1 +1,9 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export type IdMap<T> = { [id: string]: T }
|
||||
|
||||
export const schemaForType =
|
||||
<T>() =>
|
||||
<S extends z.ZodType<T, any, any>>(arg: S) => {
|
||||
return arg
|
||||
}
|
||||
|
Reference in New Issue
Block a user