refactor(models): 🎨 Build types from validation schemas
This commit is contained in:
@ -5,7 +5,7 @@ import {
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { byId, isNotEmpty } from 'utils'
|
||||
import { byId } from 'utils'
|
||||
import { MemberInWorkspace, Plan, Workspace, WorkspaceRole } from 'db'
|
||||
import {
|
||||
createNewWorkspace,
|
||||
@ -87,8 +87,11 @@ export const WorkspaceContext = ({ children }: { children: ReactNode }) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [typebot?.workspaceId])
|
||||
|
||||
const switchWorkspace = (workspaceId: string) =>
|
||||
setCurrentWorkspace(workspaces?.find(byId(workspaceId)))
|
||||
const switchWorkspace = (workspaceId: string) => {
|
||||
const newWorkspace = workspaces?.find(byId(workspaceId))
|
||||
if (!newWorkspace) return
|
||||
setCurrentWorkspace(newWorkspace)
|
||||
}
|
||||
|
||||
const createWorkspace = async (name?: string) => {
|
||||
if (!workspaces) return
|
||||
|
@ -70,11 +70,13 @@ export const ResultsContent = () => {
|
||||
</HStack>
|
||||
</Flex>
|
||||
<Flex pt={['10px', '60px']} w="full" justify="center">
|
||||
{publishedTypebot &&
|
||||
{workspace &&
|
||||
publishedTypebot &&
|
||||
(isAnalytics ? (
|
||||
<AnalyticsContent stats={stats} />
|
||||
) : (
|
||||
<SubmissionsContent
|
||||
workspaceId={workspace.id}
|
||||
typebotId={publishedTypebot.typebotId}
|
||||
onDeleteResults={handleDeletedResults}
|
||||
totalResults={stats?.totalStarts ?? 0}
|
||||
|
@ -18,12 +18,14 @@ import { Plan } from 'db'
|
||||
import { useToast } from 'components/shared/hooks/useToast'
|
||||
|
||||
type Props = {
|
||||
workspaceId: string
|
||||
typebotId: string
|
||||
totalResults: number
|
||||
totalHiddenResults?: number
|
||||
onDeleteResults: (total: number) => void
|
||||
}
|
||||
export const SubmissionsContent = ({
|
||||
workspaceId,
|
||||
typebotId,
|
||||
totalResults,
|
||||
totalHiddenResults,
|
||||
@ -51,6 +53,7 @@ export const SubmissionsContent = ({
|
||||
const resultHeader = parseResultHeader(blocksAndVariables)
|
||||
|
||||
const { data, mutate, setSize, hasMore } = useResults({
|
||||
workspaceId,
|
||||
typebotId,
|
||||
onError: (err) => showToast({ title: err.name, description: err.message }),
|
||||
})
|
||||
@ -125,7 +128,7 @@ export const SubmissionsContent = ({
|
||||
|
||||
const getAllTableData = async () => {
|
||||
if (!publishedTypebot) return []
|
||||
const results = await getAllResults(typebotId)
|
||||
const results = await getAllResults(workspaceId, typebotId)
|
||||
return convertResultsToTableData(results, resultHeader)
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,19 @@ import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
||||
import { getAuthenticatedUser } from 'services/api/utils'
|
||||
import { isFreePlan } from 'services/workspace'
|
||||
import { forbidden, methodNotAllowed, notAuthenticated } from 'utils'
|
||||
import {
|
||||
badRequest,
|
||||
forbidden,
|
||||
methodNotAllowed,
|
||||
notAuthenticated,
|
||||
} from 'utils'
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const user = await getAuthenticatedUser(req)
|
||||
if (!user) return notAuthenticated(res)
|
||||
const workspaceId = req.query.workspaceId as string | undefined
|
||||
if (req.method === 'GET') {
|
||||
if (!workspaceId) return badRequest(res, 'workspaceId is required')
|
||||
const workspace = await prisma.workspace.findFirst({
|
||||
where: { id: workspaceId, members: { some: { userId: user.id } } },
|
||||
select: { plan: true },
|
||||
|
@ -143,12 +143,13 @@ test.describe.parallel('Editor', () => {
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
|
||||
await page.click('[data-testid="editable-icon"]')
|
||||
await expect(page.locator('text="My awesome typebot"')).toBeVisible()
|
||||
await page.fill('input[placeholder="Search..."]', 'love')
|
||||
await page.click('text="😍"')
|
||||
await page.click('text="My awesome typebot"')
|
||||
await page.fill('input[value="My awesome typebot"]', 'My superb typebot')
|
||||
await page.press('input[value="My superb typebot"]', 'Enter')
|
||||
await page.goto(`/typebots`)
|
||||
await page.click('[aria-label="Navigate back"]')
|
||||
await expect(page.locator('text="😍"')).toBeVisible()
|
||||
await expect(page.locator('text="My superb typebot"')).toBeVisible()
|
||||
})
|
||||
|
@ -78,6 +78,7 @@ test.describe.parallel('Settings page', () => {
|
||||
)
|
||||
await page.goto(`/typebots/${typebotId}/settings`)
|
||||
await page.click('button:has-text("Metadata")')
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// Fav icon
|
||||
const favIconImg = page.locator('img >> nth=0')
|
||||
|
@ -2,7 +2,7 @@ import { ResultWithAnswers, VariableWithValue, ResultHeaderCell } from 'models'
|
||||
import useSWRInfinite from 'swr/infinite'
|
||||
import { stringify } from 'qs'
|
||||
import { Answer } from 'db'
|
||||
import { isDefined, sendRequest } from 'utils'
|
||||
import { isDefined, isEmpty, sendRequest } from 'utils'
|
||||
import { fetcher } from 'services/utils'
|
||||
import { HStack, Text } from '@chakra-ui/react'
|
||||
import { CodeIcon, CalendarIcon } from 'assets/icons'
|
||||
@ -11,6 +11,7 @@ import { StepIcon } from 'components/editor/StepsSideBar/StepIcon'
|
||||
const paginationLimit = 50
|
||||
|
||||
const getKey = (
|
||||
workspaceId: string,
|
||||
typebotId: string,
|
||||
pageIndex: number,
|
||||
previousPageData: {
|
||||
@ -18,16 +19,19 @@ const getKey = (
|
||||
}
|
||||
) => {
|
||||
if (previousPageData && previousPageData.results.length === 0) return null
|
||||
if (pageIndex === 0) return `/api/typebots/${typebotId}/results?limit=50`
|
||||
if (pageIndex === 0)
|
||||
return `/api/typebots/${typebotId}/results?limit=50&workspaceId=${workspaceId}`
|
||||
return `/api/typebots/${typebotId}/results?lastResultId=${
|
||||
previousPageData.results[previousPageData.results.length - 1].id
|
||||
}&limit=${paginationLimit}`
|
||||
}&limit=${paginationLimit}&workspaceId=${workspaceId}`
|
||||
}
|
||||
|
||||
export const useResults = ({
|
||||
workspaceId,
|
||||
typebotId,
|
||||
onError,
|
||||
}: {
|
||||
workspaceId: string
|
||||
typebotId: string
|
||||
onError: (error: Error) => void
|
||||
}) => {
|
||||
@ -40,9 +44,14 @@ export const useResults = ({
|
||||
previousPageData: {
|
||||
results: ResultWithAnswers[]
|
||||
}
|
||||
) => getKey(typebotId, pageIndex, previousPageData),
|
||||
) => getKey(workspaceId, typebotId, pageIndex, previousPageData),
|
||||
fetcher,
|
||||
{ revalidateAll: true }
|
||||
{
|
||||
revalidateAll: true,
|
||||
dedupingInterval: isEmpty(process.env.NEXT_PUBLIC_E2E_TEST)
|
||||
? undefined
|
||||
: 0,
|
||||
}
|
||||
)
|
||||
|
||||
if (error) onError(error)
|
||||
@ -80,12 +89,12 @@ export const deleteAllResults = async (typebotId: string) =>
|
||||
method: 'DELETE',
|
||||
})
|
||||
|
||||
export const getAllResults = async (typebotId: string) => {
|
||||
export const getAllResults = async (workspaceId: string, typebotId: string) => {
|
||||
const results = []
|
||||
let hasMore = true
|
||||
let lastResultId: string | undefined = undefined
|
||||
do {
|
||||
const query = stringify({ limit: 200, lastResultId })
|
||||
const query = stringify({ limit: 200, lastResultId, workspaceId })
|
||||
const { data } = await sendRequest<{ results: ResultWithAnswers[] }>({
|
||||
url: `/api/typebots/${typebotId}/results?${query}`,
|
||||
method: 'GET',
|
||||
|
@ -45,7 +45,10 @@
|
||||
"typescript": "^4.6.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.1.0"
|
||||
"react": "^18.1.0",
|
||||
"utils": "*",
|
||||
"db": "*",
|
||||
"models": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn rollup -c",
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Made the column `workspaceId` on table `Credentials` required. This step will fail if there are existing NULL values in that column.
|
||||
- Made the column `workspaceId` on table `CustomDomain` required. This step will fail if there are existing NULL values in that column.
|
||||
- Made the column `workspaceId` on table `DashboardFolder` required. This step will fail if there are existing NULL values in that column.
|
||||
- Made the column `workspaceId` on table `Typebot` required. This step will fail if there are existing NULL values in that column.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Credentials" ALTER COLUMN "workspaceId" SET NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "CustomDomain" ALTER COLUMN "workspaceId" SET NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DashboardFolder" ALTER COLUMN "workspaceId" SET NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Typebot" ALTER COLUMN "workspaceId" SET NOT NULL;
|
@ -114,15 +114,15 @@ enum GraphNavigation {
|
||||
model CustomDomain {
|
||||
name String @id
|
||||
createdAt DateTime @default(now())
|
||||
workspaceId String?
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
workspaceId String
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Credentials {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
workspaceId String?
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
workspaceId String
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
data String // Encrypted data
|
||||
name String
|
||||
type String
|
||||
@ -154,8 +154,8 @@ model DashboardFolder {
|
||||
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
|
||||
childrenFolder DashboardFolder[] @relation("ParentChild")
|
||||
typebots Typebot[]
|
||||
workspaceId String?
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
workspaceId String
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Typebot {
|
||||
@ -179,8 +179,8 @@ model Typebot {
|
||||
collaborators CollaboratorsOnTypebots[]
|
||||
invitations Invitation[]
|
||||
webhooks Webhook[]
|
||||
workspaceId String?
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
workspaceId String
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Invitation {
|
||||
|
@ -1,20 +1,31 @@
|
||||
{
|
||||
"name": "models",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/types/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
"module": "dist/esm/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"typescript": "^4.6.4"
|
||||
"typescript": "^4.6.4",
|
||||
"@rollup/plugin-commonjs": "^22.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
||||
"@rollup/plugin-typescript": "^8.3.2",
|
||||
"rollup": "^2.72.1",
|
||||
"rollup-plugin-dts": "^4.2.1",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^12.1.6",
|
||||
"db": "*",
|
||||
"@udecode/plate-core": "^11.0.0"
|
||||
"next": "^12.1.6",
|
||||
"zod": "^3.17.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12.1.6",
|
||||
"db": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dx": "tsc --watch --preserveWatchOutput"
|
||||
"build": "yarn rollup -c",
|
||||
"dx": "yarn rollup -c --watch"
|
||||
}
|
||||
}
|
||||
|
38
packages/models/rollup.config.js
Normal file
38
packages/models/rollup.config.js
Normal file
@ -0,0 +1,38 @@
|
||||
import resolve from '@rollup/plugin-node-resolve'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import typescript from '@rollup/plugin-typescript'
|
||||
import dts from 'rollup-plugin-dts'
|
||||
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
|
||||
|
||||
const packageJson = require('./package.json')
|
||||
|
||||
export default [
|
||||
{
|
||||
input: 'src/index.ts',
|
||||
output: [
|
||||
{
|
||||
file: packageJson.main,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
{
|
||||
file: packageJson.module,
|
||||
format: 'esm',
|
||||
sourcemap: true,
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
peerDepsExternal(),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
typescript({ tsconfig: './tsconfig.json' }),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: 'dist/esm/types/index.d.ts',
|
||||
output: [{ file: 'dist/index.d.ts', format: 'esm' }],
|
||||
plugins: [dts()],
|
||||
},
|
||||
]
|
@ -1,5 +1,6 @@
|
||||
import { Result as ResultFromPrisma } from 'db'
|
||||
import { Answer, InputStepType, VariableWithValue } from '.'
|
||||
import { Answer, VariableWithValue } from '.'
|
||||
import { InputStepType } from './typebot/steps/shared'
|
||||
|
||||
export type Result = Omit<ResultFromPrisma, 'createdAt' | 'variables'> & {
|
||||
createdAt: string
|
||||
|
@ -1,29 +1,32 @@
|
||||
export type Settings = {
|
||||
general: GeneralSettings
|
||||
typingEmulation: TypingEmulation
|
||||
metadata: Metadata
|
||||
}
|
||||
import { z } from 'zod'
|
||||
|
||||
export type GeneralSettings = {
|
||||
isBrandingEnabled: boolean
|
||||
isNewResultOnRefreshEnabled?: boolean
|
||||
isInputPrefillEnabled?: boolean
|
||||
isHideQueryParamsEnabled?: boolean
|
||||
}
|
||||
const generalSettings = z.object({
|
||||
isBrandingEnabled: z.boolean(),
|
||||
isTypingEmulationEnabled: z.boolean().optional(),
|
||||
isInputPrefillEnabled: z.boolean().optional(),
|
||||
isHideQueryParamsEnabled: z.boolean().optional(),
|
||||
isNewResultOnRefreshEnabled: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export type TypingEmulation = {
|
||||
enabled: boolean
|
||||
speed: number
|
||||
maxDelay: number
|
||||
}
|
||||
const typingEmulation = z.object({
|
||||
enabled: z.boolean(),
|
||||
speed: z.number(),
|
||||
maxDelay: z.number(),
|
||||
})
|
||||
|
||||
export type Metadata = {
|
||||
title?: string
|
||||
description: string
|
||||
imageUrl?: string
|
||||
favIconUrl?: string
|
||||
customHeadCode?: string
|
||||
}
|
||||
const metadataSchema = z.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
imageUrl: z.string().optional(),
|
||||
favIconUrl: z.string().optional(),
|
||||
customHeadCode: z.string().optional(),
|
||||
})
|
||||
|
||||
export const settingsSchema = z.object({
|
||||
general: generalSettings,
|
||||
typingEmulation: typingEmulation,
|
||||
metadata: metadataSchema,
|
||||
})
|
||||
|
||||
export const defaultSettings: Settings = {
|
||||
general: {
|
||||
@ -38,3 +41,8 @@ export const defaultSettings: Settings = {
|
||||
'Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form.',
|
||||
},
|
||||
}
|
||||
|
||||
export type Settings = z.infer<typeof settingsSchema>
|
||||
export type GeneralSettings = z.infer<typeof generalSettings>
|
||||
export type TypingEmulation = z.infer<typeof typingEmulation>
|
||||
export type Metadata = z.infer<typeof metadataSchema>
|
||||
|
@ -1,80 +0,0 @@
|
||||
import { StepBase } from '.'
|
||||
import { TElement } from '@udecode/plate-core'
|
||||
|
||||
export type BubbleStep =
|
||||
| TextBubbleStep
|
||||
| ImageBubbleStep
|
||||
| VideoBubbleStep
|
||||
| EmbedBubbleStep
|
||||
|
||||
export enum BubbleStepType {
|
||||
TEXT = 'text',
|
||||
IMAGE = 'image',
|
||||
VIDEO = 'video',
|
||||
EMBED = 'embed',
|
||||
}
|
||||
|
||||
export type BubbleStepContent =
|
||||
| TextBubbleContent
|
||||
| ImageBubbleContent
|
||||
| VideoBubbleContent
|
||||
| EmbedBubbleContent
|
||||
|
||||
export type TextBubbleStep = StepBase & {
|
||||
type: BubbleStepType.TEXT
|
||||
content: TextBubbleContent
|
||||
}
|
||||
|
||||
export type ImageBubbleStep = StepBase & {
|
||||
type: BubbleStepType.IMAGE
|
||||
content: ImageBubbleContent
|
||||
}
|
||||
|
||||
export type VideoBubbleStep = StepBase & {
|
||||
type: BubbleStepType.VIDEO
|
||||
content: VideoBubbleContent
|
||||
}
|
||||
|
||||
export type EmbedBubbleStep = StepBase & {
|
||||
type: BubbleStepType.EMBED
|
||||
content: EmbedBubbleContent
|
||||
}
|
||||
|
||||
export type TextBubbleContent = {
|
||||
html: string
|
||||
richText: TElement[]
|
||||
plainText: string
|
||||
}
|
||||
|
||||
export type ImageBubbleContent = {
|
||||
url?: string
|
||||
}
|
||||
|
||||
export type EmbedBubbleContent = {
|
||||
url?: string
|
||||
height: number
|
||||
}
|
||||
|
||||
export enum VideoBubbleContentType {
|
||||
URL = 'url',
|
||||
YOUTUBE = 'youtube',
|
||||
VIMEO = 'vimeo',
|
||||
}
|
||||
|
||||
export type VideoBubbleContent = {
|
||||
type?: VideoBubbleContentType
|
||||
url?: string
|
||||
id?: string
|
||||
}
|
||||
|
||||
export const defaultTextBubbleContent: TextBubbleContent = {
|
||||
html: '',
|
||||
richText: [],
|
||||
plainText: '',
|
||||
}
|
||||
|
||||
export const defaultImageBubbleContent: ImageBubbleContent = {}
|
||||
|
||||
export const defaultVideoBubbleContent: VideoBubbleContent = {}
|
||||
|
||||
export const defaultEmbedBubbleContent: EmbedBubbleContent = { height: 400 }
|
18
packages/models/src/typebot/steps/bubble/bubble.ts
Normal file
18
packages/models/src/typebot/steps/bubble/bubble.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod'
|
||||
import { embedBubbleContentSchema, embedBubbleStepSchema } from './embed'
|
||||
import { imageBubbleContentSchema, imageBubbleStepSchema } from './image'
|
||||
import { textBubbleContentSchema, textBubbleStepSchema } from './text'
|
||||
import { videoBubbleContentSchema, videoBubbleStepSchema } from './video'
|
||||
|
||||
export const bubbleStepContentSchema = textBubbleContentSchema
|
||||
.or(imageBubbleContentSchema)
|
||||
.or(videoBubbleContentSchema)
|
||||
.or(embedBubbleContentSchema)
|
||||
|
||||
export const bubbleStepSchema = textBubbleStepSchema
|
||||
.or(imageBubbleStepSchema)
|
||||
.or(videoBubbleStepSchema)
|
||||
.or(embedBubbleStepSchema)
|
||||
|
||||
export type BubbleStep = z.infer<typeof bubbleStepSchema>
|
||||
export type BubbleStepContent = z.infer<typeof bubbleStepContentSchema>
|
19
packages/models/src/typebot/steps/bubble/embed.ts
Normal file
19
packages/models/src/typebot/steps/bubble/embed.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { stepBaseSchema, BubbleStepType } from '../shared'
|
||||
import { z } from 'zod'
|
||||
|
||||
export const embedBubbleContentSchema = z.object({
|
||||
url: z.string().optional(),
|
||||
height: z.number(),
|
||||
})
|
||||
|
||||
export const embedBubbleStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([BubbleStepType.EMBED]),
|
||||
content: embedBubbleContentSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultEmbedBubbleContent: EmbedBubbleContent = { height: 400 }
|
||||
|
||||
export type EmbedBubbleStep = z.infer<typeof embedBubbleStepSchema>
|
||||
export type EmbedBubbleContent = z.infer<typeof embedBubbleContentSchema>
|
18
packages/models/src/typebot/steps/bubble/image.ts
Normal file
18
packages/models/src/typebot/steps/bubble/image.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod'
|
||||
import { stepBaseSchema, BubbleStepType } from '../shared'
|
||||
|
||||
export const imageBubbleContentSchema = z.object({
|
||||
url: z.string().optional(),
|
||||
})
|
||||
|
||||
export const imageBubbleStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([BubbleStepType.IMAGE]),
|
||||
content: imageBubbleContentSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultImageBubbleContent: ImageBubbleContent = {}
|
||||
|
||||
export type ImageBubbleStep = z.infer<typeof imageBubbleStepSchema>
|
||||
export type ImageBubbleContent = z.infer<typeof imageBubbleContentSchema>
|
5
packages/models/src/typebot/steps/bubble/index.ts
Normal file
5
packages/models/src/typebot/steps/bubble/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './bubble'
|
||||
export * from './text'
|
||||
export * from './image'
|
||||
export * from './video'
|
||||
export * from './embed'
|
25
packages/models/src/typebot/steps/bubble/text.ts
Normal file
25
packages/models/src/typebot/steps/bubble/text.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { stepBaseSchema, BubbleStepType } from '../shared'
|
||||
import { z } from 'zod'
|
||||
|
||||
export const defaultTextBubbleContent: TextBubbleContent = {
|
||||
html: '',
|
||||
richText: [],
|
||||
plainText: '',
|
||||
}
|
||||
|
||||
export const textBubbleContentSchema = z.object({
|
||||
html: z.string(),
|
||||
richText: z.array(z.any()),
|
||||
plainText: z.string(),
|
||||
})
|
||||
|
||||
export type TextBubbleContent = z.infer<typeof textBubbleContentSchema>
|
||||
|
||||
export const textBubbleStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([BubbleStepType.TEXT]),
|
||||
content: textBubbleContentSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export type TextBubbleStep = z.infer<typeof textBubbleStepSchema>
|
26
packages/models/src/typebot/steps/bubble/video.ts
Normal file
26
packages/models/src/typebot/steps/bubble/video.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { stepBaseSchema, BubbleStepType } from '../shared'
|
||||
import { z } from 'zod'
|
||||
|
||||
export enum VideoBubbleContentType {
|
||||
URL = 'url',
|
||||
YOUTUBE = 'youtube',
|
||||
VIMEO = 'vimeo',
|
||||
}
|
||||
|
||||
export const videoBubbleContentSchema = z.object({
|
||||
url: z.string().optional(),
|
||||
id: z.string().optional(),
|
||||
type: z.nativeEnum(VideoBubbleContentType).optional(),
|
||||
})
|
||||
|
||||
export const videoBubbleStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([BubbleStepType.VIDEO]),
|
||||
content: videoBubbleContentSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultVideoBubbleContent: VideoBubbleContent = {}
|
||||
|
||||
export type VideoBubbleStep = z.infer<typeof videoBubbleStepSchema>
|
||||
export type VideoBubbleContent = z.infer<typeof videoBubbleContentSchema>
|
@ -1,6 +1,7 @@
|
||||
export * from './steps'
|
||||
export * from './bubble'
|
||||
export * from './inputs'
|
||||
export * from './input'
|
||||
export * from './logic'
|
||||
export * from './integration'
|
||||
export * from './item'
|
||||
export * from './shared'
|
||||
|
40
packages/models/src/typebot/steps/input/choice.ts
Normal file
40
packages/models/src/typebot/steps/input/choice.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
stepBaseSchema,
|
||||
InputStepType,
|
||||
defaultButtonLabel,
|
||||
optionBaseSchema,
|
||||
itemBaseSchema,
|
||||
ItemType,
|
||||
} from '../shared'
|
||||
|
||||
export const choiceInputOptionsSchema = optionBaseSchema.and(
|
||||
z.object({
|
||||
isMultipleChoice: z.boolean(),
|
||||
buttonLabel: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultChoiceInputOptions: ChoiceInputOptions = {
|
||||
buttonLabel: defaultButtonLabel,
|
||||
isMultipleChoice: false,
|
||||
}
|
||||
|
||||
export const choiceInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.CHOICE]),
|
||||
items: z.array(z.any()),
|
||||
options: choiceInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const buttonItemSchema = itemBaseSchema.and(
|
||||
z.object({
|
||||
type: z.literal(ItemType.BUTTON),
|
||||
content: z.string().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export type ButtonItem = z.infer<typeof buttonItemSchema>
|
||||
export type ChoiceInputStep = z.infer<typeof choiceInputSchema>
|
||||
export type ChoiceInputOptions = z.infer<typeof choiceInputOptionsSchema>
|
35
packages/models/src/typebot/steps/input/date.ts
Normal file
35
packages/models/src/typebot/steps/input/date.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
stepBaseSchema,
|
||||
InputStepType,
|
||||
defaultButtonLabel,
|
||||
optionBaseSchema,
|
||||
} from '../shared'
|
||||
|
||||
export const dateInputOptionsSchema = optionBaseSchema.and(
|
||||
z.object({
|
||||
labels: z.object({
|
||||
button: z.string(),
|
||||
from: z.string(),
|
||||
to: z.string(),
|
||||
}),
|
||||
hasTime: z.boolean(),
|
||||
isRange: z.boolean(),
|
||||
})
|
||||
)
|
||||
|
||||
export const dateInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.DATE]),
|
||||
options: dateInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultDateInputOptions: DateInputOptions = {
|
||||
hasTime: false,
|
||||
isRange: false,
|
||||
labels: { button: defaultButtonLabel, from: 'From:', to: 'To:' },
|
||||
}
|
||||
|
||||
export type DateInputStep = z.infer<typeof dateInputSchema>
|
||||
export type DateInputOptions = z.infer<typeof dateInputOptionsSchema>
|
35
packages/models/src/typebot/steps/input/email.ts
Normal file
35
packages/models/src/typebot/steps/input/email.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
defaultButtonLabel,
|
||||
InputStepType,
|
||||
optionBaseSchema,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
import { textInputOptionsBaseSchema } from './text'
|
||||
|
||||
export const emailInputOptionsSchema = optionBaseSchema
|
||||
.and(textInputOptionsBaseSchema)
|
||||
.and(
|
||||
z.object({
|
||||
retryMessageContent: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export const emailInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.EMAIL]),
|
||||
options: emailInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultEmailInputOptions: EmailInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type your email...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This email doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export type EmailInputStep = z.infer<typeof emailInputSchema>
|
||||
export type EmailInputOptions = z.infer<typeof emailInputOptionsSchema>
|
9
packages/models/src/typebot/steps/input/index.ts
Normal file
9
packages/models/src/typebot/steps/input/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export * from './input'
|
||||
export * from './text'
|
||||
export * from './email'
|
||||
export * from './number'
|
||||
export * from './url'
|
||||
export * from './date'
|
||||
export * from './choice'
|
||||
export * from './payment'
|
||||
export * from './phone'
|
36
packages/models/src/typebot/steps/input/input.ts
Normal file
36
packages/models/src/typebot/steps/input/input.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { z } from 'zod'
|
||||
import { optionBaseSchema } from '../shared'
|
||||
import { choiceInputOptionsSchema, choiceInputSchema } from './choice'
|
||||
import { dateInputOptionsSchema, dateInputSchema } from './date'
|
||||
import { emailInputOptionsSchema, emailInputSchema } from './email'
|
||||
import { numberInputOptionsSchema, numberInputSchema } from './number'
|
||||
import { paymentInputOptionsSchema, paymentInputSchema } from './payment'
|
||||
import {
|
||||
phoneNumberInputOptionsSchema,
|
||||
phoneNumberInputStepSchema,
|
||||
} from './phone'
|
||||
import { textInputOptionsSchema, textInputSchema } from './text'
|
||||
import { urlInputOptionsSchema, urlInputSchema } from './url'
|
||||
|
||||
export type OptionBase = z.infer<typeof optionBaseSchema>
|
||||
|
||||
export const inputStepOptionsSchema = textInputOptionsSchema
|
||||
.or(choiceInputOptionsSchema)
|
||||
.or(emailInputOptionsSchema)
|
||||
.or(numberInputOptionsSchema)
|
||||
.or(urlInputOptionsSchema)
|
||||
.or(phoneNumberInputOptionsSchema)
|
||||
.or(dateInputOptionsSchema)
|
||||
.or(paymentInputOptionsSchema)
|
||||
|
||||
export const inputStepSchema = textInputSchema
|
||||
.or(numberInputSchema)
|
||||
.or(emailInputSchema)
|
||||
.or(urlInputSchema)
|
||||
.or(dateInputSchema)
|
||||
.or(phoneNumberInputStepSchema)
|
||||
.or(choiceInputSchema)
|
||||
.or(paymentInputSchema)
|
||||
|
||||
export type InputStep = z.infer<typeof inputStepSchema>
|
||||
export type InputStepOptions = z.infer<typeof inputStepOptionsSchema>
|
32
packages/models/src/typebot/steps/input/number.ts
Normal file
32
packages/models/src/typebot/steps/input/number.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
defaultButtonLabel,
|
||||
InputStepType,
|
||||
optionBaseSchema,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
import { textInputOptionsBaseSchema } from './text'
|
||||
|
||||
export const numberInputOptionsSchema = optionBaseSchema
|
||||
.and(textInputOptionsBaseSchema)
|
||||
.and(
|
||||
z.object({
|
||||
min: z.number().optional(),
|
||||
max: z.number().optional(),
|
||||
step: z.number().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export const numberInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.NUMBER]),
|
||||
options: numberInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultNumberInputOptions: NumberInputOptions = {
|
||||
labels: { button: defaultButtonLabel, placeholder: 'Type a number...' },
|
||||
}
|
||||
|
||||
export type NumberInputStep = z.infer<typeof numberInputSchema>
|
||||
export type NumberInputOptions = z.infer<typeof numberInputOptionsSchema>
|
49
packages/models/src/typebot/steps/input/payment.ts
Normal file
49
packages/models/src/typebot/steps/input/payment.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { z } from 'zod'
|
||||
import { InputStepType, optionBaseSchema, stepBaseSchema } from '../shared'
|
||||
|
||||
export type CreditCardDetails = {
|
||||
number: string
|
||||
exp_month: string
|
||||
exp_year: string
|
||||
cvc: string
|
||||
}
|
||||
|
||||
export enum PaymentProvider {
|
||||
STRIPE = 'Stripe',
|
||||
}
|
||||
|
||||
export const paymentInputOptionsSchema = optionBaseSchema.and(
|
||||
z.object({
|
||||
provider: z.nativeEnum(PaymentProvider),
|
||||
labels: z.object({
|
||||
button: z.string(),
|
||||
success: z.string().optional(),
|
||||
}),
|
||||
additionalInformation: z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
phoneNumber: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
credentialsId: z.string().optional(),
|
||||
currency: z.string(),
|
||||
amount: z.string().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export const paymentInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.PAYMENT]),
|
||||
options: paymentInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultPaymentInputOptions: PaymentInputOptions = {
|
||||
provider: PaymentProvider.STRIPE,
|
||||
labels: { button: 'Pay', success: 'Success' },
|
||||
currency: 'USD',
|
||||
}
|
||||
|
||||
export type PaymentInputStep = z.infer<typeof paymentInputSchema>
|
||||
export type PaymentInputOptions = z.infer<typeof paymentInputOptionsSchema>
|
38
packages/models/src/typebot/steps/input/phone.ts
Normal file
38
packages/models/src/typebot/steps/input/phone.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
defaultButtonLabel,
|
||||
InputStepType,
|
||||
optionBaseSchema,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
import { textInputOptionsBaseSchema } from './text'
|
||||
|
||||
export const phoneNumberInputOptionsSchema = optionBaseSchema
|
||||
.and(textInputOptionsBaseSchema)
|
||||
.and(
|
||||
z.object({
|
||||
retryMessageContent: z.string(),
|
||||
defaultCountryCode: z.string().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export const phoneNumberInputStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.PHONE]),
|
||||
options: phoneNumberInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultPhoneInputOptions: PhoneNumberInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type your phone number...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This phone number doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export type PhoneNumberInputStep = z.infer<typeof phoneNumberInputStepSchema>
|
||||
export type PhoneNumberInputOptions = z.infer<
|
||||
typeof phoneNumberInputOptionsSchema
|
||||
>
|
37
packages/models/src/typebot/steps/input/text.ts
Normal file
37
packages/models/src/typebot/steps/input/text.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
defaultButtonLabel,
|
||||
InputStepType,
|
||||
optionBaseSchema,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
|
||||
export const textInputOptionsBaseSchema = z.object({
|
||||
labels: z.object({
|
||||
placeholder: z.string(),
|
||||
button: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const textInputOptionsSchema = textInputOptionsBaseSchema
|
||||
.and(optionBaseSchema)
|
||||
.and(
|
||||
z.object({
|
||||
isLong: z.boolean(),
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultTextInputOptions: TextInputOptions = {
|
||||
isLong: false,
|
||||
labels: { button: defaultButtonLabel, placeholder: 'Type your answer...' },
|
||||
}
|
||||
|
||||
export const textInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.TEXT]),
|
||||
options: textInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export type TextInputStep = z.infer<typeof textInputSchema>
|
||||
export type TextInputOptions = z.infer<typeof textInputOptionsSchema>
|
35
packages/models/src/typebot/steps/input/url.ts
Normal file
35
packages/models/src/typebot/steps/input/url.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
defaultButtonLabel,
|
||||
InputStepType,
|
||||
optionBaseSchema,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
import { textInputOptionsBaseSchema } from './text'
|
||||
|
||||
export const urlInputOptionsSchema = optionBaseSchema
|
||||
.and(textInputOptionsBaseSchema)
|
||||
.and(
|
||||
z.object({
|
||||
retryMessageContent: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export const urlInputSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([InputStepType.URL]),
|
||||
options: urlInputOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultUrlInputOptions: UrlInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type a URL...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This URL doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export type UrlInputStep = z.infer<typeof urlInputSchema>
|
||||
export type UrlInputOptions = z.infer<typeof urlInputOptionsSchema>
|
@ -1,203 +0,0 @@
|
||||
import { ItemBase, ItemType } from '.'
|
||||
import { StepBase } from './steps'
|
||||
|
||||
export type InputStep =
|
||||
| TextInputStep
|
||||
| NumberInputStep
|
||||
| EmailInputStep
|
||||
| UrlInputStep
|
||||
| DateInputStep
|
||||
| PhoneNumberInputStep
|
||||
| ChoiceInputStep
|
||||
| PaymentInputStep
|
||||
|
||||
export enum InputStepType {
|
||||
TEXT = 'text input',
|
||||
NUMBER = 'number input',
|
||||
EMAIL = 'email input',
|
||||
URL = 'url input',
|
||||
DATE = 'date input',
|
||||
PHONE = 'phone number input',
|
||||
CHOICE = 'choice input',
|
||||
PAYMENT = 'payment input',
|
||||
}
|
||||
|
||||
export type InputStepOptions =
|
||||
| TextInputOptions
|
||||
| NumberInputOptions
|
||||
| EmailInputOptions
|
||||
| DateInputOptions
|
||||
| UrlInputOptions
|
||||
| PhoneNumberInputOptions
|
||||
| ChoiceInputOptions
|
||||
| PaymentInputOptions
|
||||
|
||||
export type TextInputStep = StepBase & {
|
||||
type: InputStepType.TEXT
|
||||
options: TextInputOptions
|
||||
}
|
||||
|
||||
export type NumberInputStep = StepBase & {
|
||||
type: InputStepType.NUMBER
|
||||
options: NumberInputOptions
|
||||
}
|
||||
|
||||
export type EmailInputStep = StepBase & {
|
||||
type: InputStepType.EMAIL
|
||||
options: EmailInputOptions
|
||||
}
|
||||
|
||||
export type UrlInputStep = StepBase & {
|
||||
type: InputStepType.URL
|
||||
options: UrlInputOptions
|
||||
}
|
||||
|
||||
export type DateInputStep = StepBase & {
|
||||
type: InputStepType.DATE
|
||||
options: DateInputOptions
|
||||
}
|
||||
|
||||
export type PhoneNumberInputStep = StepBase & {
|
||||
type: InputStepType.PHONE
|
||||
options: PhoneNumberInputOptions
|
||||
}
|
||||
|
||||
export type ChoiceInputStep = StepBase & {
|
||||
type: InputStepType.CHOICE
|
||||
items: ButtonItem[]
|
||||
options: ChoiceInputOptions
|
||||
}
|
||||
|
||||
export type ButtonItem = ItemBase & {
|
||||
type: ItemType.BUTTON
|
||||
content?: string
|
||||
}
|
||||
|
||||
export type PaymentInputStep = StepBase & {
|
||||
type: InputStepType.PAYMENT
|
||||
options: PaymentInputOptions
|
||||
}
|
||||
|
||||
export type CreditCardDetails = {
|
||||
number: string
|
||||
exp_month: string
|
||||
exp_year: string
|
||||
cvc: string
|
||||
}
|
||||
|
||||
type OptionBase = { variableId?: string }
|
||||
|
||||
type InputTextOptionsBase = {
|
||||
labels: { placeholder: string; button: string }
|
||||
}
|
||||
|
||||
export type ChoiceInputOptions = OptionBase & {
|
||||
isMultipleChoice: boolean
|
||||
buttonLabel: string
|
||||
}
|
||||
|
||||
export type DateInputOptions = OptionBase & {
|
||||
labels: { button: string; from: string; to: string }
|
||||
hasTime: boolean
|
||||
isRange: boolean
|
||||
}
|
||||
|
||||
export type EmailInputOptions = OptionBase & {
|
||||
labels: { placeholder: string; button: string }
|
||||
retryMessageContent: string
|
||||
}
|
||||
|
||||
export type UrlInputOptions = OptionBase & {
|
||||
labels: { placeholder: string; button: string }
|
||||
retryMessageContent: string
|
||||
}
|
||||
|
||||
export type PhoneNumberInputOptions = OptionBase & {
|
||||
labels: { placeholder: string; button: string }
|
||||
retryMessageContent: string
|
||||
defaultCountryCode?: string
|
||||
}
|
||||
|
||||
export type TextInputOptions = OptionBase &
|
||||
InputTextOptionsBase & {
|
||||
isLong: boolean
|
||||
}
|
||||
|
||||
export type NumberInputOptions = OptionBase &
|
||||
InputTextOptionsBase & {
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
}
|
||||
|
||||
export enum PaymentProvider {
|
||||
STRIPE = 'Stripe',
|
||||
}
|
||||
|
||||
export type PaymentInputOptions = OptionBase & {
|
||||
provider: PaymentProvider
|
||||
amount?: string
|
||||
currency: string
|
||||
credentialsId?: string
|
||||
additionalInformation?: {
|
||||
name?: string
|
||||
email?: string
|
||||
phoneNumber?: string
|
||||
}
|
||||
labels: { button: string; success?: string }
|
||||
}
|
||||
|
||||
const defaultButtonLabel = 'Send'
|
||||
|
||||
export const defaultTextInputOptions: TextInputOptions = {
|
||||
isLong: false,
|
||||
labels: { button: defaultButtonLabel, placeholder: 'Type your answer...' },
|
||||
}
|
||||
|
||||
export const defaultNumberInputOptions: NumberInputOptions = {
|
||||
labels: { button: defaultButtonLabel, placeholder: 'Type a number...' },
|
||||
}
|
||||
|
||||
export const defaultEmailInputOptions: EmailInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type your email...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This email doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export const defaultUrlInputOptions: UrlInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type a URL...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This URL doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export const defaultDateInputOptions: DateInputOptions = {
|
||||
hasTime: false,
|
||||
isRange: false,
|
||||
labels: { button: defaultButtonLabel, from: 'From:', to: 'To:' },
|
||||
}
|
||||
|
||||
export const defaultPhoneInputOptions: PhoneNumberInputOptions = {
|
||||
labels: {
|
||||
button: defaultButtonLabel,
|
||||
placeholder: 'Type your phone number...',
|
||||
},
|
||||
retryMessageContent:
|
||||
"This phone number doesn't seem to be valid. Can you type it again?",
|
||||
}
|
||||
|
||||
export const defaultChoiceInputOptions: ChoiceInputOptions = {
|
||||
buttonLabel: defaultButtonLabel,
|
||||
isMultipleChoice: false,
|
||||
}
|
||||
|
||||
export const defaultPaymentInputOptions: PaymentInputOptions = {
|
||||
provider: PaymentProvider.STRIPE,
|
||||
labels: { button: 'Pay', success: 'Success' },
|
||||
currency: 'USD',
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
import { StepBase } from '.'
|
||||
|
||||
export type IntegrationStep =
|
||||
| GoogleSheetsStep
|
||||
| GoogleAnalyticsStep
|
||||
| WebhookStep
|
||||
| SendEmailStep
|
||||
| ZapierStep
|
||||
| MakeComStep
|
||||
| PabblyConnectStep
|
||||
|
||||
export type IntegrationStepOptions =
|
||||
| GoogleSheetsOptions
|
||||
| GoogleAnalyticsOptions
|
||||
| WebhookOptions
|
||||
| SendEmailOptions
|
||||
|
||||
export enum IntegrationStepType {
|
||||
GOOGLE_SHEETS = 'Google Sheets',
|
||||
GOOGLE_ANALYTICS = 'Google Analytics',
|
||||
WEBHOOK = 'Webhook',
|
||||
EMAIL = 'Email',
|
||||
ZAPIER = 'Zapier',
|
||||
MAKE_COM = 'Make.com',
|
||||
PABBLY_CONNECT = 'Pabbly',
|
||||
}
|
||||
|
||||
export type GoogleSheetsStep = StepBase & {
|
||||
type: IntegrationStepType.GOOGLE_SHEETS
|
||||
options: GoogleSheetsOptions
|
||||
}
|
||||
|
||||
export type GoogleAnalyticsStep = StepBase & {
|
||||
type: IntegrationStepType.GOOGLE_ANALYTICS
|
||||
options: GoogleAnalyticsOptions
|
||||
}
|
||||
|
||||
export type WebhookStep = StepBase & {
|
||||
type: IntegrationStepType.WEBHOOK
|
||||
options: WebhookOptions
|
||||
webhookId: string
|
||||
}
|
||||
|
||||
export type ZapierStep = Omit<WebhookStep, 'type'> & {
|
||||
type: IntegrationStepType.ZAPIER
|
||||
}
|
||||
|
||||
export type MakeComStep = Omit<WebhookStep, 'type'> & {
|
||||
type: IntegrationStepType.MAKE_COM
|
||||
}
|
||||
|
||||
export type PabblyConnectStep = Omit<WebhookStep, 'type'> & {
|
||||
type: IntegrationStepType.PABBLY_CONNECT
|
||||
}
|
||||
|
||||
export type SendEmailStep = StepBase & {
|
||||
type: IntegrationStepType.EMAIL
|
||||
options: SendEmailOptions
|
||||
}
|
||||
|
||||
export type SendEmailOptions = {
|
||||
credentialsId: string | 'default'
|
||||
recipients: string[]
|
||||
replyTo?: string
|
||||
cc?: string[]
|
||||
bcc?: string[]
|
||||
subject?: string
|
||||
body?: string
|
||||
}
|
||||
|
||||
export type GoogleAnalyticsOptions = {
|
||||
trackingId?: string
|
||||
category?: string
|
||||
action?: string
|
||||
label?: string
|
||||
value?: number
|
||||
}
|
||||
|
||||
export enum GoogleSheetsAction {
|
||||
GET = 'Get data from sheet',
|
||||
INSERT_ROW = 'Insert a row',
|
||||
UPDATE_ROW = 'Update a row',
|
||||
}
|
||||
|
||||
export type GoogleSheetsOptions =
|
||||
| GoogleSheetsOptionsBase
|
||||
| GoogleSheetsGetOptions
|
||||
| GoogleSheetsInsertRowOptions
|
||||
| GoogleSheetsUpdateRowOptions
|
||||
|
||||
export type GoogleSheetsOptionsBase = {
|
||||
credentialsId?: string
|
||||
spreadsheetId?: string
|
||||
sheetId?: string
|
||||
}
|
||||
|
||||
export type Cell = { id: string; column?: string; value?: string }
|
||||
export type ExtractingCell = {
|
||||
id: string
|
||||
column?: string
|
||||
variableId?: string
|
||||
}
|
||||
|
||||
export type GoogleSheetsGetOptions = NonNullable<GoogleSheetsOptionsBase> & {
|
||||
action: GoogleSheetsAction.GET
|
||||
referenceCell?: Cell
|
||||
cellsToExtract: ExtractingCell[]
|
||||
}
|
||||
|
||||
export type GoogleSheetsInsertRowOptions =
|
||||
NonNullable<GoogleSheetsOptionsBase> & {
|
||||
action: GoogleSheetsAction.INSERT_ROW
|
||||
cellsToInsert: Cell[]
|
||||
}
|
||||
|
||||
export type GoogleSheetsUpdateRowOptions =
|
||||
NonNullable<GoogleSheetsOptionsBase> & {
|
||||
action: GoogleSheetsAction.UPDATE_ROW
|
||||
referenceCell?: Cell
|
||||
cellsToUpsert: Cell[]
|
||||
}
|
||||
|
||||
export type ResponseVariableMapping = {
|
||||
id: string
|
||||
bodyPath?: string
|
||||
variableId?: string
|
||||
}
|
||||
|
||||
export type WebhookOptions = {
|
||||
variablesForTest: VariableForTest[]
|
||||
responseVariableMapping: ResponseVariableMapping[]
|
||||
isAdvancedConfig?: boolean
|
||||
isCustomBody?: boolean
|
||||
}
|
||||
|
||||
export type VariableForTest = {
|
||||
id: string
|
||||
variableId?: string
|
||||
value?: string
|
||||
}
|
||||
|
||||
export const defaultGoogleSheetsOptions: GoogleSheetsOptions = {}
|
||||
|
||||
export const defaultGoogleAnalyticsOptions: GoogleAnalyticsOptions = {}
|
||||
|
||||
export const defaultWebhookOptions: Omit<WebhookOptions, 'webhookId'> = {
|
||||
responseVariableMapping: [],
|
||||
variablesForTest: [],
|
||||
isAdvancedConfig: false,
|
||||
isCustomBody: false,
|
||||
}
|
||||
|
||||
export const defaultSendEmailOptions: SendEmailOptions = {
|
||||
credentialsId: 'default',
|
||||
recipients: [],
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const googleAnalyticsOptionsSchema = z.object({
|
||||
trackingId: z.string().optional(),
|
||||
category: z.string().optional(),
|
||||
action: z.string().optional(),
|
||||
label: z.string().optional(),
|
||||
value: z.number().optional(),
|
||||
})
|
||||
|
||||
export const googleAnalyticsStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.GOOGLE_ANALYTICS]),
|
||||
options: googleAnalyticsOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultGoogleAnalyticsOptions: GoogleAnalyticsOptions = {}
|
||||
|
||||
export type GoogleAnalyticsStep = z.infer<typeof googleAnalyticsStepSchema>
|
||||
export type GoogleAnalyticsOptions = z.infer<
|
||||
typeof googleAnalyticsOptionsSchema
|
||||
>
|
@ -0,0 +1,80 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export enum GoogleSheetsAction {
|
||||
GET = 'Get data from sheet',
|
||||
INSERT_ROW = 'Insert a row',
|
||||
UPDATE_ROW = 'Update a row',
|
||||
}
|
||||
|
||||
const cellSchema = z.object({
|
||||
column: z.string().optional(),
|
||||
value: z.string().optional(),
|
||||
id: z.string(),
|
||||
})
|
||||
|
||||
const extractingCellSchema = z.object({
|
||||
column: z.string().optional(),
|
||||
id: z.string(),
|
||||
variableId: z.string().optional(),
|
||||
})
|
||||
|
||||
const googleSheetsOptionsBaseSchema = z.object({
|
||||
credentialsId: z.string().optional(),
|
||||
sheetId: z.string().optional(),
|
||||
spreadsheetId: z.string().optional(),
|
||||
})
|
||||
|
||||
const googleSheetsGetOptionsSchema = googleSheetsOptionsBaseSchema.and(
|
||||
z.object({
|
||||
action: z.enum([GoogleSheetsAction.GET]),
|
||||
referenceCell: cellSchema.optional(),
|
||||
cellsToExtract: z.array(extractingCellSchema),
|
||||
})
|
||||
)
|
||||
|
||||
const googleSheetsInsertRowOptionsSchema = googleSheetsOptionsBaseSchema.and(
|
||||
z.object({
|
||||
action: z.enum([GoogleSheetsAction.INSERT_ROW]),
|
||||
cellsToInsert: z.array(cellSchema),
|
||||
})
|
||||
)
|
||||
|
||||
const googleSheetsUpdateRowOptionsSchema = googleSheetsOptionsBaseSchema.and(
|
||||
z.object({
|
||||
action: z.enum([GoogleSheetsAction.UPDATE_ROW]),
|
||||
cellsToUpsert: z.array(cellSchema),
|
||||
referenceCell: cellSchema.optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export const googleSheetsOptionsSchema = googleSheetsOptionsBaseSchema
|
||||
.or(googleSheetsGetOptionsSchema)
|
||||
.or(googleSheetsInsertRowOptionsSchema)
|
||||
.or(googleSheetsUpdateRowOptionsSchema)
|
||||
|
||||
export const googleSheetsStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.GOOGLE_SHEETS]),
|
||||
options: googleSheetsOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultGoogleSheetsOptions: GoogleSheetsOptions = {}
|
||||
|
||||
export type GoogleSheetsStep = z.infer<typeof googleSheetsStepSchema>
|
||||
export type GoogleSheetsOptions = z.infer<typeof googleSheetsOptionsSchema>
|
||||
export type GoogleSheetsOptionsBase = z.infer<
|
||||
typeof googleSheetsOptionsBaseSchema
|
||||
>
|
||||
export type GoogleSheetsGetOptions = z.infer<
|
||||
typeof googleSheetsGetOptionsSchema
|
||||
>
|
||||
export type GoogleSheetsInsertRowOptions = z.infer<
|
||||
typeof googleSheetsInsertRowOptionsSchema
|
||||
>
|
||||
export type GoogleSheetsUpdateRowOptions = z.infer<
|
||||
typeof googleSheetsUpdateRowOptionsSchema
|
||||
>
|
||||
export type Cell = z.infer<typeof cellSchema>
|
||||
export type ExtractingCell = z.infer<typeof extractingCellSchema>
|
8
packages/models/src/typebot/steps/integration/index.ts
Normal file
8
packages/models/src/typebot/steps/integration/index.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export * from './integration'
|
||||
export * from './webhook'
|
||||
export * from './googleAnalytics'
|
||||
export * from './pabblyConnect'
|
||||
export * from './makeCom'
|
||||
export * from './zapier'
|
||||
export * from './sendEmail'
|
||||
export * from './googleSheets'
|
32
packages/models/src/typebot/steps/integration/integration.ts
Normal file
32
packages/models/src/typebot/steps/integration/integration.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
googleAnalyticsOptionsSchema,
|
||||
googleAnalyticsStepSchema,
|
||||
} from './googleAnalytics'
|
||||
import {
|
||||
googleSheetsOptionsSchema,
|
||||
googleSheetsStepSchema,
|
||||
} from './googleSheets'
|
||||
import { makeComStepSchema } from './makeCom'
|
||||
import { pabblyConnectStepSchema } from './pabblyConnect'
|
||||
import { sendEmailOptionsSchema, sendEmailStepSchema } from './sendEmail'
|
||||
import { webhookOptionsSchema, webhookStepSchema } from './webhook'
|
||||
import { zapierStepSchema } from './zapier'
|
||||
|
||||
const integrationStepOptionsSchema = googleSheetsOptionsSchema
|
||||
.or(googleAnalyticsOptionsSchema)
|
||||
.or(webhookOptionsSchema)
|
||||
.or(sendEmailOptionsSchema)
|
||||
|
||||
export const integrationStepSchema = googleSheetsStepSchema
|
||||
.or(googleAnalyticsStepSchema)
|
||||
.or(webhookStepSchema)
|
||||
.or(sendEmailStepSchema)
|
||||
.or(zapierStepSchema)
|
||||
.or(makeComStepSchema)
|
||||
.or(pabblyConnectStepSchema)
|
||||
|
||||
export type IntegrationStep = z.infer<typeof integrationStepSchema>
|
||||
export type IntegrationStepOptions = z.infer<
|
||||
typeof integrationStepOptionsSchema
|
||||
>
|
13
packages/models/src/typebot/steps/integration/makeCom.ts
Normal file
13
packages/models/src/typebot/steps/integration/makeCom.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
import { webhookOptionsSchema } from './webhook'
|
||||
|
||||
export const makeComStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.MAKE_COM]),
|
||||
options: webhookOptionsSchema,
|
||||
webhookId: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export type MakeComStep = z.infer<typeof makeComStepSchema>
|
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
import { webhookOptionsSchema } from './webhook'
|
||||
|
||||
export const pabblyConnectStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.PABBLY_CONNECT]),
|
||||
options: webhookOptionsSchema,
|
||||
webhookId: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export type PabblyConnectStep = z.infer<typeof pabblyConnectStepSchema>
|
27
packages/models/src/typebot/steps/integration/sendEmail.ts
Normal file
27
packages/models/src/typebot/steps/integration/sendEmail.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const sendEmailOptionsSchema = z.object({
|
||||
credentialsId: z.string(),
|
||||
recipients: z.array(z.string()),
|
||||
subject: z.string().optional(),
|
||||
body: z.string().optional(),
|
||||
replyTo: z.string().optional(),
|
||||
cc: z.array(z.string()).optional(),
|
||||
bcc: z.array(z.string()).optional(),
|
||||
})
|
||||
|
||||
export const sendEmailStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.EMAIL]),
|
||||
options: sendEmailOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultSendEmailOptions: SendEmailOptions = {
|
||||
credentialsId: 'default',
|
||||
recipients: [],
|
||||
}
|
||||
|
||||
export type SendEmailStep = z.infer<typeof sendEmailStepSchema>
|
||||
export type SendEmailOptions = z.infer<typeof sendEmailOptionsSchema>
|
43
packages/models/src/typebot/steps/integration/webhook.ts
Normal file
43
packages/models/src/typebot/steps/integration/webhook.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
const variableForTestSchema = z.object({
|
||||
id: z.string(),
|
||||
variableId: z.string().optional(),
|
||||
value: z.string().optional(),
|
||||
})
|
||||
|
||||
const responseVariableMappingSchema = z.object({
|
||||
id: z.string(),
|
||||
variableId: z.string().optional(),
|
||||
bodyPath: z.string().optional(),
|
||||
})
|
||||
|
||||
export const webhookOptionsSchema = z.object({
|
||||
variablesForTest: z.array(variableForTestSchema),
|
||||
responseVariableMapping: z.array(responseVariableMappingSchema),
|
||||
isAdvancedConfig: z.boolean().optional(),
|
||||
isCustomBody: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const webhookStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.WEBHOOK]),
|
||||
options: webhookOptionsSchema,
|
||||
webhookId: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultWebhookOptions: Omit<WebhookOptions, 'webhookId'> = {
|
||||
responseVariableMapping: [],
|
||||
variablesForTest: [],
|
||||
isAdvancedConfig: false,
|
||||
isCustomBody: false,
|
||||
}
|
||||
|
||||
export type WebhookStep = z.infer<typeof webhookStepSchema>
|
||||
export type WebhookOptions = z.infer<typeof webhookOptionsSchema>
|
||||
export type ResponseVariableMapping = z.infer<
|
||||
typeof responseVariableMappingSchema
|
||||
>
|
||||
export type VariableForTest = z.infer<typeof variableForTestSchema>
|
13
packages/models/src/typebot/steps/integration/zapier.ts
Normal file
13
packages/models/src/typebot/steps/integration/zapier.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod'
|
||||
import { IntegrationStepType, stepBaseSchema } from '../shared'
|
||||
import { webhookOptionsSchema } from './webhook'
|
||||
|
||||
export const zapierStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([IntegrationStepType.ZAPIER]),
|
||||
options: webhookOptionsSchema,
|
||||
webhookId: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export type ZapierStep = z.infer<typeof zapierStepSchema>
|
@ -1,20 +1,14 @@
|
||||
import { ButtonItem, ConditionItem } from '.'
|
||||
|
||||
export type Item = ButtonItem | ConditionItem
|
||||
|
||||
export enum ItemType {
|
||||
BUTTON,
|
||||
CONDITION,
|
||||
}
|
||||
|
||||
export type ItemBase = {
|
||||
id: string
|
||||
stepId: string
|
||||
outgoingEdgeId?: string
|
||||
}
|
||||
import { z } from 'zod'
|
||||
import { itemBaseSchema } from './shared'
|
||||
import { buttonItemSchema } from './input'
|
||||
import { conditionItemSchema } from './logic'
|
||||
|
||||
export type ItemIndices = {
|
||||
blockIndex: number
|
||||
stepIndex: number
|
||||
itemIndex: number
|
||||
}
|
||||
const itemScema = buttonItemSchema.or(conditionItemSchema)
|
||||
|
||||
export type ItemBase = z.infer<typeof itemBaseSchema>
|
||||
export type Item = z.infer<typeof itemScema>
|
||||
|
@ -1,113 +0,0 @@
|
||||
import { ItemType, StepBase } from '.'
|
||||
import { ItemBase } from './item'
|
||||
|
||||
export type LogicStep =
|
||||
| SetVariableStep
|
||||
| ConditionStep
|
||||
| RedirectStep
|
||||
| CodeStep
|
||||
| TypebotLinkStep
|
||||
|
||||
export type LogicStepOptions =
|
||||
| SetVariableOptions
|
||||
| RedirectOptions
|
||||
| CodeOptions
|
||||
| TypebotLinkOptions
|
||||
|
||||
export enum LogicStepType {
|
||||
SET_VARIABLE = 'Set variable',
|
||||
CONDITION = 'Condition',
|
||||
REDIRECT = 'Redirect',
|
||||
CODE = 'Code',
|
||||
TYPEBOT_LINK = 'Typebot link',
|
||||
}
|
||||
|
||||
export type SetVariableStep = StepBase & {
|
||||
type: LogicStepType.SET_VARIABLE
|
||||
options: SetVariableOptions
|
||||
}
|
||||
|
||||
export type ConditionStep = StepBase & {
|
||||
type: LogicStepType.CONDITION
|
||||
items: [ConditionItem]
|
||||
}
|
||||
|
||||
export type ConditionItem = ItemBase & {
|
||||
type: ItemType.CONDITION
|
||||
content: ConditionContent
|
||||
}
|
||||
|
||||
export type RedirectStep = StepBase & {
|
||||
type: LogicStepType.REDIRECT
|
||||
options: RedirectOptions
|
||||
}
|
||||
|
||||
export type CodeStep = StepBase & {
|
||||
type: LogicStepType.CODE
|
||||
options: CodeOptions
|
||||
}
|
||||
|
||||
export type TypebotLinkStep = StepBase & {
|
||||
type: LogicStepType.TYPEBOT_LINK
|
||||
options: TypebotLinkOptions
|
||||
}
|
||||
|
||||
export enum LogicalOperator {
|
||||
OR = 'OR',
|
||||
AND = 'AND',
|
||||
}
|
||||
|
||||
export enum ComparisonOperators {
|
||||
EQUAL = 'Equal to',
|
||||
NOT_EQUAL = 'Not equal',
|
||||
CONTAINS = 'Contains',
|
||||
GREATER = 'Greater than',
|
||||
LESS = 'Less than',
|
||||
IS_SET = 'Is set',
|
||||
}
|
||||
|
||||
export type ConditionContent = {
|
||||
comparisons: Comparison[]
|
||||
logicalOperator: LogicalOperator
|
||||
}
|
||||
|
||||
export type Comparison = {
|
||||
id: string
|
||||
variableId?: string
|
||||
comparisonOperator?: ComparisonOperators
|
||||
value?: string
|
||||
}
|
||||
|
||||
export type SetVariableOptions = {
|
||||
variableId?: string
|
||||
expressionToEvaluate?: string
|
||||
isCode?: boolean
|
||||
}
|
||||
|
||||
export type RedirectOptions = {
|
||||
url?: string
|
||||
isNewTab: boolean
|
||||
}
|
||||
|
||||
export type CodeOptions = {
|
||||
name: string
|
||||
content?: string
|
||||
}
|
||||
|
||||
export type TypebotLinkOptions = {
|
||||
typebotId?: string | 'current'
|
||||
blockId?: string
|
||||
}
|
||||
|
||||
export const defaultSetVariablesOptions: SetVariableOptions = {}
|
||||
|
||||
export const defaultConditionContent: ConditionContent = {
|
||||
comparisons: [],
|
||||
logicalOperator: LogicalOperator.AND,
|
||||
}
|
||||
|
||||
export const defaultRedirectOptions: RedirectOptions = { isNewTab: false }
|
||||
|
||||
export const defaultCodeOptions: CodeOptions = { name: 'Code snippet' }
|
||||
|
||||
export const defaultTypebotLinkOptions: TypebotLinkOptions = {}
|
19
packages/models/src/typebot/steps/logic/code.ts
Normal file
19
packages/models/src/typebot/steps/logic/code.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod'
|
||||
import { LogicStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const codeOptionsSchema = z.object({
|
||||
name: z.string(),
|
||||
content: z.string().optional(),
|
||||
})
|
||||
|
||||
export const codeStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([LogicStepType.CODE]),
|
||||
options: codeOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultCodeOptions: CodeOptions = { name: 'Code snippet' }
|
||||
|
||||
export type CodeStep = z.infer<typeof codeStepSchema>
|
||||
export type CodeOptions = z.infer<typeof codeOptionsSchema>
|
58
packages/models/src/typebot/steps/logic/condition.ts
Normal file
58
packages/models/src/typebot/steps/logic/condition.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
itemBaseSchema,
|
||||
ItemType,
|
||||
LogicStepType,
|
||||
stepBaseSchema,
|
||||
} from '../shared'
|
||||
|
||||
export enum LogicalOperator {
|
||||
OR = 'OR',
|
||||
AND = 'AND',
|
||||
}
|
||||
|
||||
export enum ComparisonOperators {
|
||||
EQUAL = 'Equal to',
|
||||
NOT_EQUAL = 'Not equal',
|
||||
CONTAINS = 'Contains',
|
||||
GREATER = 'Greater than',
|
||||
LESS = 'Less than',
|
||||
IS_SET = 'Is set',
|
||||
}
|
||||
|
||||
const comparisonSchema = z.object({
|
||||
id: z.string(),
|
||||
variableId: z.string().optional(),
|
||||
comparisonOperator: z.nativeEnum(ComparisonOperators).optional(),
|
||||
value: z.string().optional(),
|
||||
})
|
||||
|
||||
const conditionContentSchema = z.object({
|
||||
logicalOperator: z.nativeEnum(LogicalOperator),
|
||||
comparisons: z.array(comparisonSchema),
|
||||
})
|
||||
|
||||
export const conditionItemSchema = itemBaseSchema.and(
|
||||
z.object({
|
||||
type: z.literal(ItemType.CONDITION),
|
||||
content: conditionContentSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const conditionStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([LogicStepType.CONDITION]),
|
||||
items: z.array(conditionItemSchema),
|
||||
options: z.object({}),
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultConditionContent: ConditionContent = {
|
||||
comparisons: [],
|
||||
logicalOperator: LogicalOperator.AND,
|
||||
}
|
||||
|
||||
export type ConditionItem = z.infer<typeof conditionItemSchema>
|
||||
export type Comparison = z.infer<typeof comparisonSchema>
|
||||
export type ConditionStep = z.infer<typeof conditionStepSchema>
|
||||
export type ConditionContent = z.infer<typeof conditionContentSchema>
|
6
packages/models/src/typebot/steps/logic/index.ts
Normal file
6
packages/models/src/typebot/steps/logic/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export * from './logic'
|
||||
export * from './code'
|
||||
export * from './condition'
|
||||
export * from './redirect'
|
||||
export * from './setVariable'
|
||||
export * from './typebotLink'
|
20
packages/models/src/typebot/steps/logic/logic.ts
Normal file
20
packages/models/src/typebot/steps/logic/logic.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { z } from 'zod'
|
||||
import { codeOptionsSchema, codeStepSchema } from './code'
|
||||
import { conditionStepSchema } from './condition'
|
||||
import { redirectOptionsSchema, redirectStepSchema } from './redirect'
|
||||
import { setVariableOptionsSchema, setVariableStepSchema } from './setVariable'
|
||||
import { typebotLinkOptionsSchema, typebotLinkStepSchema } from './typebotLink'
|
||||
|
||||
const logicStepOptionsSchema = codeOptionsSchema
|
||||
.or(redirectOptionsSchema)
|
||||
.or(setVariableOptionsSchema)
|
||||
.or(typebotLinkOptionsSchema)
|
||||
|
||||
export const logicStepSchema = codeStepSchema
|
||||
.or(conditionStepSchema)
|
||||
.or(redirectStepSchema)
|
||||
.or(typebotLinkStepSchema)
|
||||
.or(setVariableStepSchema)
|
||||
|
||||
export type LogicStep = z.infer<typeof logicStepSchema>
|
||||
export type LogicStepOptions = z.infer<typeof logicStepOptionsSchema>
|
19
packages/models/src/typebot/steps/logic/redirect.ts
Normal file
19
packages/models/src/typebot/steps/logic/redirect.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod'
|
||||
import { LogicStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const redirectOptionsSchema = z.object({
|
||||
url: z.string().optional(),
|
||||
isNewTab: z.boolean(),
|
||||
})
|
||||
|
||||
export const redirectStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([LogicStepType.REDIRECT]),
|
||||
options: redirectOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultRedirectOptions: RedirectOptions = { isNewTab: false }
|
||||
|
||||
export type RedirectStep = z.infer<typeof redirectStepSchema>
|
||||
export type RedirectOptions = z.infer<typeof redirectOptionsSchema>
|
20
packages/models/src/typebot/steps/logic/setVariable.ts
Normal file
20
packages/models/src/typebot/steps/logic/setVariable.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { z } from 'zod'
|
||||
import { LogicStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const setVariableOptionsSchema = z.object({
|
||||
variableId: z.string().optional(),
|
||||
expressionToEvaluate: z.string().optional(),
|
||||
isCode: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const setVariableStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([LogicStepType.SET_VARIABLE]),
|
||||
options: setVariableOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultSetVariablesOptions: SetVariableOptions = {}
|
||||
|
||||
export type SetVariableStep = z.infer<typeof setVariableStepSchema>
|
||||
export type SetVariableOptions = z.infer<typeof setVariableOptionsSchema>
|
19
packages/models/src/typebot/steps/logic/typebotLink.ts
Normal file
19
packages/models/src/typebot/steps/logic/typebotLink.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod'
|
||||
import { LogicStepType, stepBaseSchema } from '../shared'
|
||||
|
||||
export const typebotLinkOptionsSchema = z.object({
|
||||
typebotId: z.string().optional(),
|
||||
blockId: z.string().optional(),
|
||||
})
|
||||
|
||||
export const typebotLinkStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.enum([LogicStepType.TYPEBOT_LINK]),
|
||||
options: typebotLinkOptionsSchema,
|
||||
})
|
||||
)
|
||||
|
||||
export const defaultTypebotLinkOptions: TypebotLinkOptions = {}
|
||||
|
||||
export type TypebotLinkStep = z.infer<typeof typebotLinkStepSchema>
|
||||
export type TypebotLinkOptions = z.infer<typeof typebotLinkOptionsSchema>
|
60
packages/models/src/typebot/steps/shared.ts
Normal file
60
packages/models/src/typebot/steps/shared.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const stepBaseSchema = z.object({
|
||||
id: z.string(),
|
||||
blockId: z.string(),
|
||||
outgoingEdgeId: z.string().optional(),
|
||||
})
|
||||
|
||||
export const defaultButtonLabel = 'Send'
|
||||
|
||||
export const optionBaseSchema = z.object({
|
||||
variableId: z.string().optional(),
|
||||
})
|
||||
|
||||
export const itemBaseSchema = z.object({
|
||||
id: z.string(),
|
||||
stepId: z.string(),
|
||||
outgoingEdgeId: z.string().optional(),
|
||||
})
|
||||
|
||||
export enum ItemType {
|
||||
BUTTON,
|
||||
CONDITION,
|
||||
}
|
||||
|
||||
export enum BubbleStepType {
|
||||
TEXT = 'text',
|
||||
IMAGE = 'image',
|
||||
VIDEO = 'video',
|
||||
EMBED = 'embed',
|
||||
}
|
||||
|
||||
export enum InputStepType {
|
||||
TEXT = 'text input',
|
||||
NUMBER = 'number input',
|
||||
EMAIL = 'email input',
|
||||
URL = 'url input',
|
||||
DATE = 'date input',
|
||||
PHONE = 'phone number input',
|
||||
CHOICE = 'choice input',
|
||||
PAYMENT = 'payment input',
|
||||
}
|
||||
|
||||
export enum LogicStepType {
|
||||
SET_VARIABLE = 'Set variable',
|
||||
CONDITION = 'Condition',
|
||||
REDIRECT = 'Redirect',
|
||||
CODE = 'Code',
|
||||
TYPEBOT_LINK = 'Typebot link',
|
||||
}
|
||||
|
||||
export enum IntegrationStepType {
|
||||
GOOGLE_SHEETS = 'Google Sheets',
|
||||
GOOGLE_ANALYTICS = 'Google Analytics',
|
||||
WEBHOOK = 'Webhook',
|
||||
EMAIL = 'Email',
|
||||
ZAPIER = 'Zapier',
|
||||
MAKE_COM = 'Make.com',
|
||||
PABBLY_CONNECT = 'Pabbly',
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
import {
|
||||
InputStepOptions,
|
||||
IntegrationStepOptions,
|
||||
IntegrationStepType,
|
||||
Item,
|
||||
LogicStepOptions,
|
||||
} from '.'
|
||||
import { BubbleStep, BubbleStepType } from './bubble'
|
||||
import { InputStep, InputStepType } from './inputs'
|
||||
import { IntegrationStep } from './integration'
|
||||
import { ConditionStep, LogicStep, LogicStepType } from './logic'
|
||||
|
||||
export type Step =
|
||||
| StartStep
|
||||
| BubbleStep
|
||||
| InputStep
|
||||
| LogicStep
|
||||
| IntegrationStep
|
||||
import { BubbleStep, bubbleStepSchema } from './bubble'
|
||||
import { InputStep, inputStepSchema } from './input'
|
||||
import { IntegrationStep, integrationStepSchema } from './integration'
|
||||
import { ConditionStep, LogicStep, logicStepSchema } from './logic'
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
BubbleStepType,
|
||||
InputStepType,
|
||||
IntegrationStepType,
|
||||
LogicStepType,
|
||||
stepBaseSchema,
|
||||
} from './shared'
|
||||
|
||||
export type DraggableStep = BubbleStep | InputStep | LogicStep | IntegrationStep
|
||||
|
||||
@ -49,14 +49,26 @@ export type StepOptions =
|
||||
|
||||
export type StepWithItems = Omit<Step, 'items'> & { items: Item[] }
|
||||
|
||||
export type StepBase = { id: string; blockId: string; outgoingEdgeId?: string }
|
||||
export type StepBase = z.infer<typeof stepBaseSchema>
|
||||
|
||||
export type StartStep = StepBase & {
|
||||
type: 'start'
|
||||
label: string
|
||||
}
|
||||
const startStepSchema = stepBaseSchema.and(
|
||||
z.object({
|
||||
type: z.literal('start'),
|
||||
label: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export type StartStep = z.infer<typeof startStepSchema>
|
||||
|
||||
export type StepIndices = {
|
||||
blockIndex: number
|
||||
stepIndex: number
|
||||
}
|
||||
|
||||
export const stepSchema = startStepSchema
|
||||
.or(bubbleStepSchema)
|
||||
.or(inputStepSchema)
|
||||
.or(logicStepSchema)
|
||||
.or(integrationStepSchema)
|
||||
|
||||
export type Step = z.infer<typeof stepSchema>
|
||||
|
@ -1,36 +1,29 @@
|
||||
export type Theme = {
|
||||
general: GeneralTheme
|
||||
chat: ChatTheme
|
||||
customCss?: string
|
||||
}
|
||||
import { z } from 'zod'
|
||||
|
||||
export type GeneralTheme = {
|
||||
font: string
|
||||
background: Background
|
||||
}
|
||||
const avatarPropsSchema = z.object({
|
||||
isEnabled: z.boolean(),
|
||||
url: z.string().optional(),
|
||||
})
|
||||
|
||||
export type AvatarProps = {
|
||||
isEnabled: boolean
|
||||
url?: string
|
||||
}
|
||||
const containerColorsSchema = z.object({
|
||||
backgroundColor: z.string(),
|
||||
color: z.string(),
|
||||
})
|
||||
|
||||
export type ChatTheme = {
|
||||
hostAvatar?: AvatarProps
|
||||
guestAvatar?: AvatarProps
|
||||
hostBubbles: ContainerColors
|
||||
guestBubbles: ContainerColors
|
||||
buttons: ContainerColors
|
||||
inputs: InputColors
|
||||
}
|
||||
const inputColorsSchema = containerColorsSchema.and(
|
||||
z.object({
|
||||
placeholderColor: z.string(),
|
||||
})
|
||||
)
|
||||
|
||||
export type ContainerColors = {
|
||||
backgroundColor: string
|
||||
color: string
|
||||
}
|
||||
|
||||
export type InputColors = ContainerColors & {
|
||||
placeholderColor: string
|
||||
}
|
||||
const chatThemeSchema = z.object({
|
||||
hostAvatar: avatarPropsSchema.optional(),
|
||||
guestAvatar: avatarPropsSchema.optional(),
|
||||
hostBubbles: containerColorsSchema,
|
||||
guestBubbles: containerColorsSchema,
|
||||
buttons: containerColorsSchema,
|
||||
inputs: inputColorsSchema,
|
||||
})
|
||||
|
||||
export enum BackgroundType {
|
||||
COLOR = 'Color',
|
||||
@ -38,10 +31,21 @@ export enum BackgroundType {
|
||||
NONE = 'None',
|
||||
}
|
||||
|
||||
export type Background = {
|
||||
type: BackgroundType
|
||||
content?: string
|
||||
}
|
||||
const backgroundSchema = z.object({
|
||||
type: z.nativeEnum(BackgroundType),
|
||||
content: z.string().optional(),
|
||||
})
|
||||
|
||||
const generalThemeSchema = z.object({
|
||||
font: z.string(),
|
||||
background: backgroundSchema,
|
||||
})
|
||||
|
||||
export const themeSchema = z.object({
|
||||
general: generalThemeSchema,
|
||||
chat: chatThemeSchema,
|
||||
customCss: z.string().optional(),
|
||||
})
|
||||
|
||||
export const defaultTheme: Theme = {
|
||||
chat: {
|
||||
@ -56,3 +60,11 @@ export const defaultTheme: Theme = {
|
||||
},
|
||||
general: { font: 'Open Sans', background: { type: BackgroundType.NONE } },
|
||||
}
|
||||
|
||||
export type Theme = z.infer<typeof themeSchema>
|
||||
export type ChatTheme = z.infer<typeof chatThemeSchema>
|
||||
export type AvatarProps = z.infer<typeof avatarPropsSchema>
|
||||
export type GeneralTheme = z.infer<typeof generalThemeSchema>
|
||||
export type Background = z.infer<typeof backgroundSchema>
|
||||
export type ContainerColors = z.infer<typeof containerColorsSchema>
|
||||
export type InputColors = z.infer<typeof inputColorsSchema>
|
||||
|
@ -1,46 +1,56 @@
|
||||
import { Typebot as TypebotFromPrisma } from 'db'
|
||||
import { Settings } from './settings'
|
||||
import { Step } from './steps/steps'
|
||||
import { Theme } from './theme'
|
||||
import { Variable } from './variable'
|
||||
import { z } from 'zod'
|
||||
import { settingsSchema } from './settings'
|
||||
import { stepSchema } from './steps'
|
||||
import { themeSchema } from './theme'
|
||||
import { variableSchema } from './variable'
|
||||
|
||||
export type Typebot = Omit<
|
||||
TypebotFromPrisma,
|
||||
| 'blocks'
|
||||
| 'theme'
|
||||
| 'settings'
|
||||
| 'variables'
|
||||
| 'edges'
|
||||
| 'createdAt'
|
||||
| 'updatedAt'
|
||||
> & {
|
||||
blocks: Block[]
|
||||
variables: Variable[]
|
||||
edges: Edge[]
|
||||
theme: Theme
|
||||
settings: Settings
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
const blockSchema = z.object({
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
graphCoordinates: z.object({
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
}),
|
||||
steps: z.array(stepSchema),
|
||||
})
|
||||
|
||||
export type Block = {
|
||||
id: string
|
||||
title: string
|
||||
graphCoordinates: {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
steps: Step[]
|
||||
}
|
||||
const sourceSchema = z.object({
|
||||
blockId: z.string(),
|
||||
stepId: z.string(),
|
||||
itemId: z.string().optional(),
|
||||
})
|
||||
|
||||
export type Source = {
|
||||
blockId: string
|
||||
stepId: string
|
||||
itemId?: string
|
||||
}
|
||||
export type Target = { blockId: string; stepId?: string }
|
||||
export type Edge = {
|
||||
id: string
|
||||
from: Source
|
||||
to: Target
|
||||
}
|
||||
const targetSchema = z.object({
|
||||
blockId: z.string(),
|
||||
stepId: z.string().optional(),
|
||||
})
|
||||
|
||||
const edgeSchema = z.object({
|
||||
id: z.string(),
|
||||
from: sourceSchema,
|
||||
to: targetSchema,
|
||||
})
|
||||
|
||||
const typebotSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
blocks: z.array(blockSchema),
|
||||
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(),
|
||||
})
|
||||
|
||||
export type Typebot = z.infer<typeof typebotSchema>
|
||||
export type Target = z.infer<typeof targetSchema>
|
||||
export type Source = z.infer<typeof sourceSchema>
|
||||
export type Edge = z.infer<typeof edgeSchema>
|
||||
export type Block = z.infer<typeof blockSchema>
|
||||
|
@ -1,9 +1,12 @@
|
||||
export type Variable = {
|
||||
id: string
|
||||
name: string
|
||||
value?: string | number
|
||||
}
|
||||
import { z } from 'zod'
|
||||
|
||||
export const variableSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
value: z.string().or(z.number()).optional(),
|
||||
})
|
||||
|
||||
export type VariableWithValue = Omit<Variable, 'value'> & {
|
||||
value: string
|
||||
}
|
||||
export type Variable = z.infer<typeof variableSchema>
|
||||
|
@ -1,13 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"declaration": true,
|
||||
"declarationDir": "./dist/types",
|
||||
"outDir": "./dist"
|
||||
"declarationDir": "types",
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"emitDeclarationOnly": true
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,10 @@
|
||||
"models": "*",
|
||||
"next": "^12.1.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12.1.6",
|
||||
"models": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn rollup -c",
|
||||
"dx": "yarn rollup -c --watch"
|
||||
|
@ -25,7 +25,7 @@ export default [
|
||||
],
|
||||
plugins: [
|
||||
peerDepsExternal(),
|
||||
resolve({ preferBuiltins: true }),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
typescript({ tsconfig: './tsconfig.json' }),
|
||||
],
|
||||
|
@ -1,19 +1,23 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export const methodNotAllowed = (res: NextApiResponse) =>
|
||||
res.status(405).json({ message: 'Method Not Allowed' })
|
||||
export const methodNotAllowed = (
|
||||
res: NextApiResponse,
|
||||
customMessage?: string
|
||||
) => res.status(405).json({ message: customMessage ?? 'Method Not Allowed' })
|
||||
|
||||
export const notAuthenticated = (res: NextApiResponse) =>
|
||||
res.status(401).json({ message: 'Not authenticated' })
|
||||
export const notAuthenticated = (
|
||||
res: NextApiResponse,
|
||||
customMessage?: string
|
||||
) => res.status(401).json({ message: customMessage ?? 'Not authenticated' })
|
||||
|
||||
export const notFound = (res: NextApiResponse) =>
|
||||
res.status(404).json({ message: 'Not found' })
|
||||
export const notFound = (res: NextApiResponse, customMessage?: string) =>
|
||||
res.status(404).json({ message: customMessage ?? 'Not found' })
|
||||
|
||||
export const badRequest = (res: NextApiResponse) =>
|
||||
res.status(400).json({ message: 'Bad Request' })
|
||||
export const badRequest = (res: NextApiResponse, customMessage?: any) =>
|
||||
res.status(400).json({ message: customMessage ?? 'Bad Request' })
|
||||
|
||||
export const forbidden = (res: NextApiResponse) =>
|
||||
res.status(403).json({ message: 'Bad Request' })
|
||||
export const forbidden = (res: NextApiResponse, customMessage?: string) =>
|
||||
res.status(403).json({ message: customMessage ?? 'Bad Request' })
|
||||
|
||||
export const initMiddleware =
|
||||
(
|
||||
|
@ -15406,6 +15406,11 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zod@^3.17.3:
|
||||
version "3.17.3"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.17.3.tgz#86abbc670ff0063a4588d85a4dcc917d6e4af2ba"
|
||||
integrity sha512-4oKP5zvG6GGbMlqBkI5FESOAweldEhSOZ6LI6cG+JzUT7ofj1ZOC0PJudpQOpT1iqOFpYYtX5Pw0+o403y4bcg==
|
||||
|
||||
zustand@^3.4.2, zustand@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d"
|
||||
|
Reference in New Issue
Block a user