2
0

♻️ Introduce typebot v6 with events (#1013)

Closes #885
This commit is contained in:
Baptiste Arnaud
2023-11-08 15:34:16 +01:00
committed by GitHub
parent 68e4fc71fb
commit 35300eaf34
634 changed files with 58971 additions and 31449 deletions

View File

@@ -1,9 +1,14 @@
import { z } from 'zod'
export const totalAnswersInBlock = z.object({
export const totalAnswersSchema = z.object({
blockId: z.string(),
itemId: z.string().optional(),
total: z.number(),
})
export type TotalAnswers = z.infer<typeof totalAnswersSchema>
export type TotalAnswersInBlock = z.infer<typeof totalAnswersInBlock>
export const totalVisitedEdgesSchema = z.object({
edgeId: z.string(),
total: z.number(),
})
export type TotalVisitedEdges = z.infer<typeof totalVisitedEdgesSchema>

View File

@@ -5,12 +5,12 @@ export const answerSchema = z.object({
createdAt: z.date(),
resultId: z.string(),
blockId: z.string(),
itemId: z.string().nullable(),
groupId: z.string(),
variableId: z.string().nullable(),
content: z.string(),
storageUsed: z.number().nullable(),
}) satisfies z.ZodType<AnswerPrisma>
// TO-DO: remove once itemId is removed from database schema
}) satisfies z.ZodType<Omit<AnswerPrisma, 'itemId'>>
export const answerInputSchema = answerSchema
.omit({
@@ -19,13 +19,10 @@ export const answerInputSchema = answerSchema
variableId: true,
storageUsed: true,
})
.merge(
z.object({
variableId: z.string().nullish(),
storageUsed: z.number().nullish(),
itemId: z.string().nullish(),
})
) satisfies z.ZodType<Prisma.AnswerUncheckedUpdateInput>
.extend({
variableId: z.string().nullish(),
storageUsed: z.number().nullish(),
}) satisfies z.ZodType<Prisma.AnswerUncheckedUpdateInput>
export type Stats = {
totalViews: number

View File

@@ -0,0 +1,5 @@
import { AudioBubbleBlock } from './schema'
export const defaultAudioBubbleContent = {
isAutoplayEnabled: true,
} as const satisfies AudioBubbleBlock['content']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,6 +1,6 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { BubbleBlockType } from './enums'
import { blockBaseSchema } from '../../shared'
import { BubbleBlockType } from '../constants'
export const audioBubbleContentSchema = z.object({
url: z.string().optional(),
@@ -10,11 +10,9 @@ export const audioBubbleContentSchema = z.object({
export const audioBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.AUDIO]),
content: audioBubbleContentSchema,
content: audioBubbleContentSchema.optional(),
})
)
export const defaultAudioBubbleContent = {}
export type AudioBubbleBlock = z.infer<typeof audioBubbleBlockSchema>
export type AudioBubbleContent = z.infer<typeof audioBubbleContentSchema>

View File

@@ -1,21 +0,0 @@
import { z } from 'zod'
import { variableStringSchema } from '../../utils'
import { blockBaseSchema } from '../baseSchemas'
import { BubbleBlockType } from './enums'
export const embedBubbleContentSchema = z.object({
url: z.string().optional(),
height: z.number().or(variableStringSchema),
})
export const embedBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.EMBED]),
content: embedBubbleContentSchema,
})
)
export const defaultEmbedBubbleContent: EmbedBubbleContent = { height: 400 }
export type EmbedBubbleBlock = z.infer<typeof embedBubbleBlockSchema>
export type EmbedBubbleContent = z.infer<typeof embedBubbleContentSchema>

View File

@@ -0,0 +1,5 @@
import { EmbedBubbleBlock } from './schema'
export const defaultEmbedBubbleContent = {
height: 400,
} as const satisfies EmbedBubbleBlock['content']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,18 @@
import { z } from 'zod'
import { variableStringSchema } from '../../../utils'
import { blockBaseSchema } from '../../shared'
import { BubbleBlockType } from '../constants'
export const embedBubbleContentSchema = z.object({
url: z.string().optional(),
height: z.number().or(variableStringSchema).optional(),
})
export const embedBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.EMBED]),
content: embedBubbleContentSchema.optional(),
})
)
export type EmbedBubbleBlock = z.infer<typeof embedBubbleBlockSchema>

View File

@@ -0,0 +1,7 @@
import { ImageBubbleBlock } from './schema'
export const defaultImageBubbleContent = {
clickLink: {
alt: 'Bubble image',
},
} as const satisfies ImageBubbleBlock['content']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,6 +1,6 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { BubbleBlockType } from './enums'
import { BubbleBlockType } from '../constants'
import { blockBaseSchema } from '../../shared'
export const imageBubbleContentSchema = z.object({
url: z.string().optional(),
@@ -15,11 +15,8 @@ export const imageBubbleContentSchema = z.object({
export const imageBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.IMAGE]),
content: imageBubbleContentSchema,
content: imageBubbleContentSchema.optional(),
})
)
export const defaultImageBubbleContent: ImageBubbleContent = {}
export type ImageBubbleBlock = z.infer<typeof imageBubbleBlockSchema>
export type ImageBubbleContent = z.infer<typeof imageBubbleContentSchema>

View File

@@ -3,4 +3,4 @@ export * from './embed'
export * from './image'
export * from './text'
export * from './video'
export * from './enums'
export * from './schema'

View File

@@ -0,0 +1,21 @@
import { z } from 'zod'
import { audioBubbleBlockSchema } from './audio'
import { embedBubbleBlockSchema } from './embed'
import { imageBubbleBlockSchema } from './image'
import { textBubbleBlockSchema } from './text'
import { videoBubbleBlockSchema } from './video'
export const bubbleBlockSchemas = [
textBubbleBlockSchema,
imageBubbleBlockSchema,
videoBubbleBlockSchema,
embedBubbleBlockSchema,
audioBubbleBlockSchema,
] as const
export const bubbleBlockSchema = z.discriminatedUnion('type', [
...bubbleBlockSchemas,
])
export type BubbleBlock = z.infer<typeof bubbleBlockSchema>
export type BubbleBlockContent = BubbleBlock['content']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,22 +1,18 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { BubbleBlockType } from './enums'
import type { TElement } from '@udecode/plate-common'
export const defaultTextBubbleContent: TextBubbleContent = {
richText: [],
}
import { blockBaseSchema } from '../../shared'
import { BubbleBlockType } from '../constants'
export const textBubbleContentSchema = z.object({
html: z.string().optional(),
richText: z.array(z.any()),
richText: z.array(z.any()).optional(),
plainText: z.string().optional(),
})
export const textBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.TEXT]),
content: textBubbleContentSchema,
content: textBubbleContentSchema.optional(),
})
)
@@ -24,6 +20,5 @@ export type TextBubbleBlock = Omit<
z.infer<typeof textBubbleBlockSchema>,
'content'
> & {
content: { richText: TElement[]; html?: string; plainText?: string }
content?: { richText?: TElement[]; html?: string; plainText?: string }
}
export type TextBubbleContent = TextBubbleBlock['content']

View File

@@ -3,3 +3,7 @@ export enum VideoBubbleContentType {
YOUTUBE = 'youtube',
VIMEO = 'vimeo',
}
export const defaultVideoBubbleContent = {
height: 400,
} as const

View File

@@ -1,2 +1 @@
export * from './enums'
export * from './schemas'
export * from './schema'

View File

@@ -1,8 +1,8 @@
import { z } from 'zod'
import { blockBaseSchema } from '../../baseSchemas'
import { BubbleBlockType } from '../enums'
import { VideoBubbleContentType } from './enums'
import { blockBaseSchema } from '../../shared'
import { VideoBubbleContentType } from './constants'
import { variableStringSchema } from '../../../utils'
import { BubbleBlockType } from '../constants'
export const videoBubbleContentSchema = z.object({
url: z.string().optional(),
@@ -14,11 +14,8 @@ export const videoBubbleContentSchema = z.object({
export const videoBubbleBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([BubbleBlockType.VIDEO]),
content: videoBubbleContentSchema,
content: videoBubbleContentSchema.optional(),
})
)
export const defaultVideoBubbleContent: VideoBubbleContent = {}
export type VideoBubbleBlock = z.infer<typeof videoBubbleBlockSchema>
export type VideoBubbleContent = z.infer<typeof videoBubbleContentSchema>

View File

@@ -1,7 +1,6 @@
export * from './baseSchemas'
export * from './bubbles'
export * from './inputs'
export * from './integrations'
export * from './logic'
export * from './start'
export * from './schemas'
export * from './schema'

View File

@@ -1,49 +0,0 @@
import { z } from 'zod'
import { ItemType } from '../../items/enums'
import { itemBaseSchema } from '../../items/baseSchemas'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { conditionSchema } from '../logic/condition'
export const choiceInputOptionsSchema = optionBaseSchema.merge(
z.object({
isMultipleChoice: z.boolean(),
buttonLabel: z.string(),
dynamicVariableId: z.string().optional(),
isSearchable: z.boolean().optional(),
searchInputPlaceholder: z.string().optional(),
})
)
export const defaultChoiceInputOptions = {
buttonLabel: defaultButtonLabel,
searchInputPlaceholder: 'Filter the options...',
isMultipleChoice: false,
isSearchable: false,
} as const
export const buttonItemSchema = itemBaseSchema.merge(
z.object({
type: z.literal(ItemType.BUTTON),
content: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
})
)
export const choiceInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.CHOICE]),
items: z.array(buttonItemSchema),
options: choiceInputOptionsSchema,
})
)
export type ButtonItem = z.infer<typeof buttonItemSchema>
export type ChoiceInputBlock = z.infer<typeof choiceInputSchema>
export type ChoiceInputOptions = z.infer<typeof choiceInputOptionsSchema>

View File

@@ -0,0 +1,9 @@
import { defaultButtonLabel } from '../constants'
import { ChoiceInputBlock } from './schema'
export const defaultChoiceInputOptions = {
buttonLabel: defaultButtonLabel,
searchInputPlaceholder: 'Filter the options...',
isMultipleChoice: false,
isSearchable: false,
} as const satisfies ChoiceInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,64 @@
import { z } from 'zod'
import { InputBlockType } from '../constants'
import { itemBaseSchemas } from '../../../items/shared'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { conditionSchema } from '../../logic'
export const choiceInputOptionsSchema = optionBaseSchema.merge(
z.object({
isMultipleChoice: z.boolean().optional(),
buttonLabel: z.string().optional(),
dynamicVariableId: z.string().optional(),
isSearchable: z.boolean().optional(),
searchInputPlaceholder: z.string().optional(),
})
)
export const buttonItemSchemas = {
v5: itemBaseSchemas.v5.extend({
content: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
}),
v6: itemBaseSchemas.v6.extend({
content: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
}),
}
export const buttonItemSchema = z.union([
buttonItemSchemas.v5,
buttonItemSchemas.v6,
])
export const buttonsInputV5Schema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.CHOICE]),
items: z.array(buttonItemSchemas.v5),
options: choiceInputOptionsSchema.optional(),
})
)
export const buttonsInputSchemas = {
v5: buttonsInputV5Schema,
v6: buttonsInputV5Schema.extend({
items: z.array(buttonItemSchemas.v6),
}),
} as const
export const buttonsInputSchema = z.union([
buttonsInputSchemas.v5,
buttonsInputSchemas.v6,
])
export type ButtonItem = z.infer<typeof buttonItemSchema>
export type ChoiceInputBlock = z.infer<typeof buttonsInputSchema>

View File

@@ -1 +1,15 @@
export const defaultButtonLabel = 'Send'
export enum InputBlockType {
TEXT = 'text input',
NUMBER = 'number input',
EMAIL = 'email input',
URL = 'url input',
DATE = 'date input',
PHONE = 'phone number input',
CHOICE = 'choice input',
PICTURE_CHOICE = 'picture choice input',
PAYMENT = 'payment input',
RATING = 'rating input',
FILE = 'file input',
}

View File

@@ -1,35 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
export const dateInputOptionsSchema = optionBaseSchema.merge(
z.object({
labels: z.object({
button: z.string(),
from: z.string(),
to: z.string(),
}),
hasTime: z.boolean(),
isRange: z.boolean(),
format: z.string().optional(),
min: z.string().optional(),
max: z.string().optional(),
})
)
export const dateInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.DATE]),
options: dateInputOptionsSchema,
})
)
export const defaultDateInputOptions: DateInputOptions = {
hasTime: false,
isRange: false,
labels: { button: defaultButtonLabel, from: 'From:', to: 'To:' },
}
export type DateInputBlock = z.infer<typeof dateInputSchema>
export type DateInputOptions = z.infer<typeof dateInputOptionsSchema>

View File

@@ -0,0 +1,12 @@
import { defaultButtonLabel } from '../constants'
import { DateInputBlock } from './schema'
export const defaultDateInputOptions = {
hasTime: false,
isRange: false,
labels: { button: defaultButtonLabel, from: 'From:', to: 'To:' },
format: 'dd/MM/yyyy',
formatWithTime: 'dd/MM/yyyy HH:mm',
} as const satisfies DateInputBlock['options'] & {
formatWithTime: string
}

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,29 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
export const dateInputOptionsSchema = optionBaseSchema.merge(
z.object({
labels: z
.object({
button: z.string().optional(),
from: z.string().optional(),
to: z.string().optional(),
})
.optional(),
hasTime: z.boolean().optional(),
isRange: z.boolean().optional(),
format: z.string().optional(),
min: z.string().optional(),
max: z.string().optional(),
})
)
export const dateInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.DATE]),
options: dateInputOptionsSchema.optional(),
})
)
export type DateInputBlock = z.infer<typeof dateInputSchema>

View File

@@ -1,33 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { textInputOptionsBaseSchema } from './text'
export const emailInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string().optional(),
})
)
export const emailInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.EMAIL]),
options: emailInputOptionsSchema,
})
)
export const invalidEmailDefaultRetryMessage =
"This email doesn't seem to be valid. Can you type it again?"
export const defaultEmailInputOptions: EmailInputOptions = {
labels: {
button: defaultButtonLabel,
placeholder: 'Type your email...',
},
}
export type EmailInputBlock = z.infer<typeof emailInputSchema>
export type EmailInputOptions = z.infer<typeof emailInputOptionsSchema>

View File

@@ -0,0 +1,11 @@
import { defaultButtonLabel } from '../constants'
import { EmailInputBlock } from './schema'
export const defaultEmailInputOptions = {
labels: {
button: defaultButtonLabel,
placeholder: 'Type your email...',
},
retryMessageContent:
"This email doesn't seem to be valid. Can you type it again?",
} as const satisfies EmailInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,22 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
import { textInputOptionsBaseSchema } from '../text'
export const emailInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string().optional(),
})
)
export const emailInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.EMAIL]),
options: emailInputOptionsSchema.optional(),
})
)
export type EmailInputBlock = z.infer<typeof emailInputSchema>
export type EmailInputOptions = z.infer<typeof emailInputOptionsSchema>

View File

@@ -1,13 +0,0 @@
export enum InputBlockType {
TEXT = 'text input',
NUMBER = 'number input',
EMAIL = 'email input',
URL = 'url input',
DATE = 'date input',
PHONE = 'phone number input',
CHOICE = 'choice input',
PICTURE_CHOICE = 'picture choice input',
PAYMENT = 'payment input',
RATING = 'rating input',
FILE = 'file input',
}

View File

@@ -1,41 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { InputBlockType } from './enums'
export const fileInputOptionsSchema = optionBaseSchema.merge(
z.object({
isRequired: z.boolean().optional(),
isMultipleAllowed: z.boolean(),
labels: z.object({
placeholder: z.string(),
button: z.string(),
clear: z.string().optional(),
skip: z.string().optional(),
}),
sizeLimit: z.number().optional().describe('Deprecated'),
})
)
export const fileInputStepSchema = blockBaseSchema.merge(
z.object({
type: z.literal(InputBlockType.FILE),
options: fileInputOptionsSchema,
})
)
export const defaultFileInputOptions = {
isRequired: true,
isMultipleAllowed: false,
labels: {
placeholder: `<strong>
Click to upload
</strong> or drag and drop<br>
(size limit: 10MB)`,
button: 'Upload',
clear: 'Clear',
skip: 'Skip',
},
} satisfies FileInputOptions
export type FileInputBlock = z.infer<typeof fileInputStepSchema>
export type FileInputOptions = z.infer<typeof fileInputOptionsSchema>

View File

@@ -0,0 +1,15 @@
import { FileInputBlock } from './schema'
export const defaultFileInputOptions = {
isRequired: true,
isMultipleAllowed: false,
labels: {
placeholder: `<strong>
Click to upload
</strong> or drag and drop<br>
(size limit: 10MB)`,
button: 'Upload',
clear: 'Clear',
skip: 'Skip',
},
} as const satisfies FileInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,50 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
const fileInputOptionsV5Schema = optionBaseSchema.merge(
z.object({
isRequired: z.boolean().optional(),
isMultipleAllowed: z.boolean().optional(),
labels: z
.object({
placeholder: z.string().optional(),
button: z.string().optional(),
clear: z.string().optional(),
skip: z.string().optional(),
})
.optional(),
sizeLimit: z.number().optional(),
})
)
const fileInputOptionsSchemas = {
v5: fileInputOptionsV5Schema,
v6: fileInputOptionsV5Schema.omit({
sizeLimit: true,
}),
} as const
const fileInputBlockV5Schema = blockBaseSchema.merge(
z.object({
type: z.literal(InputBlockType.FILE),
options: fileInputOptionsSchemas.v5.optional(),
})
)
export const fileInputBlockSchemas = {
v5: fileInputBlockV5Schema,
v6: fileInputBlockV5Schema.merge(
z.object({
options: fileInputOptionsSchemas.v6.optional(),
})
),
}
const fileInputBlockSchema = z.union([
fileInputBlockSchemas.v5,
fileInputBlockSchemas.v6,
])
export type FileInputBlock = z.infer<typeof fileInputBlockSchema>
export type FileInputBlockV6 = z.infer<typeof fileInputBlockSchemas.v6>

View File

@@ -1,8 +1,6 @@
export * from './choice'
export * from './constants'
export * from './date'
export * from './email'
export * from './enums'
export * from './file'
export * from './number'
export * from './payment'
@@ -11,3 +9,4 @@ export * from './rating'
export * from './text'
export * from './url'
export * from './pictureChoice'
export * from './schema'

View File

@@ -0,0 +1,6 @@
import { defaultButtonLabel } from '../constants'
import { NumberInputBlock } from './schema'
export const defaultNumberInputOptions = {
labels: { button: defaultButtonLabel, placeholder: 'Type a number...' },
} as const satisfies NumberInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,9 +1,8 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { textInputOptionsBaseSchema } from './text'
import { variableStringSchema } from '../../utils'
import { variableStringSchema } from '../../../utils'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
import { textInputOptionsBaseSchema } from '../text'
export const numberInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
@@ -18,13 +17,8 @@ export const numberInputOptionsSchema = optionBaseSchema
export const numberInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.NUMBER]),
options: numberInputOptionsSchema,
options: numberInputOptionsSchema.optional(),
})
)
export const defaultNumberInputOptions: NumberInputOptions = {
labels: { button: defaultButtonLabel, placeholder: 'Type a number...' },
}
export type NumberInputBlock = z.infer<typeof numberInputSchema>
export type NumberInputOptions = z.infer<typeof numberInputOptionsSchema>

View File

@@ -0,0 +1,12 @@
import { PaymentInputBlock } from './schema'
export enum PaymentProvider {
STRIPE = 'Stripe',
}
export const defaultPaymentInputOptions = {
provider: PaymentProvider.STRIPE,
labels: { button: 'Pay', success: 'Success' },
retryMessageContent: 'Payment failed. Please, try again.',
currency: 'USD',
} as const satisfies PaymentInputBlock['options']

View File

@@ -1,3 +0,0 @@
export enum PaymentProvider {
STRIPE = 'Stripe',
}

View File

@@ -1,2 +1 @@
export * from './enums'
export * from './schemas'
export * from './schema'

View File

@@ -3,9 +3,9 @@ import {
optionBaseSchema,
blockBaseSchema,
credentialsBaseSchema,
} from '../../baseSchemas'
import { InputBlockType } from '../enums'
import { PaymentProvider } from './enums'
} from '../../shared'
import { PaymentProvider } from './constants'
import { InputBlockType } from '../constants'
export type CreditCardDetails = {
number: string
@@ -25,11 +25,13 @@ const addressSchema = z.object({
export const paymentInputOptionsSchema = optionBaseSchema.merge(
z.object({
provider: z.nativeEnum(PaymentProvider),
labels: z.object({
button: z.string(),
success: z.string().optional(),
}),
provider: z.nativeEnum(PaymentProvider).optional(),
labels: z
.object({
button: z.string().optional(),
success: z.string().optional(),
})
.optional(),
additionalInformation: z
.object({
description: z.string().optional(),
@@ -40,7 +42,7 @@ export const paymentInputOptionsSchema = optionBaseSchema.merge(
})
.optional(),
credentialsId: z.string().optional(),
currency: z.string(),
currency: z.string().optional(),
amount: z.string().optional(),
retryMessageContent: z.string().optional(),
})
@@ -55,7 +57,7 @@ export const paymentInputRuntimeOptionsSchema = z.object({
export const paymentInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.PAYMENT]),
options: paymentInputOptionsSchema,
options: paymentInputOptionsSchema.optional(),
})
)
@@ -75,19 +77,11 @@ export const stripeCredentialsSchema = z
})
.merge(credentialsBaseSchema)
export const defaultPaymentInputOptions: PaymentInputOptions = {
provider: PaymentProvider.STRIPE,
labels: { button: 'Pay', success: 'Success' },
retryMessageContent: 'Payment failed. Please, try again.',
currency: 'USD',
}
export type PaymentInputBlock = z.infer<typeof paymentInputSchema>
export type PaymentInputOptions = z.infer<typeof paymentInputOptionsSchema>
export type PaymentInputRuntimeOptions = z.infer<
typeof paymentInputRuntimeOptionsSchema
>
export type StripeCredentials = z.infer<typeof stripeCredentialsSchema>
export type PaymentAddress = NonNullable<
PaymentInputOptions['additionalInformation']
NonNullable<PaymentInputBlock['options']>['additionalInformation']
>['address']

View File

@@ -1,35 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { textInputOptionsBaseSchema } from './text'
export const phoneNumberInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string(),
defaultCountryCode: z.string().optional(),
})
)
export const phoneNumberInputBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.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 PhoneNumberInputBlock = z.infer<typeof phoneNumberInputBlockSchema>
export type PhoneNumberInputOptions = z.infer<
typeof phoneNumberInputOptionsSchema
>

View File

@@ -0,0 +1,11 @@
import { defaultButtonLabel } from '../constants'
import { PhoneNumberInputBlock } from './schema'
export const defaultPhoneInputOptions = {
labels: {
button: defaultButtonLabel,
placeholder: 'Type your phone number...',
},
retryMessageContent:
"This phone number doesn't seem to be valid. Can you type it again?",
} as const satisfies PhoneNumberInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,22 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
import { textInputOptionsBaseSchema } from '../text'
export const phoneNumberInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string().optional(),
defaultCountryCode: z.string().optional(),
})
)
export const phoneNumberInputBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.PHONE]),
options: phoneNumberInputOptionsSchema.optional(),
})
)
export type PhoneNumberInputBlock = z.infer<typeof phoneNumberInputBlockSchema>

View File

@@ -1,55 +0,0 @@
import { z } from 'zod'
import { ItemType } from '../../items/enums'
import { itemBaseSchema } from '../../items/baseSchemas'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { conditionSchema } from '../logic/condition'
export const pictureChoiceOptionsSchema = optionBaseSchema.merge(
z.object({
isMultipleChoice: z.boolean().optional(),
isSearchable: z.boolean().optional(),
buttonLabel: z.string(),
searchInputPlaceholder: z.string(),
dynamicItems: z
.object({
isEnabled: z.boolean().optional(),
titlesVariableId: z.string().optional(),
descriptionsVariableId: z.string().optional(),
pictureSrcsVariableId: z.string().optional(),
})
.optional(),
})
)
export const pictureChoiceItemSchema = itemBaseSchema.merge(
z.object({
type: z.literal(ItemType.PICTURE_CHOICE),
pictureSrc: z.string().optional(),
title: z.string().optional(),
description: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
})
)
export const pictureChoiceBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.PICTURE_CHOICE]),
items: z.array(pictureChoiceItemSchema),
options: pictureChoiceOptionsSchema,
})
)
export type PictureChoiceItem = z.infer<typeof pictureChoiceItemSchema>
export type PictureChoiceBlock = z.infer<typeof pictureChoiceBlockSchema>
export const defaultPictureChoiceOptions: PictureChoiceBlock['options'] = {
buttonLabel: defaultButtonLabel,
searchInputPlaceholder: 'Filter the options...',
}

View File

@@ -0,0 +1,12 @@
import { defaultButtonLabel } from '../constants'
import { PictureChoiceBlock } from './schema'
export const defaultPictureChoiceOptions = {
buttonLabel: defaultButtonLabel,
searchInputPlaceholder: 'Filter the options...',
isMultipleChoice: false,
isSearchable: false,
dynamicItems: {
isEnabled: false,
},
} as const satisfies PictureChoiceBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,75 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { conditionSchema } from '../../logic'
import { InputBlockType } from '../constants'
import { itemBaseSchemas } from '../../../items/shared'
export const pictureChoiceOptionsSchema = optionBaseSchema.merge(
z.object({
isMultipleChoice: z.boolean().optional(),
isSearchable: z.boolean().optional(),
buttonLabel: z.string().optional(),
searchInputPlaceholder: z.string().optional(),
dynamicItems: z
.object({
isEnabled: z.boolean().optional(),
titlesVariableId: z.string().optional(),
descriptionsVariableId: z.string().optional(),
pictureSrcsVariableId: z.string().optional(),
})
.optional(),
})
)
export const pictureChoiceItemSchemas = {
v5: itemBaseSchemas.v5.extend({
pictureSrc: z.string().optional(),
title: z.string().optional(),
description: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
}),
v6: itemBaseSchemas.v6.extend({
pictureSrc: z.string().optional(),
title: z.string().optional(),
description: z.string().optional(),
displayCondition: z
.object({
isEnabled: z.boolean().optional(),
condition: conditionSchema.optional(),
})
.optional(),
}),
}
export const pictureChoiceItemSchema = z.union([
pictureChoiceItemSchemas.v5,
pictureChoiceItemSchemas.v6,
])
export const pictureChoiceBlockV5Schema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.PICTURE_CHOICE]),
items: z.array(pictureChoiceItemSchemas.v5),
options: pictureChoiceOptionsSchema.optional(),
})
)
export const pictureChoiceBlockSchemas = {
v5: pictureChoiceBlockV5Schema,
v6: pictureChoiceBlockV5Schema.extend({
items: z.array(pictureChoiceItemSchemas.v6),
}),
} as const
export const pictureChoiceBlockSchema = z.union([
pictureChoiceBlockSchemas.v5,
pictureChoiceBlockSchemas.v6,
])
export type PictureChoiceItem = z.infer<typeof pictureChoiceItemSchema>
export type PictureChoiceBlock = z.infer<typeof pictureChoiceBlockSchema>

View File

@@ -1,38 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
export const defaultRatingInputOptions: RatingInputOptions = {
buttonType: 'Numbers',
length: 10,
labels: { button: defaultButtonLabel },
customIcon: { isEnabled: false },
}
export const ratingInputOptionsSchema = optionBaseSchema.merge(
z.object({
buttonType: z.literal('Icons').or(z.literal('Numbers')),
length: z.number(),
labels: z.object({
left: z.string().optional(),
right: z.string().optional(),
button: z.string(),
}),
customIcon: z.object({
isEnabled: z.boolean(),
svg: z.string().optional(),
}),
isOneClickSubmitEnabled: z.boolean().optional(),
})
)
export const ratingInputBlockSchema = blockBaseSchema.merge(
z.object({
type: z.literal(InputBlockType.RATING),
options: ratingInputOptionsSchema,
})
)
export type RatingInputBlock = z.infer<typeof ratingInputBlockSchema>
export type RatingInputOptions = z.infer<typeof ratingInputOptionsSchema>

View File

@@ -0,0 +1,12 @@
import { defaultButtonLabel } from '../constants'
import { RatingInputBlock } from '../rating'
export const defaultRatingInputOptions = {
buttonType: 'Numbers',
length: 10,
labels: {
button: defaultButtonLabel,
},
customIcon: { isEnabled: false },
isOneClickSubmitEnabled: false,
} as const satisfies RatingInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,33 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
export const ratingInputOptionsSchema = optionBaseSchema.merge(
z.object({
buttonType: z.literal('Icons').or(z.literal('Numbers')).optional(),
length: z.number().optional(),
labels: z
.object({
left: z.string().optional(),
right: z.string().optional(),
button: z.string().optional(),
})
.optional(),
customIcon: z
.object({
isEnabled: z.boolean().optional(),
svg: z.string().optional(),
})
.optional(),
isOneClickSubmitEnabled: z.boolean().optional(),
})
)
export const ratingInputBlockSchema = blockBaseSchema.merge(
z.object({
type: z.literal(InputBlockType.RATING),
options: ratingInputOptionsSchema.optional(),
})
)
export type RatingInputBlock = z.infer<typeof ratingInputBlockSchema>

View File

@@ -0,0 +1,56 @@
import { z } from 'zod'
import { buttonsInputSchemas } from './choice'
import { dateInputSchema } from './date'
import { emailInputSchema } from './email'
import { numberInputSchema } from './number'
import { paymentInputSchema } from './payment'
import { phoneNumberInputBlockSchema } from './phone'
import {
pictureChoiceBlockSchema,
pictureChoiceBlockSchemas,
} from './pictureChoice'
import { ratingInputBlockSchema } from './rating'
import { textInputSchema } from './text'
import { urlInputSchema } from './url'
import { fileInputBlockSchemas } from './file'
export const inputBlockSchemas = {
v5: [
textInputSchema,
buttonsInputSchemas.v5,
emailInputSchema,
numberInputSchema,
urlInputSchema,
phoneNumberInputBlockSchema,
dateInputSchema,
paymentInputSchema,
ratingInputBlockSchema,
fileInputBlockSchemas.v5,
pictureChoiceBlockSchemas.v5,
],
v6: [
textInputSchema,
buttonsInputSchemas.v6,
emailInputSchema,
numberInputSchema,
urlInputSchema,
phoneNumberInputBlockSchema,
dateInputSchema,
paymentInputSchema,
ratingInputBlockSchema,
fileInputBlockSchemas.v6,
pictureChoiceBlockSchemas.v6,
],
} as const
const inputBlockV5Schema = z.discriminatedUnion('type', [
...inputBlockSchemas.v5,
])
const inputBlockV6Schema = z.discriminatedUnion('type', [
...inputBlockSchemas.v6,
])
const inputBlockSchema = z.union([inputBlockV5Schema, inputBlockV6Schema])
export type InputBlock = z.infer<typeof inputBlockSchema>

View File

@@ -1,34 +0,0 @@
import { z } from 'zod'
import { blockBaseSchema, optionBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
export const textInputOptionsBaseSchema = z.object({
labels: z.object({
placeholder: z.string(),
button: z.string(),
}),
})
export const textInputOptionsSchema = textInputOptionsBaseSchema
.merge(optionBaseSchema)
.merge(
z.object({
isLong: z.boolean(),
})
)
export const defaultTextInputOptions: TextInputOptions = {
isLong: false,
labels: { button: defaultButtonLabel, placeholder: 'Type your answer...' },
}
export const textInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.TEXT]),
options: textInputOptionsSchema,
})
)
export type TextInputBlock = z.infer<typeof textInputSchema>
export type TextInputOptions = z.infer<typeof textInputOptionsSchema>

View File

@@ -0,0 +1,7 @@
import { defaultButtonLabel } from '../constants'
import { TextInputBlock } from './schema'
export const defaultTextInputOptions = {
isLong: false,
labels: { button: defaultButtonLabel, placeholder: 'Type your answer...' },
} as const satisfies TextInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,29 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
export const textInputOptionsBaseSchema = z.object({
labels: z
.object({
placeholder: z.string().optional(),
button: z.string().optional(),
})
.optional(),
})
export const textInputOptionsSchema = textInputOptionsBaseSchema
.merge(optionBaseSchema)
.merge(
z.object({
isLong: z.boolean().optional(),
})
)
export const textInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.TEXT]),
options: textInputOptionsSchema.optional(),
})
)
export type TextInputBlock = z.infer<typeof textInputSchema>

View File

@@ -1,32 +0,0 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../baseSchemas'
import { defaultButtonLabel } from './constants'
import { InputBlockType } from './enums'
import { textInputOptionsBaseSchema } from './text'
export const urlInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string(),
})
)
export const urlInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.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 UrlInputBlock = z.infer<typeof urlInputSchema>
export type UrlInputOptions = z.infer<typeof urlInputOptionsSchema>

View File

@@ -0,0 +1,11 @@
import { defaultButtonLabel } from '../constants'
import { UrlInputBlock } from './schema'
export const defaultUrlInputOptions = {
labels: {
button: defaultButtonLabel,
placeholder: 'Type a URL...',
},
retryMessageContent:
"This URL doesn't seem to be valid. Can you type it again?",
} as const satisfies UrlInputBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,21 @@
import { z } from 'zod'
import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants'
import { textInputOptionsBaseSchema } from '../text'
export const urlInputOptionsSchema = optionBaseSchema
.merge(textInputOptionsBaseSchema)
.merge(
z.object({
retryMessageContent: z.string().optional(),
})
)
export const urlInputSchema = blockBaseSchema.merge(
z.object({
type: z.enum([InputBlockType.URL]),
options: urlInputOptionsSchema.optional(),
})
)
export type UrlInputBlock = z.infer<typeof urlInputSchema>

View File

@@ -0,0 +1,8 @@
import { ChatwootBlock } from './schema'
export const chatwootTasks = ['Show widget', 'Close widget'] as const
export const defaultChatwootOptions = {
task: 'Show widget',
baseUrl: 'https://app.chatwoot.com',
} as const satisfies ChatwootBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,13 +1,12 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
export const chatwootTasks = ['Show widget', 'Close widget'] as const
import { chatwootTasks } from './constants'
import { blockBaseSchema } from '../../shared'
import { IntegrationBlockType } from '../constants'
export const chatwootOptionsSchema = z.object({
task: z.enum(chatwootTasks).optional(),
baseUrl: z.string(),
websiteToken: z.string(),
baseUrl: z.string().optional(),
websiteToken: z.string().optional(),
user: z
.object({
id: z.string().optional(),
@@ -22,15 +21,8 @@ export const chatwootOptionsSchema = z.object({
export const chatwootBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.CHATWOOT]),
options: chatwootOptionsSchema,
options: chatwootOptionsSchema.optional(),
})
)
export const defaultChatwootOptions: ChatwootOptions = {
task: 'Show widget',
baseUrl: 'https://app.chatwoot.com',
websiteToken: '',
}
export type ChatwootBlock = z.infer<typeof chatwootBlockSchema>
export type ChatwootOptions = z.infer<typeof chatwootOptionsSchema>

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,7 +1,7 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
import { variableStringSchema } from '../../utils'
import { variableStringSchema } from '../../../utils'
import { blockBaseSchema } from '../../shared'
import { IntegrationBlockType } from '../constants'
export const googleAnalyticsOptionsSchema = z.object({
trackingId: z.string().optional(),
@@ -15,13 +15,8 @@ export const googleAnalyticsOptionsSchema = z.object({
export const googleAnalyticsBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.GOOGLE_ANALYTICS]),
options: googleAnalyticsOptionsSchema,
options: googleAnalyticsOptionsSchema.optional(),
})
)
export const defaultGoogleAnalyticsOptions: GoogleAnalyticsOptions = {}
export type GoogleAnalyticsBlock = z.infer<typeof googleAnalyticsBlockSchema>
export type GoogleAnalyticsOptions = z.infer<
typeof googleAnalyticsOptionsSchema
>

View File

@@ -0,0 +1,16 @@
export enum GoogleSheetsAction {
GET = 'Get data from sheet',
INSERT_ROW = 'Insert a row',
UPDATE_ROW = 'Update a row',
}
export const totalRowsToExtractOptions = [
'All',
'First',
'Last',
'Random',
] as const
export const defaultGoogleSheetsOptions = {
totalRowsToExtract: 'All',
} as const

View File

@@ -1,5 +0,0 @@
export enum GoogleSheetsAction {
GET = 'Get data from sheet',
INSERT_ROW = 'Insert a row',
UPDATE_ROW = 'Update a row',
}

View File

@@ -1,2 +1 @@
export * from './enums'
export * from './schemas'
export * from './schema'

View File

@@ -0,0 +1,178 @@
import { z } from 'zod'
import { IntegrationBlockType } from '../constants'
import { GoogleSheetsAction, totalRowsToExtractOptions } from './constants'
import { blockBaseSchema, credentialsBaseSchema } from '../../shared'
import {
ComparisonOperators,
LogicalOperator,
} from '../../logic/condition/constants'
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 rowsFilterComparisonSchema = z.object({
id: z.string(),
column: z.string().optional(),
comparisonOperator: z.nativeEnum(ComparisonOperators).optional(),
value: z.string().optional(),
})
const initialGoogleSheetsOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.undefined(),
})
)
const googleSheetsGetOptionsV5Schema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.GET]),
referenceCell: cellSchema.optional().optional(),
filter: z
.object({
comparisons: z.array(rowsFilterComparisonSchema).optional(),
logicalOperator: z.nativeEnum(LogicalOperator).optional(),
})
.optional(),
cellsToExtract: z.array(extractingCellSchema).optional(),
totalRowsToExtract: z.enum(totalRowsToExtractOptions).optional(),
})
)
const googleSheetsGetOptionsSchemas = {
v5: googleSheetsGetOptionsV5Schema,
v6: googleSheetsGetOptionsV5Schema.omit({
referenceCell: true,
}),
}
const googleSheetsGetOptionsSchema = z.union([
googleSheetsGetOptionsSchemas.v5,
googleSheetsGetOptionsSchemas.v6,
])
const googleSheetsInsertRowOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.INSERT_ROW]),
cellsToInsert: z.array(cellSchema).optional(),
})
)
const googleSheetsUpdateRowOptionsV5Schema =
googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.UPDATE_ROW]),
cellsToUpsert: z.array(cellSchema).optional(),
referenceCell: cellSchema.optional(),
filter: z
.object({
comparisons: z.array(rowsFilterComparisonSchema).optional(),
logicalOperator: z.nativeEnum(LogicalOperator).optional(),
})
.optional(),
})
)
const googleSheetsUpdateRowOptionsSchemas = {
v5: googleSheetsUpdateRowOptionsV5Schema,
v6: googleSheetsUpdateRowOptionsV5Schema.omit({
referenceCell: true,
}),
}
const googleSheetsUpdateRowOptionsSchema = z.union([
googleSheetsUpdateRowOptionsSchemas.v5,
googleSheetsUpdateRowOptionsSchemas.v6,
])
export const googleSheetsOptionsSchemas = {
v5: z.discriminatedUnion('action', [
googleSheetsGetOptionsSchemas.v5,
googleSheetsInsertRowOptionsSchema,
googleSheetsUpdateRowOptionsSchemas.v5,
initialGoogleSheetsOptionsSchema,
]),
v6: z.discriminatedUnion('action', [
googleSheetsGetOptionsSchemas.v6,
googleSheetsInsertRowOptionsSchema,
googleSheetsUpdateRowOptionsSchemas.v6,
initialGoogleSheetsOptionsSchema,
]),
}
export const googleSheetsBlockV5Schema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.GOOGLE_SHEETS]),
options: googleSheetsOptionsSchemas.v5.optional(),
})
)
export const googleSheetsBlockSchemas = {
v5: googleSheetsBlockV5Schema,
v6: googleSheetsBlockV5Schema.merge(
z.object({
options: googleSheetsOptionsSchemas.v6.optional(),
})
),
}
export const googleSheetsBlockSchema = z.union([
googleSheetsBlockSchemas.v5,
googleSheetsBlockSchemas.v6,
])
export const googleSheetsCredentialsSchema = z
.object({
type: z.literal('google sheets'),
data: z.object({
refresh_token: z.string().nullish(),
expiry_date: z.number().nullish(),
access_token: z.string().nullish(),
token_type: z.string().nullish(),
id_token: z.string().nullish(),
scope: z.string().optional(),
}),
})
.merge(credentialsBaseSchema)
export type GoogleSheetsBlock = z.infer<typeof googleSheetsBlockSchema>
export type GoogleSheetsBlockV5 = z.infer<typeof googleSheetsBlockSchemas.v5>
export type GoogleSheetsBlockV6 = z.infer<typeof googleSheetsBlockSchemas.v6>
export type GoogleSheetsOptionsBase = z.infer<
typeof googleSheetsOptionsBaseSchema
>
export type GoogleSheetsGetOptions = z.infer<
typeof googleSheetsGetOptionsSchema
>
export type GoogleSheetsGetOptionsV6 = z.infer<
typeof googleSheetsGetOptionsSchemas.v6
>
export type GoogleSheetsInsertRowOptions = z.infer<
typeof googleSheetsInsertRowOptionsSchema
>
export type GoogleSheetsUpdateRowOptions = z.infer<
typeof googleSheetsUpdateRowOptionsSchema
>
export type GoogleSheetsUpdateRowOptionsV6 = z.infer<
typeof googleSheetsUpdateRowOptionsSchemas.v6
>
export type Cell = z.infer<typeof cellSchema>
export type ExtractingCell = z.infer<typeof extractingCellSchema>
export type RowsFilterComparison = z.infer<typeof rowsFilterComparisonSchema>
export type GoogleSheetsCredentials = z.infer<
typeof googleSheetsCredentialsSchema
>

View File

@@ -1,167 +0,0 @@
import { z } from 'zod'
import { ComparisonOperators, LogicalOperator } from '../../logic/condition'
import { IntegrationBlockType } from '../enums'
import { GoogleSheetsAction } from './enums'
import { blockBaseSchema, credentialsBaseSchema } from '../../baseSchemas'
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 rowsFilterComparisonSchema = z.object({
id: z.string(),
column: z.string().optional(),
comparisonOperator: z.nativeEnum(ComparisonOperators).optional(),
value: z.string().optional(),
})
const initialGoogleSheetsOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.undefined(),
})
)
export const totalRowsToExtractOptions = [
'All',
'First',
'Last',
'Random',
] as const
const googleSheetsGetOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.GET]),
referenceCell: cellSchema
.optional()
.describe('Deprecated. Use `filter` instead.'),
filter: z
.object({
comparisons: z.array(rowsFilterComparisonSchema),
logicalOperator: z.nativeEnum(LogicalOperator),
})
.optional(),
cellsToExtract: z.array(extractingCellSchema),
totalRowsToExtract: z.enum(totalRowsToExtractOptions).optional(),
})
)
const googleSheetsInsertRowOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.INSERT_ROW]),
cellsToInsert: z.array(cellSchema),
})
)
const googleSheetsUpdateRowOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({
action: z.enum([GoogleSheetsAction.UPDATE_ROW]),
cellsToUpsert: z.array(cellSchema),
referenceCell: cellSchema
.optional()
.describe('Deprecated. Use `filter` instead.'),
filter: z
.object({
comparisons: z.array(rowsFilterComparisonSchema),
logicalOperator: z.nativeEnum(LogicalOperator),
})
.optional(),
})
)
export const googleSheetsOptionsSchema = z.discriminatedUnion('action', [
googleSheetsGetOptionsSchema,
googleSheetsInsertRowOptionsSchema,
googleSheetsUpdateRowOptionsSchema,
initialGoogleSheetsOptionsSchema,
])
export const googleSheetsBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.GOOGLE_SHEETS]),
options: googleSheetsOptionsSchema,
})
)
export const googleSheetsCredentialsSchema = z
.object({
type: z.literal('google sheets'),
data: z.object({
refresh_token: z.string().nullish(),
expiry_date: z.number().nullish(),
access_token: z.string().nullish(),
token_type: z.string().nullish(),
id_token: z.string().nullish(),
scope: z.string().optional(),
}),
})
.merge(credentialsBaseSchema)
export const defaultGoogleSheetsOptions: GoogleSheetsOptions = {}
export const defaultGoogleSheetsGetOptions = (
createId: () => string
): GoogleSheetsGetOptions => ({
action: GoogleSheetsAction.GET,
cellsToExtract: [
{
id: createId(),
},
],
})
export const defaultGoogleSheetsInsertOptions = (
createId: () => string
): GoogleSheetsInsertRowOptions => ({
action: GoogleSheetsAction.INSERT_ROW,
cellsToInsert: [
{
id: createId(),
},
],
})
export const defaultGoogleSheetsUpdateOptions = (
createId: () => string
): GoogleSheetsUpdateRowOptions => ({
action: GoogleSheetsAction.UPDATE_ROW,
cellsToUpsert: [
{
id: createId(),
},
],
})
export type GoogleSheetsBlock = z.infer<typeof googleSheetsBlockSchema>
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>
export type RowsFilterComparison = z.infer<typeof rowsFilterComparisonSchema>
export type GoogleSheetsCredentials = z.infer<
typeof googleSheetsCredentialsSchema
>

View File

@@ -1,12 +1,11 @@
export * from './chatwoot'
export * from './enums'
export * from './googleAnalytics'
export * from './googleSheets'
export * from './makeCom'
export * from './pabblyConnect'
export * from './sendEmail'
export * from './webhook/schemas'
export * from './webhook'
export * from './zapier'
export * from './pixel/schemas'
export * from './pixel/constants'
export * from './pixel'
export * from './zemanticAi'
export * from './schema'

View File

@@ -1,17 +0,0 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
import { webhookOptionsSchema } from './webhook/schemas'
export const makeComBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.MAKE_COM]),
options: webhookOptionsSchema,
webhookId: z
.string()
.describe('Deprecated, use webhook.id instead')
.optional(),
})
)
export type MakeComBlock = z.infer<typeof makeComBlockSchema>

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,23 @@
import { z } from 'zod'
import { IntegrationBlockType } from '../constants'
import { webhookBlockSchemas } from '../webhook'
export const makeComBlockSchemas = {
v5: webhookBlockSchemas.v5.merge(
z.object({
type: z.enum([IntegrationBlockType.MAKE_COM]),
})
),
v6: webhookBlockSchemas.v6.merge(
z.object({
type: z.enum([IntegrationBlockType.MAKE_COM]),
})
),
} as const
const makeComBlockSchema = z.union([
makeComBlockSchemas.v5,
makeComBlockSchemas.v6,
])
export type MakeComBlock = z.infer<typeof makeComBlockSchema>

View File

@@ -0,0 +1,29 @@
export const openAITasks = ['Create chat completion', 'Create image'] as const
export const chatCompletionMessageRoles = [
'system',
'user',
'assistant',
] as const
export const chatCompletionMessageCustomRoles = [
'Messages sequence ✨',
'Dialogue',
] as const
export const deprecatedRoles = ['Messages sequence ✨'] as const
export const chatCompletionResponseValues = [
'Message content',
'Total tokens',
] as const
export const defaultOpenAIOptions = {
baseUrl: 'https://api.openai.com/v1',
task: 'Create chat completion',
model: 'gpt-3.5-turbo',
} as const
export const defaultOpenAIResponseMappingItem = {
valueToExtract: 'Message content',
} as const

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,30 +1,17 @@
import { z } from 'zod'
import { variableStringSchema } from '../../utils'
import { blockBaseSchema, credentialsBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
export const openAITasks = ['Create chat completion', 'Create image'] as const
export const chatCompletionMessageRoles = [
'system',
'user',
'assistant',
] as const
export const chatCompletionMessageCustomRoles = [
'Messages sequence ✨',
] as const
export const chatCompletionResponseValues = [
'Message content',
'Total tokens',
] as const
export const defaultBaseUrl = 'https://api.openai.com/v1'
import {
chatCompletionMessageCustomRoles,
chatCompletionMessageRoles,
chatCompletionResponseValues,
openAITasks,
} from './constants'
import { variableStringSchema } from '../../../utils'
import { blockBaseSchema, credentialsBaseSchema } from '../../shared'
import { IntegrationBlockType } from '../constants'
const openAIBaseOptionsSchema = z.object({
credentialsId: z.string().optional(),
baseUrl: z.string().default(defaultBaseUrl),
baseUrl: z.string().optional(),
apiVersion: z.string().optional(),
})
@@ -34,16 +21,16 @@ const initialOptionsSchema = z
})
.merge(openAIBaseOptionsSchema)
export const chatCompletionMessageSchema = z.object({
export const nativeMessageSchema = z.object({
id: z.string(),
role: z.enum(chatCompletionMessageRoles).optional(),
content: z.string().optional(),
name: z.string().optional(),
})
const chatCompletionCustomMessageSchema = z.object({
const messageSequenceItemSchema = z.object({
id: z.string(),
role: z.enum(chatCompletionMessageCustomRoles),
role: z.literal('Messages sequence ✨'),
content: z
.object({
assistantMessagesVariableId: z.string().optional(),
@@ -52,28 +39,43 @@ const chatCompletionCustomMessageSchema = z.object({
.optional(),
})
const dialogueItemSchema = z.object({
id: z.string(),
role: z.literal('Dialogue'),
dialogueVariableId: z.string().optional(),
startsBy: z.enum(['user', 'assistant']).optional(),
})
const chatCompletionOptionsSchema = z
.object({
task: z.literal(openAITasks[0]),
model: z.string(),
messages: z.array(
z.union([chatCompletionMessageSchema, chatCompletionCustomMessageSchema])
),
model: z.string().optional(),
messages: z
.array(
z.union([
nativeMessageSchema,
messageSequenceItemSchema,
dialogueItemSchema,
])
)
.optional(),
advancedSettings: z
.object({
temperature: z.number().or(variableStringSchema).optional(),
})
.optional(),
responseMapping: z.array(
z.object({
id: z.string(),
valueToExtract: z.preprocess(
(val) => (!val ? 'Message content' : val),
z.enum(chatCompletionResponseValues)
),
variableId: z.string().optional(),
})
),
responseMapping: z
.array(
z.object({
id: z.string(),
valueToExtract: z.preprocess(
(val) => (!val ? 'Message content' : val),
z.enum(chatCompletionResponseValues)
),
variableId: z.string().optional(),
})
)
.optional(),
})
.merge(openAIBaseOptionsSchema)
@@ -97,11 +99,13 @@ const createImageOptionsSchema = z
export const openAIBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.OPEN_AI]),
options: z.discriminatedUnion('task', [
initialOptionsSchema,
chatCompletionOptionsSchema,
createImageOptionsSchema,
]),
options: z
.discriminatedUnion('task', [
initialOptionsSchema,
chatCompletionOptionsSchema,
createImageOptionsSchema,
])
.optional(),
})
)
@@ -114,25 +118,6 @@ export const openAICredentialsSchema = z
})
.merge(credentialsBaseSchema)
export const defaultChatCompletionOptions = (
createId: () => string
): ChatCompletionOpenAIOptions => ({
baseUrl: defaultBaseUrl,
task: 'Create chat completion',
messages: [
{
id: createId(),
},
],
responseMapping: [
{
id: createId(),
valueToExtract: 'Message content',
},
],
model: 'gpt-3.5-turbo',
})
export type OpenAICredentials = z.infer<typeof openAICredentialsSchema>
export type OpenAIBlock = z.infer<typeof openAIBlockSchema>
export type ChatCompletionOpenAIOptions = z.infer<

View File

@@ -1,17 +0,0 @@
import { z } from 'zod'
import { blockBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
import { webhookOptionsSchema } from './webhook/schemas'
export const pabblyConnectBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.PABBLY_CONNECT]),
options: webhookOptionsSchema,
webhookId: z
.string()
.describe('Deprecated, use webhook.id instead')
.optional(),
})
)
export type PabblyConnectBlock = z.infer<typeof pabblyConnectBlockSchema>

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -0,0 +1,23 @@
import { z } from 'zod'
import { IntegrationBlockType } from '../constants'
import { webhookBlockSchemas } from '../webhook'
export const pabblyConnectBlockSchemas = {
v5: webhookBlockSchemas.v5.merge(
z.object({
type: z.enum([IntegrationBlockType.PABBLY_CONNECT]),
})
),
v6: webhookBlockSchemas.v6.merge(
z.object({
type: z.enum([IntegrationBlockType.PABBLY_CONNECT]),
})
),
} as const
const pabblyConnectBlockSchema = z.union([
pabblyConnectBlockSchemas.v5,
pabblyConnectBlockSchemas.v6,
])
export type PabblyConnectBlock = z.infer<typeof pabblyConnectBlockSchema>

View File

@@ -1,5 +1,7 @@
// Reference: https://developers.facebook.com/docs/meta-pixel/reference#standard-events
import { PixelBlock } from './schema'
export const pixelEventTypes = [
'Lead',
'Contact',
@@ -132,3 +134,7 @@ export const pixelObjectProperties: {
],
},
]
export const defaultPixelOptions = {
isInitSkip: false,
} as const satisfies PixelBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,7 +1,7 @@
import { z } from 'zod'
import { pixelEventTypes } from './constants'
import { blockBaseSchema } from '../../baseSchemas'
import { IntegrationBlockType } from '../enums'
import { blockBaseSchema } from '../../shared'
import { IntegrationBlockType } from '../constants'
const basePixelOptionSchema = z.object({
pixelId: z.string().optional(),
@@ -45,7 +45,7 @@ export const pixelOptionsSchema = z.discriminatedUnion('eventType', [
export const pixelBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.PIXEL]),
options: pixelOptionsSchema,
options: pixelOptionsSchema.optional(),
})
)

View File

@@ -0,0 +1,58 @@
import { z } from 'zod'
import { chatwootBlockSchema } from './chatwoot'
import { googleAnalyticsBlockSchema } from './googleAnalytics'
import { googleSheetsBlockSchemas } from './googleSheets'
import { openAIBlockSchema } from './openai'
import { pixelBlockSchema } from './pixel/schema'
import { sendEmailBlockSchema } from './sendEmail'
import { zemanticAiBlockSchema } from './zemanticAi'
import { zapierBlockSchemas } from './zapier'
import { webhookBlockSchemas } from './webhook'
import { makeComBlockSchemas } from './makeCom'
import { pabblyConnectBlockSchemas } from './pabblyConnect'
export const integrationBlockSchemas = {
v5: [
chatwootBlockSchema,
googleAnalyticsBlockSchema,
googleSheetsBlockSchemas.v5,
makeComBlockSchemas.v5,
openAIBlockSchema,
pabblyConnectBlockSchemas.v5,
sendEmailBlockSchema,
webhookBlockSchemas.v5,
zapierBlockSchemas.v5,
pixelBlockSchema,
zemanticAiBlockSchema,
],
v6: [
chatwootBlockSchema,
googleAnalyticsBlockSchema,
googleSheetsBlockSchemas.v6,
makeComBlockSchemas.v6,
openAIBlockSchema,
pabblyConnectBlockSchemas.v6,
sendEmailBlockSchema,
webhookBlockSchemas.v6,
zapierBlockSchemas.v6,
pixelBlockSchema,
zemanticAiBlockSchema,
],
} as const
const integrationBlockV5Schema = z.discriminatedUnion('type', [
...integrationBlockSchemas.v5,
])
const integrationBlockV6Schema = z.discriminatedUnion('type', [
...integrationBlockSchemas.v6,
])
const integrationBlockSchema = z.union([
integrationBlockV5Schema,
integrationBlockV6Schema,
])
export type IntegrationBlock = z.infer<typeof integrationBlockSchema>
export type IntegrationBlockV5 = z.infer<typeof integrationBlockV5Schema>
export type IntegrationBlockV6 = z.infer<typeof integrationBlockV6Schema>

View File

@@ -0,0 +1,7 @@
import { SendEmailBlock } from './schema'
export const defaultSendEmailOptions = {
credentialsId: 'default',
isCustomBody: false,
isBodyCode: false,
} as const satisfies SendEmailBlock['options']

View File

@@ -0,0 +1 @@
export * from './schema'

View File

@@ -1,12 +1,12 @@
import { z } from 'zod'
import { blockBaseSchema, credentialsBaseSchema } from '../baseSchemas'
import { IntegrationBlockType } from './enums'
import { blockBaseSchema, credentialsBaseSchema } from '../../shared'
import { IntegrationBlockType } from '../constants'
export const sendEmailOptionsSchema = z.object({
credentialsId: z.string(),
credentialsId: z.string().optional(),
isCustomBody: z.boolean().optional(),
isBodyCode: z.boolean().optional(),
recipients: z.array(z.string()),
recipients: z.array(z.string()).optional(),
subject: z.string().optional(),
body: z.string().optional(),
replyTo: z.string().optional(),
@@ -18,7 +18,7 @@ export const sendEmailOptionsSchema = z.object({
export const sendEmailBlockSchema = blockBaseSchema.merge(
z.object({
type: z.enum([IntegrationBlockType.EMAIL]),
options: sendEmailOptionsSchema,
options: sendEmailOptionsSchema.optional(),
})
)
@@ -39,12 +39,5 @@ export const smtpCredentialsSchema = z
})
.merge(credentialsBaseSchema)
export const defaultSendEmailOptions: SendEmailOptions = {
credentialsId: 'default',
isCustomBody: false,
recipients: [],
}
export type SendEmailBlock = z.infer<typeof sendEmailBlockSchema>
export type SendEmailOptions = z.infer<typeof sendEmailOptionsSchema>
export type SmtpCredentials = z.infer<typeof smtpCredentialsSchema>

Some files were not shown because too many files have changed in this diff Show More