diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json
index 210bd8a64..2516920c6 100644
--- a/packages/embeds/js/package.json
+++ b/packages/embeds/js/package.json
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
- "version": "0.2.28",
+ "version": "0.2.29",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",
@@ -15,6 +15,7 @@
"@stripe/stripe-js": "1.54.1",
"@udecode/plate-common": "21.1.5",
"dompurify": "3.0.6",
+ "ky": "^1.1.3",
"marked": "9.0.3",
"solid-element": "1.7.1",
"solid-js": "1.7.8"
diff --git a/packages/embeds/js/src/components/Bot.tsx b/packages/embeds/js/src/components/Bot.tsx
index 6e1d473b1..e2f09792a 100644
--- a/packages/embeds/js/src/components/Bot.tsx
+++ b/packages/embeds/js/src/components/Bot.tsx
@@ -16,6 +16,7 @@ import { InputBlock } from '@typebot.io/schemas'
import { StartFrom } from '@typebot.io/schemas'
import { defaultTheme } from '@typebot.io/schemas/features/typebot/theme/constants'
import { clsx } from 'clsx'
+import { HTTPError } from 'ky'
export type BotProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -52,7 +53,7 @@ export const Bot = (props: BotProps & { class?: string }) => {
typeof props.typebot === 'string' ? props.typebot : undefined
const isPreview =
typeof props.typebot !== 'string' || (props.isPreview ?? false)
- const { data, error, response } = await startChatQuery({
+ const { data, error } = await startChatQuery({
stripeRedirectStatus: urlParams.get('redirect_status') ?? undefined,
typebot: props.typebot,
apiHost: props.apiHost,
@@ -66,24 +67,42 @@ export const Bot = (props: BotProps & { class?: string }) => {
},
startFrom: props.startFrom,
})
- if (error && 'code' in error && typeof error.code === 'string') {
+ if (error instanceof HTTPError) {
if (isPreview) {
return setError(
- new Error('An error occurred while loading the bot.', {
- cause: error.message,
+ new Error(`An error occurred while loading the bot.`, {
+ cause: {
+ status: error.response.status,
+ body: await error.response.json(),
+ },
})
)
}
- if (['BAD_REQUEST', 'FORBIDDEN'].includes(error.code))
+ if (error.response.status === 400 || error.response.status === 403)
return setError(new Error('This bot is now closed.'))
- if (error.code === 'NOT_FOUND')
+ if (error.response.status === 404)
return setError(new Error("The bot you're looking for doesn't exist."))
+ return setError(
+ new Error(
+ `Error! Couldn't initiate the chat. (${error.response.statusText})`
+ )
+ )
}
if (!data) {
- if (error) console.error(error)
- console.error({ data, error, response })
- return setError(new Error("Error! Couldn't initiate the chat."))
+ if (error) {
+ console.error(error)
+ if (isPreview) {
+ return setError(
+ new Error(`Error! Could not reach server. Check your connection.`, {
+ cause: error,
+ })
+ )
+ }
+ }
+ return setError(
+ new Error('Error! Could not reach server. Check your connection.')
+ )
}
if (data.resultId && typebotIdFromProps)
diff --git a/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx b/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx
index 7934fbd4e..1a89c79d7 100644
--- a/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx
+++ b/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx
@@ -31,6 +31,7 @@ import {
} from '@/utils/formattedMessagesSignal'
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
import { saveClientLogsQuery } from '@/queries/saveClientLogsQuery'
+import { HTTPError } from 'ky'
const parseDynamicTheme = (
initialTheme: Theme,
@@ -173,7 +174,13 @@ export const ConversationContainer = (props: Props) => {
const errorLogs = [
{
description: 'Failed to send the reply',
- details: error,
+ details:
+ error instanceof HTTPError
+ ? {
+ status: error.response.status,
+ body: await error.response.json(),
+ }
+ : error,
status: 'error',
},
]
diff --git a/packages/embeds/js/src/components/ErrorMessage.tsx b/packages/embeds/js/src/components/ErrorMessage.tsx
index 6399bbc54..2c834c90b 100644
--- a/packages/embeds/js/src/components/ErrorMessage.tsx
+++ b/packages/embeds/js/src/components/ErrorMessage.tsx
@@ -5,7 +5,7 @@ export const ErrorMessage = (props: Props) => {
return (
{props.error.message}
-
{props.error.cause as string}
+
{JSON.stringify(props.error.cause, null, 2) as string}
)
}
diff --git a/packages/embeds/js/src/queries/continueChatQuery.ts b/packages/embeds/js/src/queries/continueChatQuery.ts
index 04264b78c..9beff6f23 100644
--- a/packages/embeds/js/src/queries/continueChatQuery.ts
+++ b/packages/embeds/js/src/queries/continueChatQuery.ts
@@ -1,8 +1,9 @@
import { guessApiHost } from '@/utils/guessApiHost'
-import { isNotEmpty, sendRequest } from '@typebot.io/lib'
+import { isNotEmpty } from '@typebot.io/lib'
import { ContinueChatResponse } from '@typebot.io/schemas'
+import ky from 'ky'
-export const continueChatQuery = ({
+export const continueChatQuery = async ({
apiHost,
message,
sessionId,
@@ -10,13 +11,24 @@ export const continueChatQuery = ({
apiHost?: string
message: string | undefined
sessionId: string
-}) =>
- sendRequest({
- method: 'POST',
- url: `${
- isNotEmpty(apiHost) ? apiHost : guessApiHost()
- }/api/v1/sessions/${sessionId}/continueChat`,
- body: {
- message,
- },
- })
+}) => {
+ try {
+ const data = await ky
+ .post(
+ `${
+ isNotEmpty(apiHost) ? apiHost : guessApiHost()
+ }/api/v1/sessions/${sessionId}/continueChat`,
+ {
+ json: {
+ message,
+ },
+ timeout: false,
+ }
+ )
+ .json()
+
+ return { data }
+ } catch (error) {
+ return { error }
+ }
+}
diff --git a/packages/embeds/js/src/queries/getOpenAiStreamerQuery.ts b/packages/embeds/js/src/queries/getOpenAiStreamerQuery.ts
deleted file mode 100644
index 21012ac76..000000000
--- a/packages/embeds/js/src/queries/getOpenAiStreamerQuery.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { guessApiHost } from '@/utils/guessApiHost'
-import { isNotEmpty } from '@typebot.io/lib'
-
-export const getOpenAiStreamerQuery =
- ({ apiHost, sessionId }: { apiHost?: string; sessionId: string }) =>
- async (
- messages: {
- content?: string | undefined
- role?: 'system' | 'user' | 'assistant' | undefined
- }[]
- ) => {
- const response = await fetch(
- `${
- isNotEmpty(apiHost) ? apiHost : guessApiHost()
- }/api/integrations/openai/streamer`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- sessionId,
- messages,
- }),
- }
- )
- if (!response.ok) {
- throw new Error(response.statusText)
- }
-
- const data = response.body
- return data
- }
diff --git a/packages/embeds/js/src/queries/saveClientLogsQuery.ts b/packages/embeds/js/src/queries/saveClientLogsQuery.ts
index 47627da99..a0f3ac3dd 100644
--- a/packages/embeds/js/src/queries/saveClientLogsQuery.ts
+++ b/packages/embeds/js/src/queries/saveClientLogsQuery.ts
@@ -1,8 +1,9 @@
import { guessApiHost } from '@/utils/guessApiHost'
import type { ChatLog } from '@typebot.io/schemas'
-import { isNotEmpty, sendRequest } from '@typebot.io/lib'
+import { isNotEmpty } from '@typebot.io/lib'
+import ky from 'ky'
-export const saveClientLogsQuery = ({
+export const saveClientLogsQuery = async ({
apiHost,
sessionId,
clientLogs,
@@ -10,13 +11,19 @@ export const saveClientLogsQuery = ({
apiHost?: string
sessionId: string
clientLogs: ChatLog[]
-}) =>
- sendRequest({
- method: 'POST',
- url: `${
- isNotEmpty(apiHost) ? apiHost : guessApiHost()
- }/api/v1/sessions/${sessionId}/clientLogs`,
- body: {
- clientLogs,
- },
- })
+}) => {
+ try {
+ await ky.post(
+ `${
+ isNotEmpty(apiHost) ? apiHost : guessApiHost()
+ }/api/v1/sessions/${sessionId}/clientLogs`,
+ {
+ json: {
+ clientLogs,
+ },
+ }
+ )
+ } catch (e) {
+ console.log(e)
+ }
+}
diff --git a/packages/embeds/js/src/queries/startChatQuery.ts b/packages/embeds/js/src/queries/startChatQuery.ts
index e682b79bc..5fc6947bc 100644
--- a/packages/embeds/js/src/queries/startChatQuery.ts
+++ b/packages/embeds/js/src/queries/startChatQuery.ts
@@ -1,6 +1,6 @@
import { BotContext, InitialChatReply } from '@/types'
import { guessApiHost } from '@/utils/guessApiHost'
-import { isNotDefined, isNotEmpty, sendRequest } from '@typebot.io/lib'
+import { isNotDefined, isNotEmpty } from '@typebot.io/lib'
import {
getPaymentInProgressInStorage,
removePaymentInProgressFromStorage,
@@ -10,6 +10,18 @@ import {
StartFrom,
StartPreviewChatInput,
} from '@typebot.io/schemas'
+import ky from 'ky'
+
+type Props = {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ typebot: string | any
+ stripeRedirectStatus?: string
+ apiHost?: string
+ startFrom?: StartFrom
+ isPreview: boolean
+ prefilledVariables?: Record
+ resultId?: string
+}
export async function startChatQuery({
typebot,
@@ -19,16 +31,7 @@ export async function startChatQuery({
resultId,
stripeRedirectStatus,
startFrom,
-}: {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- typebot: string | any
- stripeRedirectStatus?: string
- apiHost?: string
- startFrom?: StartFrom
- isPreview: boolean
- prefilledVariables?: Record
- resultId?: string
-}) {
+}: Props) {
if (isNotDefined(typebot))
throw new Error('Typebot ID is required to get initial messages')
@@ -41,67 +44,75 @@ export async function startChatQuery({
: undefined
if (paymentInProgressState) {
removePaymentInProgressFromStorage()
- const { data, error, response } = await sendRequest({
- method: 'POST',
- url: `${isNotEmpty(apiHost) ? apiHost : guessApiHost()}/api/v1/sessions/${
- paymentInProgressState.sessionId
- }/continueChat`,
- body: {
- message: paymentInProgressState
- ? stripeRedirectStatus === 'failed'
- ? 'fail'
- : 'Success'
- : undefined,
- },
- })
- return {
- data: data
- ? {
- ...data,
- ...(paymentInProgressState
- ? { typebot: paymentInProgressState.typebot }
- : {}),
+
+ try {
+ const data = await ky
+ .post(
+ `${isNotEmpty(apiHost) ? apiHost : guessApiHost()}/api/v1/sessions/${
+ paymentInProgressState.sessionId
+ }/continueChat`,
+ {
+ json: {
+ message: paymentInProgressState
+ ? stripeRedirectStatus === 'failed'
+ ? 'fail'
+ : 'Success'
+ : undefined,
+ },
+ timeout: false,
}
- : undefined,
- error,
- response,
+ )
+ .json()
+
+ return { data }
+ } catch (error) {
+ return { error }
}
}
const typebotId = typeof typebot === 'string' ? typebot : typebot.id
if (isPreview) {
- const { data, error, response } = await sendRequest({
- method: 'POST',
- url: `${
- isNotEmpty(apiHost) ? apiHost : guessApiHost()
- }/api/v1/typebots/${typebotId}/preview/startChat`,
- body: {
- isStreamEnabled: true,
- startFrom,
- typebot,
- } satisfies Omit,
- })
- return {
- data,
- error,
- response,
+ try {
+ const data = await ky
+ .post(
+ `${
+ isNotEmpty(apiHost) ? apiHost : guessApiHost()
+ }/api/v1/typebots/${typebotId}/preview/startChat`,
+ {
+ json: {
+ isStreamEnabled: true,
+ startFrom,
+ typebot,
+ } satisfies Omit,
+ timeout: false,
+ }
+ )
+ .json()
+
+ return { data }
+ } catch (error) {
+ return { error }
}
}
- const { data, error, response } = await sendRequest({
- method: 'POST',
- url: `${
- isNotEmpty(apiHost) ? apiHost : guessApiHost()
- }/api/v1/typebots/${typebotId}/startChat`,
- body: {
- isStreamEnabled: true,
- prefilledVariables,
- resultId,
- } satisfies Omit,
- })
+ try {
+ const data = await ky
+ .post(
+ `${
+ isNotEmpty(apiHost) ? apiHost : guessApiHost()
+ }/api/v1/typebots/${typebotId}/startChat`,
+ {
+ json: {
+ isStreamEnabled: true,
+ prefilledVariables,
+ resultId,
+ } satisfies Omit,
+ timeout: false,
+ }
+ )
+ .json()
- return {
- data,
- error,
- response,
+ return { data }
+ } catch (error) {
+ return { error }
}
}
diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json
index 187711d4e..a778dce5f 100644
--- a/packages/embeds/nextjs/package.json
+++ b/packages/embeds/nextjs/package.json
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/nextjs",
- "version": "0.2.28",
+ "version": "0.2.29",
"description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json
index 42da16137..255d382fd 100644
--- a/packages/embeds/react/package.json
+++ b/packages/embeds/react/package.json
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
- "version": "0.2.28",
+ "version": "0.2.29",
"description": "Convenient library to display typebots on your React app",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6b285ac8d..d69c71e0e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -956,6 +956,9 @@ importers:
dompurify:
specifier: 3.0.6
version: 3.0.6
+ ky:
+ specifier: ^1.1.3
+ version: 1.1.3
marked:
specifier: 9.0.3
version: 9.0.3
@@ -17743,6 +17746,11 @@ packages:
resolution: {integrity: sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==}
dev: true
+ /ky@1.1.3:
+ resolution: {integrity: sha512-t7q8sJfazzHbfYxiCtuLIH4P+pWoCgunDll17O/GBZBqMt2vHjGSx5HzSxhOc2BDEg3YN/EmeA7VKrHnwuWDag==}
+ engines: {node: '>=18'}
+ dev: false
+
/language-subtag-registry@0.3.22:
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
dev: false