refactor(models): 🎨 Build types from validation schemas
This commit is contained in:
@ -5,7 +5,7 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { byId, isNotEmpty } from 'utils'
|
import { byId } from 'utils'
|
||||||
import { MemberInWorkspace, Plan, Workspace, WorkspaceRole } from 'db'
|
import { MemberInWorkspace, Plan, Workspace, WorkspaceRole } from 'db'
|
||||||
import {
|
import {
|
||||||
createNewWorkspace,
|
createNewWorkspace,
|
||||||
@ -87,8 +87,11 @@ export const WorkspaceContext = ({ children }: { children: ReactNode }) => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [typebot?.workspaceId])
|
}, [typebot?.workspaceId])
|
||||||
|
|
||||||
const switchWorkspace = (workspaceId: string) =>
|
const switchWorkspace = (workspaceId: string) => {
|
||||||
setCurrentWorkspace(workspaces?.find(byId(workspaceId)))
|
const newWorkspace = workspaces?.find(byId(workspaceId))
|
||||||
|
if (!newWorkspace) return
|
||||||
|
setCurrentWorkspace(newWorkspace)
|
||||||
|
}
|
||||||
|
|
||||||
const createWorkspace = async (name?: string) => {
|
const createWorkspace = async (name?: string) => {
|
||||||
if (!workspaces) return
|
if (!workspaces) return
|
||||||
|
@ -70,11 +70,13 @@ export const ResultsContent = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex pt={['10px', '60px']} w="full" justify="center">
|
<Flex pt={['10px', '60px']} w="full" justify="center">
|
||||||
{publishedTypebot &&
|
{workspace &&
|
||||||
|
publishedTypebot &&
|
||||||
(isAnalytics ? (
|
(isAnalytics ? (
|
||||||
<AnalyticsContent stats={stats} />
|
<AnalyticsContent stats={stats} />
|
||||||
) : (
|
) : (
|
||||||
<SubmissionsContent
|
<SubmissionsContent
|
||||||
|
workspaceId={workspace.id}
|
||||||
typebotId={publishedTypebot.typebotId}
|
typebotId={publishedTypebot.typebotId}
|
||||||
onDeleteResults={handleDeletedResults}
|
onDeleteResults={handleDeletedResults}
|
||||||
totalResults={stats?.totalStarts ?? 0}
|
totalResults={stats?.totalStarts ?? 0}
|
||||||
|
@ -18,12 +18,14 @@ import { Plan } from 'db'
|
|||||||
import { useToast } from 'components/shared/hooks/useToast'
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
workspaceId: string
|
||||||
typebotId: string
|
typebotId: string
|
||||||
totalResults: number
|
totalResults: number
|
||||||
totalHiddenResults?: number
|
totalHiddenResults?: number
|
||||||
onDeleteResults: (total: number) => void
|
onDeleteResults: (total: number) => void
|
||||||
}
|
}
|
||||||
export const SubmissionsContent = ({
|
export const SubmissionsContent = ({
|
||||||
|
workspaceId,
|
||||||
typebotId,
|
typebotId,
|
||||||
totalResults,
|
totalResults,
|
||||||
totalHiddenResults,
|
totalHiddenResults,
|
||||||
@ -51,6 +53,7 @@ export const SubmissionsContent = ({
|
|||||||
const resultHeader = parseResultHeader(blocksAndVariables)
|
const resultHeader = parseResultHeader(blocksAndVariables)
|
||||||
|
|
||||||
const { data, mutate, setSize, hasMore } = useResults({
|
const { data, mutate, setSize, hasMore } = useResults({
|
||||||
|
workspaceId,
|
||||||
typebotId,
|
typebotId,
|
||||||
onError: (err) => showToast({ title: err.name, description: err.message }),
|
onError: (err) => showToast({ title: err.name, description: err.message }),
|
||||||
})
|
})
|
||||||
@ -125,7 +128,7 @@ export const SubmissionsContent = ({
|
|||||||
|
|
||||||
const getAllTableData = async () => {
|
const getAllTableData = async () => {
|
||||||
if (!publishedTypebot) return []
|
if (!publishedTypebot) return []
|
||||||
const results = await getAllResults(typebotId)
|
const results = await getAllResults(workspaceId, typebotId)
|
||||||
return convertResultsToTableData(results, resultHeader)
|
return convertResultsToTableData(results, resultHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,19 @@ import { NextApiRequest, NextApiResponse } from 'next'
|
|||||||
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { isFreePlan } from 'services/workspace'
|
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 handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
const workspaceId = req.query.workspaceId as string | undefined
|
const workspaceId = req.query.workspaceId as string | undefined
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
if (!workspaceId) return badRequest(res, 'workspaceId is required')
|
||||||
const workspace = await prisma.workspace.findFirst({
|
const workspace = await prisma.workspace.findFirst({
|
||||||
where: { id: workspaceId, members: { some: { userId: user.id } } },
|
where: { id: workspaceId, members: { some: { userId: user.id } } },
|
||||||
select: { plan: true },
|
select: { plan: true },
|
||||||
|
@ -143,12 +143,13 @@ test.describe.parallel('Editor', () => {
|
|||||||
await page.goto(`/typebots/${typebotId}/edit`)
|
await page.goto(`/typebots/${typebotId}/edit`)
|
||||||
|
|
||||||
await page.click('[data-testid="editable-icon"]')
|
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.fill('input[placeholder="Search..."]', 'love')
|
||||||
await page.click('text="😍"')
|
await page.click('text="😍"')
|
||||||
await page.click('text="My awesome typebot"')
|
await page.click('text="My awesome typebot"')
|
||||||
await page.fill('input[value="My awesome typebot"]', 'My superb typebot')
|
await page.fill('input[value="My awesome typebot"]', 'My superb typebot')
|
||||||
await page.press('input[value="My superb typebot"]', 'Enter')
|
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="😍"')).toBeVisible()
|
||||||
await expect(page.locator('text="My superb typebot"')).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.goto(`/typebots/${typebotId}/settings`)
|
||||||
await page.click('button:has-text("Metadata")')
|
await page.click('button:has-text("Metadata")')
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
// Fav icon
|
// Fav icon
|
||||||
const favIconImg = page.locator('img >> nth=0')
|
const favIconImg = page.locator('img >> nth=0')
|
||||||
|
@ -2,7 +2,7 @@ import { ResultWithAnswers, VariableWithValue, ResultHeaderCell } from 'models'
|
|||||||
import useSWRInfinite from 'swr/infinite'
|
import useSWRInfinite from 'swr/infinite'
|
||||||
import { stringify } from 'qs'
|
import { stringify } from 'qs'
|
||||||
import { Answer } from 'db'
|
import { Answer } from 'db'
|
||||||
import { isDefined, sendRequest } from 'utils'
|
import { isDefined, isEmpty, sendRequest } from 'utils'
|
||||||
import { fetcher } from 'services/utils'
|
import { fetcher } from 'services/utils'
|
||||||
import { HStack, Text } from '@chakra-ui/react'
|
import { HStack, Text } from '@chakra-ui/react'
|
||||||
import { CodeIcon, CalendarIcon } from 'assets/icons'
|
import { CodeIcon, CalendarIcon } from 'assets/icons'
|
||||||
@ -11,6 +11,7 @@ import { StepIcon } from 'components/editor/StepsSideBar/StepIcon'
|
|||||||
const paginationLimit = 50
|
const paginationLimit = 50
|
||||||
|
|
||||||
const getKey = (
|
const getKey = (
|
||||||
|
workspaceId: string,
|
||||||
typebotId: string,
|
typebotId: string,
|
||||||
pageIndex: number,
|
pageIndex: number,
|
||||||
previousPageData: {
|
previousPageData: {
|
||||||
@ -18,16 +19,19 @@ const getKey = (
|
|||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
if (previousPageData && previousPageData.results.length === 0) return null
|
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=${
|
return `/api/typebots/${typebotId}/results?lastResultId=${
|
||||||
previousPageData.results[previousPageData.results.length - 1].id
|
previousPageData.results[previousPageData.results.length - 1].id
|
||||||
}&limit=${paginationLimit}`
|
}&limit=${paginationLimit}&workspaceId=${workspaceId}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useResults = ({
|
export const useResults = ({
|
||||||
|
workspaceId,
|
||||||
typebotId,
|
typebotId,
|
||||||
onError,
|
onError,
|
||||||
}: {
|
}: {
|
||||||
|
workspaceId: string
|
||||||
typebotId: string
|
typebotId: string
|
||||||
onError: (error: Error) => void
|
onError: (error: Error) => void
|
||||||
}) => {
|
}) => {
|
||||||
@ -40,9 +44,14 @@ export const useResults = ({
|
|||||||
previousPageData: {
|
previousPageData: {
|
||||||
results: ResultWithAnswers[]
|
results: ResultWithAnswers[]
|
||||||
}
|
}
|
||||||
) => getKey(typebotId, pageIndex, previousPageData),
|
) => getKey(workspaceId, typebotId, pageIndex, previousPageData),
|
||||||
fetcher,
|
fetcher,
|
||||||
{ revalidateAll: true }
|
{
|
||||||
|
revalidateAll: true,
|
||||||
|
dedupingInterval: isEmpty(process.env.NEXT_PUBLIC_E2E_TEST)
|
||||||
|
? undefined
|
||||||
|
: 0,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (error) onError(error)
|
if (error) onError(error)
|
||||||
@ -80,12 +89,12 @@ export const deleteAllResults = async (typebotId: string) =>
|
|||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getAllResults = async (typebotId: string) => {
|
export const getAllResults = async (workspaceId: string, typebotId: string) => {
|
||||||
const results = []
|
const results = []
|
||||||
let hasMore = true
|
let hasMore = true
|
||||||
let lastResultId: string | undefined = undefined
|
let lastResultId: string | undefined = undefined
|
||||||
do {
|
do {
|
||||||
const query = stringify({ limit: 200, lastResultId })
|
const query = stringify({ limit: 200, lastResultId, workspaceId })
|
||||||
const { data } = await sendRequest<{ results: ResultWithAnswers[] }>({
|
const { data } = await sendRequest<{ results: ResultWithAnswers[] }>({
|
||||||
url: `/api/typebots/${typebotId}/results?${query}`,
|
url: `/api/typebots/${typebotId}/results?${query}`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
@ -45,7 +45,10 @@
|
|||||||
"typescript": "^4.6.4"
|
"typescript": "^4.6.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.1.0"
|
"react": "^18.1.0",
|
||||||
|
"utils": "*",
|
||||||
|
"db": "*",
|
||||||
|
"models": "*"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn rollup -c",
|
"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 {
|
model CustomDomain {
|
||||||
name String @id
|
name String @id
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
workspaceId String?
|
workspaceId String
|
||||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
model Credentials {
|
model Credentials {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
workspaceId String?
|
workspaceId String
|
||||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||||
data String // Encrypted data
|
data String // Encrypted data
|
||||||
name String
|
name String
|
||||||
type String
|
type String
|
||||||
@ -154,8 +154,8 @@ model DashboardFolder {
|
|||||||
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
|
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
|
||||||
childrenFolder DashboardFolder[] @relation("ParentChild")
|
childrenFolder DashboardFolder[] @relation("ParentChild")
|
||||||
typebots Typebot[]
|
typebots Typebot[]
|
||||||
workspaceId String?
|
workspaceId String
|
||||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
model Typebot {
|
model Typebot {
|
||||||
@ -179,8 +179,8 @@ model Typebot {
|
|||||||
collaborators CollaboratorsOnTypebots[]
|
collaborators CollaboratorsOnTypebots[]
|
||||||
invitations Invitation[]
|
invitations Invitation[]
|
||||||
webhooks Webhook[]
|
webhooks Webhook[]
|
||||||
workspaceId String?
|
workspaceId String
|
||||||
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
model Invitation {
|
model Invitation {
|
||||||
|
@ -1,20 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "models",
|
"name": "models",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "dist/index.js",
|
"main": "dist/cjs/index.js",
|
||||||
"types": "dist/types/index.d.ts",
|
"module": "dist/esm/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"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": {
|
"dependencies": {
|
||||||
"next": "^12.1.6",
|
|
||||||
"db": "*",
|
"db": "*",
|
||||||
"@udecode/plate-core": "^11.0.0"
|
"next": "^12.1.6",
|
||||||
|
"zod": "^3.17.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": "^12.1.6",
|
||||||
|
"db": "*"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "yarn rollup -c",
|
||||||
"dx": "tsc --watch --preserveWatchOutput"
|
"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 { 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'> & {
|
export type Result = Omit<ResultFromPrisma, 'createdAt' | 'variables'> & {
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
@ -1,29 +1,32 @@
|
|||||||
export type Settings = {
|
import { z } from 'zod'
|
||||||
general: GeneralSettings
|
|
||||||
typingEmulation: TypingEmulation
|
|
||||||
metadata: Metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GeneralSettings = {
|
const generalSettings = z.object({
|
||||||
isBrandingEnabled: boolean
|
isBrandingEnabled: z.boolean(),
|
||||||
isNewResultOnRefreshEnabled?: boolean
|
isTypingEmulationEnabled: z.boolean().optional(),
|
||||||
isInputPrefillEnabled?: boolean
|
isInputPrefillEnabled: z.boolean().optional(),
|
||||||
isHideQueryParamsEnabled?: boolean
|
isHideQueryParamsEnabled: z.boolean().optional(),
|
||||||
}
|
isNewResultOnRefreshEnabled: z.boolean().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
export type TypingEmulation = {
|
const typingEmulation = z.object({
|
||||||
enabled: boolean
|
enabled: z.boolean(),
|
||||||
speed: number
|
speed: z.number(),
|
||||||
maxDelay: number
|
maxDelay: z.number(),
|
||||||
}
|
})
|
||||||
|
|
||||||
export type Metadata = {
|
const metadataSchema = z.object({
|
||||||
title?: string
|
title: z.string().optional(),
|
||||||
description: string
|
description: z.string().optional(),
|
||||||
imageUrl?: string
|
imageUrl: z.string().optional(),
|
||||||
favIconUrl?: string
|
favIconUrl: z.string().optional(),
|
||||||
customHeadCode?: string
|
customHeadCode: z.string().optional(),
|
||||||
}
|
})
|
||||||
|
|
||||||
|
export const settingsSchema = z.object({
|
||||||
|
general: generalSettings,
|
||||||
|
typingEmulation: typingEmulation,
|
||||||
|
metadata: metadataSchema,
|
||||||
|
})
|
||||||
|
|
||||||
export const defaultSettings: Settings = {
|
export const defaultSettings: Settings = {
|
||||||
general: {
|
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.',
|
'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 './steps'
|
||||||
export * from './bubble'
|
export * from './bubble'
|
||||||
export * from './inputs'
|
export * from './input'
|
||||||
export * from './logic'
|
export * from './logic'
|
||||||
export * from './integration'
|
export * from './integration'
|
||||||
export * from './item'
|
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 '.'
|
import { z } from 'zod'
|
||||||
|
import { itemBaseSchema } from './shared'
|
||||||
export type Item = ButtonItem | ConditionItem
|
import { buttonItemSchema } from './input'
|
||||||
|
import { conditionItemSchema } from './logic'
|
||||||
export enum ItemType {
|
|
||||||
BUTTON,
|
|
||||||
CONDITION,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ItemBase = {
|
|
||||||
id: string
|
|
||||||
stepId: string
|
|
||||||
outgoingEdgeId?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ItemIndices = {
|
export type ItemIndices = {
|
||||||
blockIndex: number
|
blockIndex: number
|
||||||
stepIndex: number
|
stepIndex: number
|
||||||
itemIndex: 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 {
|
import {
|
||||||
InputStepOptions,
|
InputStepOptions,
|
||||||
IntegrationStepOptions,
|
IntegrationStepOptions,
|
||||||
IntegrationStepType,
|
|
||||||
Item,
|
Item,
|
||||||
LogicStepOptions,
|
LogicStepOptions,
|
||||||
} from '.'
|
} from '.'
|
||||||
import { BubbleStep, BubbleStepType } from './bubble'
|
import { BubbleStep, bubbleStepSchema } from './bubble'
|
||||||
import { InputStep, InputStepType } from './inputs'
|
import { InputStep, inputStepSchema } from './input'
|
||||||
import { IntegrationStep } from './integration'
|
import { IntegrationStep, integrationStepSchema } from './integration'
|
||||||
import { ConditionStep, LogicStep, LogicStepType } from './logic'
|
import { ConditionStep, LogicStep, logicStepSchema } from './logic'
|
||||||
|
import { z } from 'zod'
|
||||||
export type Step =
|
import {
|
||||||
| StartStep
|
BubbleStepType,
|
||||||
| BubbleStep
|
InputStepType,
|
||||||
| InputStep
|
IntegrationStepType,
|
||||||
| LogicStep
|
LogicStepType,
|
||||||
| IntegrationStep
|
stepBaseSchema,
|
||||||
|
} from './shared'
|
||||||
|
|
||||||
export type DraggableStep = BubbleStep | InputStep | LogicStep | IntegrationStep
|
export type DraggableStep = BubbleStep | InputStep | LogicStep | IntegrationStep
|
||||||
|
|
||||||
@ -49,14 +49,26 @@ export type StepOptions =
|
|||||||
|
|
||||||
export type StepWithItems = Omit<Step, 'items'> & { items: Item[] }
|
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 & {
|
const startStepSchema = stepBaseSchema.and(
|
||||||
type: 'start'
|
z.object({
|
||||||
label: string
|
type: z.literal('start'),
|
||||||
}
|
label: z.string(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export type StartStep = z.infer<typeof startStepSchema>
|
||||||
|
|
||||||
export type StepIndices = {
|
export type StepIndices = {
|
||||||
blockIndex: number
|
blockIndex: number
|
||||||
stepIndex: 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 = {
|
import { z } from 'zod'
|
||||||
general: GeneralTheme
|
|
||||||
chat: ChatTheme
|
|
||||||
customCss?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GeneralTheme = {
|
const avatarPropsSchema = z.object({
|
||||||
font: string
|
isEnabled: z.boolean(),
|
||||||
background: Background
|
url: z.string().optional(),
|
||||||
}
|
})
|
||||||
|
|
||||||
export type AvatarProps = {
|
const containerColorsSchema = z.object({
|
||||||
isEnabled: boolean
|
backgroundColor: z.string(),
|
||||||
url?: string
|
color: z.string(),
|
||||||
}
|
})
|
||||||
|
|
||||||
export type ChatTheme = {
|
const inputColorsSchema = containerColorsSchema.and(
|
||||||
hostAvatar?: AvatarProps
|
z.object({
|
||||||
guestAvatar?: AvatarProps
|
placeholderColor: z.string(),
|
||||||
hostBubbles: ContainerColors
|
})
|
||||||
guestBubbles: ContainerColors
|
)
|
||||||
buttons: ContainerColors
|
|
||||||
inputs: InputColors
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ContainerColors = {
|
const chatThemeSchema = z.object({
|
||||||
backgroundColor: string
|
hostAvatar: avatarPropsSchema.optional(),
|
||||||
color: string
|
guestAvatar: avatarPropsSchema.optional(),
|
||||||
}
|
hostBubbles: containerColorsSchema,
|
||||||
|
guestBubbles: containerColorsSchema,
|
||||||
export type InputColors = ContainerColors & {
|
buttons: containerColorsSchema,
|
||||||
placeholderColor: string
|
inputs: inputColorsSchema,
|
||||||
}
|
})
|
||||||
|
|
||||||
export enum BackgroundType {
|
export enum BackgroundType {
|
||||||
COLOR = 'Color',
|
COLOR = 'Color',
|
||||||
@ -38,10 +31,21 @@ export enum BackgroundType {
|
|||||||
NONE = 'None',
|
NONE = 'None',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Background = {
|
const backgroundSchema = z.object({
|
||||||
type: BackgroundType
|
type: z.nativeEnum(BackgroundType),
|
||||||
content?: string
|
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 = {
|
export const defaultTheme: Theme = {
|
||||||
chat: {
|
chat: {
|
||||||
@ -56,3 +60,11 @@ export const defaultTheme: Theme = {
|
|||||||
},
|
},
|
||||||
general: { font: 'Open Sans', background: { type: BackgroundType.NONE } },
|
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 { z } from 'zod'
|
||||||
import { Settings } from './settings'
|
import { settingsSchema } from './settings'
|
||||||
import { Step } from './steps/steps'
|
import { stepSchema } from './steps'
|
||||||
import { Theme } from './theme'
|
import { themeSchema } from './theme'
|
||||||
import { Variable } from './variable'
|
import { variableSchema } from './variable'
|
||||||
|
|
||||||
export type Typebot = Omit<
|
const blockSchema = z.object({
|
||||||
TypebotFromPrisma,
|
id: z.string(),
|
||||||
| 'blocks'
|
title: z.string(),
|
||||||
| 'theme'
|
graphCoordinates: z.object({
|
||||||
| 'settings'
|
x: z.number(),
|
||||||
| 'variables'
|
y: z.number(),
|
||||||
| 'edges'
|
}),
|
||||||
| 'createdAt'
|
steps: z.array(stepSchema),
|
||||||
| 'updatedAt'
|
})
|
||||||
> & {
|
|
||||||
blocks: Block[]
|
|
||||||
variables: Variable[]
|
|
||||||
edges: Edge[]
|
|
||||||
theme: Theme
|
|
||||||
settings: Settings
|
|
||||||
createdAt: string
|
|
||||||
updatedAt: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Block = {
|
const sourceSchema = z.object({
|
||||||
id: string
|
blockId: z.string(),
|
||||||
title: string
|
stepId: z.string(),
|
||||||
graphCoordinates: {
|
itemId: z.string().optional(),
|
||||||
x: number
|
})
|
||||||
y: number
|
|
||||||
}
|
|
||||||
steps: Step[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Source = {
|
const targetSchema = z.object({
|
||||||
blockId: string
|
blockId: z.string(),
|
||||||
stepId: string
|
stepId: z.string().optional(),
|
||||||
itemId?: string
|
})
|
||||||
}
|
|
||||||
export type Target = { blockId: string; stepId?: string }
|
const edgeSchema = z.object({
|
||||||
export type Edge = {
|
id: z.string(),
|
||||||
id: string
|
from: sourceSchema,
|
||||||
from: Source
|
to: targetSchema,
|
||||||
to: Target
|
})
|
||||||
}
|
|
||||||
|
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 = {
|
import { z } from 'zod'
|
||||||
id: string
|
|
||||||
name: string
|
export const variableSchema = z.object({
|
||||||
value?: string | number
|
id: z.string(),
|
||||||
}
|
name: z.string(),
|
||||||
|
value: z.string().or(z.number()).optional(),
|
||||||
|
})
|
||||||
|
|
||||||
export type VariableWithValue = Omit<Variable, 'value'> & {
|
export type VariableWithValue = Omit<Variable, 'value'> & {
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
export type Variable = z.infer<typeof variableSchema>
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2016",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationDir": "./dist/types",
|
"declarationDir": "types",
|
||||||
"outDir": "./dist"
|
"sourceMap": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"emitDeclarationOnly": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
"models": "*",
|
"models": "*",
|
||||||
"next": "^12.1.6"
|
"next": "^12.1.6"
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": "^12.1.6",
|
||||||
|
"models": "*"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn rollup -c",
|
"build": "yarn rollup -c",
|
||||||
"dx": "yarn rollup -c --watch"
|
"dx": "yarn rollup -c --watch"
|
||||||
|
@ -25,7 +25,7 @@ export default [
|
|||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
peerDepsExternal(),
|
peerDepsExternal(),
|
||||||
resolve({ preferBuiltins: true }),
|
resolve(),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
typescript({ tsconfig: './tsconfig.json' }),
|
typescript({ tsconfig: './tsconfig.json' }),
|
||||||
],
|
],
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
|
||||||
export const methodNotAllowed = (res: NextApiResponse) =>
|
export const methodNotAllowed = (
|
||||||
res.status(405).json({ message: 'Method Not Allowed' })
|
res: NextApiResponse,
|
||||||
|
customMessage?: string
|
||||||
|
) => res.status(405).json({ message: customMessage ?? 'Method Not Allowed' })
|
||||||
|
|
||||||
export const notAuthenticated = (res: NextApiResponse) =>
|
export const notAuthenticated = (
|
||||||
res.status(401).json({ message: 'Not authenticated' })
|
res: NextApiResponse,
|
||||||
|
customMessage?: string
|
||||||
|
) => res.status(401).json({ message: customMessage ?? 'Not authenticated' })
|
||||||
|
|
||||||
export const notFound = (res: NextApiResponse) =>
|
export const notFound = (res: NextApiResponse, customMessage?: string) =>
|
||||||
res.status(404).json({ message: 'Not found' })
|
res.status(404).json({ message: customMessage ?? 'Not found' })
|
||||||
|
|
||||||
export const badRequest = (res: NextApiResponse) =>
|
export const badRequest = (res: NextApiResponse, customMessage?: any) =>
|
||||||
res.status(400).json({ message: 'Bad Request' })
|
res.status(400).json({ message: customMessage ?? 'Bad Request' })
|
||||||
|
|
||||||
export const forbidden = (res: NextApiResponse) =>
|
export const forbidden = (res: NextApiResponse, customMessage?: string) =>
|
||||||
res.status(403).json({ message: 'Bad Request' })
|
res.status(403).json({ message: customMessage ?? 'Bad Request' })
|
||||||
|
|
||||||
export const initMiddleware =
|
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"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
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:
|
zustand@^3.4.2, zustand@^3.7.2:
|
||||||
version "3.7.2"
|
version "3.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d"
|
resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d"
|
||||||
|
Reference in New Issue
Block a user