♻️ (viewer) Remove barrel exports and flatten folder arch
This commit is contained in:
@ -13,7 +13,7 @@
|
|||||||
"write-translations": "docusaurus write-translations",
|
"write-translations": "docusaurus write-translations",
|
||||||
"write-heading-ids": "docusaurus write-heading-ids",
|
"write-heading-ids": "docusaurus write-heading-ids",
|
||||||
"update-search": "docker run -it --rm --env-file=.env -e \"CONFIG=$(cat docsearch-scrapper-config.json | jq -r tostring)\" algolia/docsearch-scraper",
|
"update-search": "docker run -it --rm --env-file=.env -e \"CONFIG=$(cat docsearch-scrapper-config.json | jq -r tostring)\" algolia/docsearch-scraper",
|
||||||
"api:generate": "tsx --tsconfig ../builder/tsconfig.json ../builder/src/helpers/server/generateOpenApi.ts && tsx --tsconfig ../viewer/openapi.tsconfig.json ../viewer/src/utils/server/generateOpenApi.ts"
|
"api:generate": "tsx --tsconfig ../builder/tsconfig.json ../builder/src/helpers/server/generateOpenApi.ts && tsx --tsconfig ../viewer/openapi.tsconfig.json ../viewer/src/helpers/server/generateOpenApi.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "2.3.1",
|
"@docusaurus/core": "2.3.1",
|
||||||
|
@ -15,13 +15,14 @@ import {
|
|||||||
} from '@typebot.io/lib'
|
} from '@typebot.io/lib'
|
||||||
import { SEO } from './Seo'
|
import { SEO } from './Seo'
|
||||||
import { ErrorPage } from './ErrorPage'
|
import { ErrorPage } from './ErrorPage'
|
||||||
import { createResultQuery, updateResultQuery } from '@/features/results'
|
|
||||||
import { upsertAnswerQuery } from '@/features/answers'
|
|
||||||
import { gtmBodyElement } from '@/lib/google-tag-manager'
|
import { gtmBodyElement } from '@/lib/google-tag-manager'
|
||||||
import {
|
import {
|
||||||
getExistingResultFromSession,
|
getExistingResultFromSession,
|
||||||
setResultInSession,
|
setResultInSession,
|
||||||
} from '@/utils/sessionStorage'
|
} from '@/helpers/sessionStorage'
|
||||||
|
import { upsertAnswerQuery } from '@/features/answers/queries/upsertAnswerQuery'
|
||||||
|
import { createResultQuery } from '@/features/results/queries/createResultQuery'
|
||||||
|
import { updateResultQuery } from '@/features/results/queries/updateResultQuery'
|
||||||
|
|
||||||
export type TypebotPageProps = {
|
export type TypebotPageProps = {
|
||||||
publishedTypebot: Omit<PublicTypebot, 'createdAt' | 'updatedAt'> & {
|
publishedTypebot: Omit<PublicTypebot, 'createdAt' | 'updatedAt'> & {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { upsertAnswerQuery } from './queries/upsertAnswerQuery'
|
|
@ -1 +0,0 @@
|
|||||||
export { authenticateUser } from './authenticateUser'
|
|
@ -1,4 +1,3 @@
|
|||||||
import { deepParseVariable } from '@/features/variables/utils'
|
|
||||||
import {
|
import {
|
||||||
SessionState,
|
SessionState,
|
||||||
VariableWithValue,
|
VariableWithValue,
|
||||||
@ -6,6 +5,7 @@ import {
|
|||||||
ItemType,
|
ItemType,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { isDefined } from '@typebot.io/lib'
|
import { isDefined } from '@typebot.io/lib'
|
||||||
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
|
|
||||||
export const injectVariableValuesInButtonsInputBlock =
|
export const injectVariableValuesInButtonsInputBlock =
|
||||||
(variables: SessionState['typebot']['variables']) =>
|
(variables: SessionState['typebot']['variables']) =>
|
||||||
@ -27,5 +27,5 @@ export const injectVariableValuesInButtonsInputBlock =
|
|||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return deepParseVariable(variables)(block)
|
return deepParseVariables(variables)(block)
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './parseReadableDate'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './validateEmail'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './computePaymentInputRuntimeOptions'
|
|
@ -1,4 +1,4 @@
|
|||||||
import { parseVariables } from '@/features/variables'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import {
|
import {
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './formatPhoneNumber'
|
|
||||||
export * from './validatePhoneNumber'
|
|
@ -1 +0,0 @@
|
|||||||
export { validateUrl } from './utils/validateUrl'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './utils/executeChatwootBlock'
|
|
@ -1,9 +1,7 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
import {
|
import { extractVariablesFromText } from '@/features/variables/extractVariablesFromText'
|
||||||
parseVariables,
|
import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType'
|
||||||
parseCorrectValueType,
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
extractVariablesFromText,
|
|
||||||
} from '@/features/variables'
|
|
||||||
import {
|
import {
|
||||||
ChatwootBlock,
|
ChatwootBlock,
|
||||||
ChatwootOptions,
|
ChatwootOptions,
|
||||||
@ -85,7 +83,7 @@ export const executeChatwootBlock = (
|
|||||||
args: extractVariablesFromText(variables)(chatwootCode).map(
|
args: extractVariablesFromText(variables)(chatwootCode).map(
|
||||||
(variable) => ({
|
(variable) => ({
|
||||||
id: variable.id,
|
id: variable.id,
|
||||||
value: parseCorrectValueType(variable.value),
|
value: parseGuessedValueType(variable.value),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
},
|
},
|
@ -1 +0,0 @@
|
|||||||
export { executeGoogleAnalyticsBlock } from './utils/executeGoogleAnalyticsBlock'
|
|
@ -1,5 +1,5 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
import { deepParseVariable } from '@/features/variables'
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
import { GoogleAnalyticsBlock, SessionState } from '@typebot.io/schemas'
|
import { GoogleAnalyticsBlock, SessionState } from '@typebot.io/schemas'
|
||||||
|
|
||||||
export const executeGoogleAnalyticsBlock = (
|
export const executeGoogleAnalyticsBlock = (
|
||||||
@ -10,7 +10,7 @@ export const executeGoogleAnalyticsBlock = (
|
|||||||
outgoingEdgeId: block.outgoingEdgeId,
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
clientSideActions: [
|
clientSideActions: [
|
||||||
{
|
{
|
||||||
googleAnalytics: deepParseVariable(variables)(block.options),
|
googleAnalytics: deepParseVariables(variables)(block.options),
|
||||||
lastBubbleBlockId,
|
lastBubbleBlockId,
|
||||||
},
|
},
|
||||||
],
|
],
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './executeGoogleSheetBlock'
|
|
@ -1,12 +1,12 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
|
||||||
import {
|
import {
|
||||||
GoogleSheetsBlock,
|
GoogleSheetsBlock,
|
||||||
GoogleSheetsAction,
|
GoogleSheetsAction,
|
||||||
SessionState,
|
SessionState,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { getRow } from './getRow'
|
|
||||||
import { insertRow } from './insertRow'
|
import { insertRow } from './insertRow'
|
||||||
import { updateRow } from './updateRow'
|
import { updateRow } from './updateRow'
|
||||||
|
import { getRow } from './getRow'
|
||||||
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
|
||||||
export const executeGoogleSheetBlock = async (
|
export const executeGoogleSheetBlock = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
@ -6,12 +6,13 @@ import {
|
|||||||
LogicalOperator,
|
LogicalOperator,
|
||||||
ReplyLog,
|
ReplyLog,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { saveErrorLog } from '@/features/logs/api'
|
|
||||||
import { getAuthenticatedGoogleDoc } from './helpers'
|
|
||||||
import { deepParseVariable, updateVariables } from '@/features/variables'
|
|
||||||
import { isNotEmpty, byId, isDefined } from '@typebot.io/lib'
|
import { isNotEmpty, byId, isDefined } from '@typebot.io/lib'
|
||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
|
||||||
import type { GoogleSpreadsheetRow } from 'google-spreadsheet'
|
import type { GoogleSpreadsheetRow } from 'google-spreadsheet'
|
||||||
|
import { getAuthenticatedGoogleDoc } from './helpers/getAuthenticatedGoogleDoc'
|
||||||
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
|
|
||||||
export const getRow = async (
|
export const getRow = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
@ -20,7 +21,7 @@ export const getRow = async (
|
|||||||
options,
|
options,
|
||||||
}: { outgoingEdgeId?: string; options: GoogleSheetsGetOptions }
|
}: { outgoingEdgeId?: string; options: GoogleSheetsGetOptions }
|
||||||
): Promise<ExecuteIntegrationResponse> => {
|
): Promise<ExecuteIntegrationResponse> => {
|
||||||
const { sheetId, cellsToExtract, referenceCell, filter } = deepParseVariable(
|
const { sheetId, cellsToExtract, referenceCell, filter } = deepParseVariables(
|
||||||
state.typebot.variables
|
state.typebot.variables
|
||||||
)(options)
|
)(options)
|
||||||
if (!sheetId) return { outgoingEdgeId }
|
if (!sheetId) return { outgoingEdgeId }
|
@ -1,20 +1,6 @@
|
|||||||
import { parseVariables } from '@/features/variables'
|
|
||||||
import { getAuthenticatedGoogleClient } from '@/lib/google-sheets'
|
import { getAuthenticatedGoogleClient } from '@/lib/google-sheets'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { GoogleSpreadsheet } from 'google-spreadsheet'
|
import { GoogleSpreadsheet } from 'google-spreadsheet'
|
||||||
import { Variable, Cell } from '@typebot.io/schemas'
|
|
||||||
|
|
||||||
export const parseCellValues =
|
|
||||||
(variables: Variable[]) =>
|
|
||||||
(cells: Cell[]): { [key: string]: string } =>
|
|
||||||
cells.reduce((row, cell) => {
|
|
||||||
return !cell.column || !cell.value
|
|
||||||
? row
|
|
||||||
: {
|
|
||||||
...row,
|
|
||||||
[cell.column]: parseVariables(variables)(cell.value),
|
|
||||||
}
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
export const getAuthenticatedGoogleDoc = async ({
|
export const getAuthenticatedGoogleDoc = async ({
|
||||||
credentialsId,
|
credentialsId,
|
@ -0,0 +1,14 @@
|
|||||||
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
|
import { Variable, Cell } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const parseCellValues =
|
||||||
|
(variables: Variable[]) =>
|
||||||
|
(cells: Cell[]): { [key: string]: string } =>
|
||||||
|
cells.reduce((row, cell) => {
|
||||||
|
return !cell.column || !cell.value
|
||||||
|
? row
|
||||||
|
: {
|
||||||
|
...row,
|
||||||
|
[cell.column]: parseVariables(variables)(cell.value),
|
||||||
|
}
|
||||||
|
}, {})
|
@ -3,9 +3,11 @@ import {
|
|||||||
GoogleSheetsInsertRowOptions,
|
GoogleSheetsInsertRowOptions,
|
||||||
ReplyLog,
|
ReplyLog,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { saveErrorLog, saveSuccessLog } from '@/features/logs/api'
|
import { parseCellValues } from './helpers/parseCellValues'
|
||||||
import { getAuthenticatedGoogleDoc, parseCellValues } from './helpers'
|
import { getAuthenticatedGoogleDoc } from './helpers/getAuthenticatedGoogleDoc'
|
||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
|
||||||
export const insertRow = async (
|
export const insertRow = async (
|
||||||
{ result, typebot: { variables } }: SessionState,
|
{ result, typebot: { variables } }: SessionState,
|
@ -3,11 +3,13 @@ import {
|
|||||||
GoogleSheetsUpdateRowOptions,
|
GoogleSheetsUpdateRowOptions,
|
||||||
ReplyLog,
|
ReplyLog,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { saveErrorLog, saveSuccessLog } from '@/features/logs/api'
|
|
||||||
import { getAuthenticatedGoogleDoc, parseCellValues } from './helpers'
|
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { deepParseVariable } from '@/features/variables'
|
import { parseCellValues } from './helpers/parseCellValues'
|
||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
import { getAuthenticatedGoogleDoc } from './helpers/getAuthenticatedGoogleDoc'
|
||||||
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
|
||||||
export const updateRow = async (
|
export const updateRow = async (
|
||||||
{ result, typebot: { variables } }: SessionState,
|
{ result, typebot: { variables } }: SessionState,
|
||||||
@ -16,7 +18,7 @@ export const updateRow = async (
|
|||||||
options,
|
options,
|
||||||
}: { outgoingEdgeId?: string; options: GoogleSheetsUpdateRowOptions }
|
}: { outgoingEdgeId?: string; options: GoogleSheetsUpdateRowOptions }
|
||||||
): Promise<ExecuteIntegrationResponse> => {
|
): Promise<ExecuteIntegrationResponse> => {
|
||||||
const { sheetId, referenceCell } = deepParseVariable(variables)(options)
|
const { sheetId, referenceCell } = deepParseVariables(variables)(options)
|
||||||
if (!options.cellsToUpsert || !sheetId || !referenceCell)
|
if (!options.cellsToUpsert || !sheetId || !referenceCell)
|
||||||
return { outgoingEdgeId }
|
return { outgoingEdgeId }
|
||||||
|
|
@ -1,7 +1,5 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
import { saveErrorLog } from '@/features/logs/api'
|
|
||||||
import { transformStringVariablesToList } from '@/features/variables/transformVariablesToList'
|
import { transformStringVariablesToList } from '@/features/variables/transformVariablesToList'
|
||||||
import { parseVariables, updateVariables } from '@/features/variables/utils'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import {
|
import {
|
||||||
SessionState,
|
SessionState,
|
||||||
@ -16,6 +14,9 @@ import {
|
|||||||
import { OpenAIApi, Configuration, ChatCompletionRequestMessage } from 'openai'
|
import { OpenAIApi, Configuration, ChatCompletionRequestMessage } from 'openai'
|
||||||
import { isDefined, byId, isNotEmpty } from '@typebot.io/lib'
|
import { isDefined, byId, isNotEmpty } from '@typebot.io/lib'
|
||||||
import { decrypt } from '@typebot.io/lib/api/encryption'
|
import { decrypt } from '@typebot.io/lib/api/encryption'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
|
import { parseVariables } from 'bot-engine'
|
||||||
|
|
||||||
export const createChatCompletionOpenAI = async (
|
export const createChatCompletionOpenAI = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { executeSendEmailBlock } from './utils/executeSendEmailBlock'
|
|
@ -1,6 +1,4 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import { saveErrorLog, saveSuccessLog } from '@/features/logs/api'
|
|
||||||
import { parseVariables } from '@/features/variables'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { render } from '@faire/mjml-react/utils/render'
|
import { render } from '@faire/mjml-react/utils/render'
|
||||||
import { DefaultBotNotificationEmail } from '@typebot.io/emails'
|
import { DefaultBotNotificationEmail } from '@typebot.io/emails'
|
||||||
@ -17,7 +15,10 @@ import Mail from 'nodemailer/lib/mailer'
|
|||||||
import { byId, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
|
import { byId, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
|
||||||
import { parseAnswers } from '@typebot.io/lib/results'
|
import { parseAnswers } from '@typebot.io/lib/results'
|
||||||
import { decrypt } from '@typebot.io/lib/api'
|
import { decrypt } from '@typebot.io/lib/api'
|
||||||
import { defaultFrom, defaultTransportOptions } from '../constants'
|
import { defaultFrom, defaultTransportOptions } from './constants'
|
||||||
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
|
||||||
export const executeSendEmailBlock = async (
|
export const executeSendEmailBlock = async (
|
||||||
{ result, typebot }: SessionState,
|
{ result, typebot }: SessionState,
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './executeWebhookBlock'
|
|
||||||
export * from './parseSampleResult'
|
|
@ -1,6 +1,3 @@
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat'
|
|
||||||
import { saveErrorLog, saveSuccessLog } from '@/features/logs/api'
|
|
||||||
import { parseVariables, updateVariables } from '@/features/variables'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import {
|
import {
|
||||||
WebhookBlock,
|
WebhookBlock,
|
||||||
@ -26,6 +23,11 @@ import { byId, omit } from '@typebot.io/lib'
|
|||||||
import { parseAnswers } from '@typebot.io/lib/results'
|
import { parseAnswers } from '@typebot.io/lib/results'
|
||||||
import got, { Method, Headers, HTTPError } from 'got'
|
import got, { Method, Headers, HTTPError } from 'got'
|
||||||
import { parseSampleResult } from './parseSampleResult'
|
import { parseSampleResult } from './parseSampleResult'
|
||||||
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
|
import { parseVariables } from 'bot-engine'
|
||||||
|
|
||||||
export const executeWebhookBlock = async (
|
export const executeWebhookBlock = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
@ -1 +0,0 @@
|
|||||||
export { executeCondition } from './utils/executeCondition'
|
|
@ -1,5 +1,3 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
|
||||||
import { findUniqueVariableValue, parseVariables } from '@/features/variables'
|
|
||||||
import {
|
import {
|
||||||
Comparison,
|
Comparison,
|
||||||
ComparisonOperators,
|
ComparisonOperators,
|
||||||
@ -9,6 +7,9 @@ import {
|
|||||||
Variable,
|
Variable,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { isNotDefined, isDefined } from '@typebot.io/lib'
|
import { isNotDefined, isDefined } from '@typebot.io/lib'
|
||||||
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
|
import { findUniqueVariableValue } from '@/features/variables/findUniqueVariableValue'
|
||||||
|
import { parseVariables } from 'bot-engine'
|
||||||
|
|
||||||
export const executeCondition = (
|
export const executeCondition = (
|
||||||
{ typebot: { variables } }: SessionState,
|
{ typebot: { variables } }: SessionState,
|
@ -1,8 +1,8 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
|
||||||
import {
|
import {
|
||||||
addEdgeToTypebot,
|
addEdgeToTypebot,
|
||||||
createPortalEdge,
|
createPortalEdge,
|
||||||
} from '@/features/chat/api/utils/addEdgeToTypebot'
|
} from '@/features/chat/helpers/addEdgeToTypebot'
|
||||||
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { SessionState } from '@typebot.io/schemas'
|
import { SessionState } from '@typebot.io/schemas'
|
||||||
import { JumpBlock } from '@typebot.io/schemas/features/blocks/logic/jump'
|
import { JumpBlock } from '@typebot.io/schemas/features/blocks/logic/jump'
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { executeRedirect } from './utils/executeRedirect'
|
|
@ -1,7 +1,7 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import { parseVariables } from '@/features/variables'
|
|
||||||
import { RedirectBlock, SessionState } from '@typebot.io/schemas'
|
import { RedirectBlock, SessionState } from '@typebot.io/schemas'
|
||||||
import { sanitizeUrl } from '@typebot.io/lib'
|
import { sanitizeUrl } from '@typebot.io/lib'
|
||||||
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
|
|
||||||
export const executeRedirect = (
|
export const executeRedirect = (
|
||||||
{ typebot: { variables } }: SessionState,
|
{ typebot: { variables } }: SessionState,
|
@ -1,9 +1,7 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
import {
|
import { extractVariablesFromText } from '@/features/variables/extractVariablesFromText'
|
||||||
parseVariables,
|
import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType'
|
||||||
parseCorrectValueType,
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
extractVariablesFromText,
|
|
||||||
} from '@/features/variables'
|
|
||||||
import { ScriptBlock, SessionState } from '@typebot.io/schemas'
|
import { ScriptBlock, SessionState } from '@typebot.io/schemas'
|
||||||
|
|
||||||
export const executeScript = (
|
export const executeScript = (
|
||||||
@ -19,7 +17,7 @@ export const executeScript = (
|
|||||||
const args = extractVariablesFromText(variables)(block.options.content).map(
|
const args = extractVariablesFromText(variables)(block.options.content).map(
|
||||||
(variable) => ({
|
(variable) => ({
|
||||||
id: variable.id,
|
id: variable.id,
|
||||||
value: parseCorrectValueType(variable.value),
|
value: parseGuessedValueType(variable.value),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { executeSetVariable } from './utils/executeSetVariable'
|
|
@ -1,11 +1,9 @@
|
|||||||
import { SessionState, SetVariableBlock, Variable } from '@typebot.io/schemas'
|
import { SessionState, SetVariableBlock, Variable } from '@typebot.io/schemas'
|
||||||
import { byId } from '@typebot.io/lib'
|
import { byId } from '@typebot.io/lib'
|
||||||
import {
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
parseVariables,
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
parseCorrectValueType,
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
updateVariables,
|
import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType'
|
||||||
} from '@/features/variables'
|
|
||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
|
||||||
|
|
||||||
export const executeSetVariable = async (
|
export const executeSetVariable = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
@ -45,7 +43,7 @@ const evaluateSetVariableExpression =
|
|||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
const func = Function(...variables.map((v) => v.id), evaluating)
|
const func = Function(...variables.map((v) => v.id), evaluating)
|
||||||
return func(...variables.map((v) => parseCorrectValueType(v.value)))
|
return func(...variables.map((v) => parseGuessedValueType(v.value)))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return parseVariables(variables)(str)
|
return parseVariables(variables)(str)
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1,3 +0,0 @@
|
|||||||
export * from './executeTypebotLink'
|
|
||||||
export * from './getLinkedTypebots'
|
|
||||||
export * from './getLinkedTypebotsChildren'
|
|
@ -1,9 +1,7 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
|
||||||
import {
|
import {
|
||||||
addEdgeToTypebot,
|
addEdgeToTypebot,
|
||||||
createPortalEdge,
|
createPortalEdge,
|
||||||
} from '@/features/chat/api/utils/addEdgeToTypebot'
|
} from '@/features/chat/helpers/addEdgeToTypebot'
|
||||||
import { saveErrorLog } from '@/features/logs/api'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import {
|
import {
|
||||||
TypebotLinkBlock,
|
TypebotLinkBlock,
|
||||||
@ -12,6 +10,8 @@ import {
|
|||||||
Variable,
|
Variable,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { byId } from '@typebot.io/lib'
|
import { byId } from '@typebot.io/lib'
|
||||||
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
|
||||||
export const executeTypebotLink = async (
|
export const executeTypebotLink = async (
|
||||||
state: SessionState,
|
state: SessionState,
|
@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { canReadTypebots } from '@/utils/api/dbRules'
|
import { canReadTypebots } from '@/helpers/api/dbRules'
|
||||||
import { User } from '@typebot.io/prisma'
|
import { User } from '@typebot.io/prisma'
|
||||||
import {
|
import {
|
||||||
LogicBlockType,
|
LogicBlockType,
|
@ -1,5 +1,5 @@
|
|||||||
import { ExecuteLogicResponse } from '@/features/chat'
|
import { ExecuteLogicResponse } from '@/features/chat/types'
|
||||||
import { parseVariables } from '@/features/variables'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import { SessionState, WaitBlock } from '@typebot.io/schemas'
|
import { SessionState, WaitBlock } from '@typebot.io/schemas'
|
||||||
|
|
||||||
export const executeWait = async (
|
export const executeWait = async (
|
@ -1,6 +0,0 @@
|
|||||||
import { router } from '@/utils/server/trpc'
|
|
||||||
import { sendMessageProcedure } from './procedures'
|
|
||||||
|
|
||||||
export const chatRouter = router({
|
|
||||||
sendMessage: sendMessageProcedure,
|
|
||||||
})
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './chatRouter'
|
|
||||||
export { getSession } from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './sendMessageProcedure'
|
|
6
apps/viewer/src/features/chat/api/router.ts
Normal file
6
apps/viewer/src/features/chat/api/router.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { router } from '@/helpers/server/trpc'
|
||||||
|
import { sendMessage } from './sendMessage'
|
||||||
|
|
||||||
|
export const chatRouter = router({
|
||||||
|
sendMessage,
|
||||||
|
})
|
@ -1,12 +1,5 @@
|
|||||||
import { checkChatsUsage } from '@/features/usage'
|
|
||||||
import {
|
|
||||||
prefillVariables,
|
|
||||||
deepParseVariable,
|
|
||||||
parseVariables,
|
|
||||||
injectVariablesFromExistingResult,
|
|
||||||
} from '@/features/variables'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { publicProcedure } from '@/utils/server/trpc'
|
import { publicProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Prisma } from '@typebot.io/prisma'
|
import { Prisma } from '@typebot.io/prisma'
|
||||||
import {
|
import {
|
||||||
@ -28,10 +21,15 @@ import {
|
|||||||
getSession,
|
getSession,
|
||||||
setResultAsCompleted,
|
setResultAsCompleted,
|
||||||
startBotFlow,
|
startBotFlow,
|
||||||
} from '../utils'
|
} from '../helpers'
|
||||||
import { env, isDefined, omit } from '@typebot.io/lib'
|
import { env, isDefined, omit } from '@typebot.io/lib'
|
||||||
|
import { prefillVariables } from '@/features/variables/prefillVariables'
|
||||||
|
import { checkChatsUsage } from '@/features/usage/checkChatsUsage'
|
||||||
|
import { injectVariablesFromExistingResult } from '@/features/variables/injectVariablesFromExistingResult'
|
||||||
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
|
|
||||||
export const sendMessageProcedure = publicProcedure
|
export const sendMessage = publicProcedure
|
||||||
.meta({
|
.meta({
|
||||||
openapi: {
|
openapi: {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -165,10 +163,10 @@ const startSession = async (startParams?: StartParams, userId?: string) => {
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
typebot: {
|
typebot: {
|
||||||
id: typebot.id,
|
id: typebot.id,
|
||||||
settings: deepParseVariable(newInitialState.typebot.variables)(
|
settings: deepParseVariables(newInitialState.typebot.variables)(
|
||||||
typebot.settings
|
typebot.settings
|
||||||
),
|
),
|
||||||
theme: deepParseVariable(newInitialState.typebot.variables)(
|
theme: deepParseVariables(newInitialState.typebot.variables)(
|
||||||
typebot.theme
|
typebot.theme
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -195,10 +193,10 @@ const startSession = async (startParams?: StartParams, userId?: string) => {
|
|||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
typebot: {
|
typebot: {
|
||||||
id: typebot.id,
|
id: typebot.id,
|
||||||
settings: deepParseVariable(newInitialState.typebot.variables)(
|
settings: deepParseVariables(newInitialState.typebot.variables)(
|
||||||
typebot.settings
|
typebot.settings
|
||||||
),
|
),
|
||||||
theme: deepParseVariable(newInitialState.typebot.variables)(
|
theme: deepParseVariables(newInitialState.typebot.variables)(
|
||||||
typebot.theme
|
typebot.theme
|
||||||
),
|
),
|
||||||
},
|
},
|
@ -1,10 +1,3 @@
|
|||||||
import { validateEmail } from '@/features/blocks/inputs/email/api'
|
|
||||||
import {
|
|
||||||
formatPhoneNumber,
|
|
||||||
validatePhoneNumber,
|
|
||||||
} from '@/features/blocks/inputs/phone/api'
|
|
||||||
import { validateUrl } from '@/features/blocks/inputs/url/api'
|
|
||||||
import { parseVariables, updateVariables } from '@/features/variables'
|
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Prisma } from '@typebot.io/prisma'
|
import { Prisma } from '@typebot.io/prisma'
|
||||||
@ -22,6 +15,12 @@ import {
|
|||||||
import { isInputBlock, isNotDefined } from '@typebot.io/lib'
|
import { isInputBlock, isNotDefined } from '@typebot.io/lib'
|
||||||
import { executeGroup } from './executeGroup'
|
import { executeGroup } from './executeGroup'
|
||||||
import { getNextGroup } from './getNextGroup'
|
import { getNextGroup } from './getNextGroup'
|
||||||
|
import { validateEmail } from '@/features/blocks/inputs/email/validateEmail'
|
||||||
|
import { formatPhoneNumber } from '@/features/blocks/inputs/phone/formatPhoneNumber'
|
||||||
|
import { validatePhoneNumber } from '@/features/blocks/inputs/phone/validatePhoneNumber'
|
||||||
|
import { validateUrl } from '@/features/blocks/inputs/url/validateUrl'
|
||||||
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
|
|
||||||
export const continueBotFlow =
|
export const continueBotFlow =
|
||||||
(state: SessionState) =>
|
(state: SessionState) =>
|
@ -1,4 +1,3 @@
|
|||||||
import { deepParseVariable } from '@/features/variables'
|
|
||||||
import {
|
import {
|
||||||
BubbleBlock,
|
BubbleBlock,
|
||||||
BubbleBlockType,
|
BubbleBlockType,
|
||||||
@ -19,8 +18,9 @@ import {
|
|||||||
import { executeLogic } from './executeLogic'
|
import { executeLogic } from './executeLogic'
|
||||||
import { getNextGroup } from './getNextGroup'
|
import { getNextGroup } from './getNextGroup'
|
||||||
import { executeIntegration } from './executeIntegration'
|
import { executeIntegration } from './executeIntegration'
|
||||||
import { computePaymentInputRuntimeOptions } from '@/features/blocks/inputs/payment/api'
|
import { injectVariableValuesInButtonsInputBlock } from '@/features/blocks/inputs/buttons/injectVariableValuesInButtonsInputBlock'
|
||||||
import { injectVariableValuesInButtonsInputBlock } from '@/features/blocks/inputs/buttons/api/utils/injectVariableValuesInButtonsInputBlock'
|
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||||
|
import { computePaymentInputRuntimeOptions } from '@/features/blocks/inputs/payment/computePaymentInputRuntimeOptions'
|
||||||
|
|
||||||
export const executeGroup =
|
export const executeGroup =
|
||||||
(
|
(
|
||||||
@ -137,7 +137,7 @@ const parseBubbleBlock =
|
|||||||
(block: BubbleBlock): ChatReply['messages'][0] => {
|
(block: BubbleBlock): ChatReply['messages'][0] => {
|
||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
case BubbleBlockType.EMBED: {
|
case BubbleBlockType.EMBED: {
|
||||||
const message = deepParseVariable(variables)(block)
|
const message = deepParseVariables(variables)(block)
|
||||||
return {
|
return {
|
||||||
...message,
|
...message,
|
||||||
content: {
|
content: {
|
||||||
@ -150,7 +150,7 @@ const parseBubbleBlock =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return deepParseVariable(variables)(block)
|
return deepParseVariables(variables)(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ const injectVariablesValueInBlock =
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return deepParseVariable(state.typebot.variables)({
|
return deepParseVariables(state.typebot.variables)({
|
||||||
...block,
|
...block,
|
||||||
runtimeOptions: await computeRuntimeOptions(state)(block),
|
runtimeOptions: await computeRuntimeOptions(state)(block),
|
||||||
prefilledValue: getPrefilledInputValue(state.typebot.variables)(
|
prefilledValue: getPrefilledInputValue(state.typebot.variables)(
|
@ -1,15 +1,15 @@
|
|||||||
import { executeChatwootBlock } from '@/features/blocks/integrations/chatwoot/api'
|
|
||||||
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/api'
|
|
||||||
import { executeGoogleSheetBlock } from '@/features/blocks/integrations/googleSheets/api'
|
|
||||||
import { executeOpenAIBlock } from '@/features/blocks/integrations/openai/executeOpenAIBlock'
|
import { executeOpenAIBlock } from '@/features/blocks/integrations/openai/executeOpenAIBlock'
|
||||||
import { executeSendEmailBlock } from '@/features/blocks/integrations/sendEmail/api'
|
import { executeSendEmailBlock } from '@/features/blocks/integrations/sendEmail/executeSendEmailBlock'
|
||||||
import { executeWebhookBlock } from '@/features/blocks/integrations/webhook/api'
|
import { executeWebhookBlock } from '@/features/blocks/integrations/webhook/executeWebhookBlock'
|
||||||
|
import { executeChatwootBlock } from '@/features/blocks/integrations/chatwoot/executeChatwootBlock'
|
||||||
|
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/executeGoogleAnalyticsBlock'
|
||||||
|
import { executeGoogleSheetBlock } from '@/features/blocks/integrations/googleSheets/executeGoogleSheetBlock'
|
||||||
import {
|
import {
|
||||||
IntegrationBlock,
|
IntegrationBlock,
|
||||||
IntegrationBlockType,
|
IntegrationBlockType,
|
||||||
SessionState,
|
SessionState,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { ExecuteIntegrationResponse } from '../../types'
|
import { ExecuteIntegrationResponse } from '../types'
|
||||||
|
|
||||||
export const executeIntegration =
|
export const executeIntegration =
|
||||||
(state: SessionState, lastBubbleBlockId?: string) =>
|
(state: SessionState, lastBubbleBlockId?: string) =>
|
@ -1,12 +1,12 @@
|
|||||||
import { executeCondition } from '@/features/blocks/logic/condition/api'
|
import { executeWait } from '@/features/blocks/logic/wait/executeWait'
|
||||||
import { executeRedirect } from '@/features/blocks/logic/redirect/api'
|
|
||||||
import { executeSetVariable } from '@/features/blocks/logic/setVariable/api'
|
|
||||||
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink/api'
|
|
||||||
import { executeWait } from '@/features/blocks/logic/wait/api/utils/executeWait'
|
|
||||||
import { LogicBlock, LogicBlockType, SessionState } from '@typebot.io/schemas'
|
import { LogicBlock, LogicBlockType, SessionState } from '@typebot.io/schemas'
|
||||||
import { ExecuteLogicResponse } from '../../types'
|
import { ExecuteLogicResponse } from '../types'
|
||||||
import { executeScript } from '@/features/blocks/logic/script/executeScript'
|
import { executeScript } from '@/features/blocks/logic/script/executeScript'
|
||||||
import { executeJumpBlock } from '@/features/blocks/logic/jump/executeJumpBlock'
|
import { executeJumpBlock } from '@/features/blocks/logic/jump/executeJumpBlock'
|
||||||
|
import { executeRedirect } from '@/features/blocks/logic/redirect/executeRedirect'
|
||||||
|
import { executeCondition } from '@/features/blocks/logic/condition/executeCondition'
|
||||||
|
import { executeSetVariable } from '@/features/blocks/logic/setVariable/executeSetVariable'
|
||||||
|
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink/executeTypebotLink'
|
||||||
|
|
||||||
export const executeLogic =
|
export const executeLogic =
|
||||||
(state: SessionState, lastBubbleBlockId?: string) =>
|
(state: SessionState, lastBubbleBlockId?: string) =>
|
@ -1 +0,0 @@
|
|||||||
export * from './types'
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './saveErrorLog'
|
|
||||||
export * from './saveSuccessLog'
|
|
@ -1,4 +1,4 @@
|
|||||||
import { saveLog } from './utils'
|
import { saveLog } from './saveLog'
|
||||||
|
|
||||||
export const saveErrorLog = ({
|
export const saveErrorLog = ({
|
||||||
resultId,
|
resultId,
|
@ -1,4 +1,4 @@
|
|||||||
import { saveLog } from './utils'
|
import { saveLog } from './saveLog'
|
||||||
|
|
||||||
export const saveSuccessLog = ({
|
export const saveSuccessLog = ({
|
||||||
resultId,
|
resultId,
|
@ -1 +0,0 @@
|
|||||||
export { createResultQuery, updateResultQuery } from './queries'
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './createResultQuery'
|
|
||||||
export * from './updateResultQuery'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './checkChatsUsage'
|
|
28
apps/viewer/src/features/variables/deepParseVariable.ts
Normal file
28
apps/viewer/src/features/variables/deepParseVariable.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Variable } from '@typebot.io/schemas'
|
||||||
|
import { parseVariables } from './parseVariables'
|
||||||
|
|
||||||
|
export const deepParseVariables =
|
||||||
|
(variables: Variable[]) =>
|
||||||
|
<T extends Record<string, unknown>>(object: T): T =>
|
||||||
|
Object.keys(object).reduce<T>((newObj, key) => {
|
||||||
|
const currentValue = object[key]
|
||||||
|
|
||||||
|
if (typeof currentValue === 'string')
|
||||||
|
return { ...newObj, [key]: parseVariables(variables)(currentValue) }
|
||||||
|
|
||||||
|
if (currentValue instanceof Object && currentValue.constructor === Object)
|
||||||
|
return {
|
||||||
|
...newObj,
|
||||||
|
[key]: deepParseVariables(variables)(
|
||||||
|
currentValue as Record<string, unknown>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue instanceof Array)
|
||||||
|
return {
|
||||||
|
...newObj,
|
||||||
|
[key]: currentValue.map(deepParseVariables(variables)),
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...newObj, [key]: currentValue }
|
||||||
|
}, {} as T)
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Variable } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const extractVariablesFromText =
|
||||||
|
(variables: Variable[]) =>
|
||||||
|
(text: string): Variable[] => {
|
||||||
|
const matches = [...text.matchAll(/\{\{(.*?)\}\}/g)]
|
||||||
|
return matches.reduce<Variable[]>((acc, match) => {
|
||||||
|
const variableName = match[1]
|
||||||
|
const variable = variables.find(
|
||||||
|
(variable) => variable.name === variableName
|
||||||
|
)
|
||||||
|
if (!variable) return acc
|
||||||
|
return [...acc, variable]
|
||||||
|
}, [])
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { Variable } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const findUniqueVariableValue =
|
||||||
|
(variables: Variable[]) =>
|
||||||
|
(value: string | undefined): string | string[] | null => {
|
||||||
|
if (!value || !value.startsWith('{{') || !value.endsWith('}}')) return null
|
||||||
|
const variableName = value.slice(2, -2)
|
||||||
|
const variable = variables.find(
|
||||||
|
(variable) => variable.name === variableName
|
||||||
|
)
|
||||||
|
return variable?.value ?? null
|
||||||
|
}
|
1
apps/viewer/src/features/variables/hasVariable.ts
Normal file
1
apps/viewer/src/features/variables/hasVariable.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const hasVariable = (str: string): boolean => /\{\{(.*?)\}\}/g.test(str)
|
@ -1 +0,0 @@
|
|||||||
export * from './utils'
|
|
@ -0,0 +1,17 @@
|
|||||||
|
import { Result, Variable } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const injectVariablesFromExistingResult = (
|
||||||
|
variables: Variable[],
|
||||||
|
resultVariables: Result['variables']
|
||||||
|
): Variable[] =>
|
||||||
|
variables.map((variable) => {
|
||||||
|
const resultVariable = resultVariables.find(
|
||||||
|
(resultVariable) =>
|
||||||
|
resultVariable.name === variable.name && !variable.value
|
||||||
|
)
|
||||||
|
if (!resultVariable) return variable
|
||||||
|
return {
|
||||||
|
...variable,
|
||||||
|
value: resultVariable.value,
|
||||||
|
}
|
||||||
|
})
|
20
apps/viewer/src/features/variables/parseGuessedValueType.ts
Normal file
20
apps/viewer/src/features/variables/parseGuessedValueType.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Variable } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const parseGuessedValueType = (
|
||||||
|
value: Variable['value']
|
||||||
|
): string | string[] | boolean | number | null | undefined => {
|
||||||
|
if (value === null) return null
|
||||||
|
if (value === undefined) return undefined
|
||||||
|
if (typeof value !== 'string') return value
|
||||||
|
const isNumberStartingWithZero =
|
||||||
|
value.startsWith('0') && !value.startsWith('0.') && value.length > 1
|
||||||
|
if (typeof value === 'string' && isNumberStartingWithZero) return value
|
||||||
|
if (typeof value === 'number') return value
|
||||||
|
if (value === 'true') return true
|
||||||
|
if (value === 'false') return false
|
||||||
|
if (value === 'null') return null
|
||||||
|
if (value === 'undefined') return undefined
|
||||||
|
// isNaN works with strings
|
||||||
|
if (isNaN(value as unknown as number)) return value
|
||||||
|
return Number(value)
|
||||||
|
}
|
40
apps/viewer/src/features/variables/parseVariables.ts
Normal file
40
apps/viewer/src/features/variables/parseVariables.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { isDefined } from '@typebot.io/lib'
|
||||||
|
import { Variable, VariableWithValue } from '@typebot.io/schemas'
|
||||||
|
import { safeStringify } from './safeStringify'
|
||||||
|
|
||||||
|
export const parseVariables =
|
||||||
|
(
|
||||||
|
variables: Variable[],
|
||||||
|
options: { fieldToParse?: 'value' | 'id'; escapeForJson?: boolean } = {
|
||||||
|
fieldToParse: 'value',
|
||||||
|
escapeForJson: false,
|
||||||
|
}
|
||||||
|
) =>
|
||||||
|
(text: string | undefined): string => {
|
||||||
|
if (!text || text === '') return ''
|
||||||
|
return text.replace(/\{\{(.*?)\}\}/g, (_, fullVariableString) => {
|
||||||
|
const matchedVarName = fullVariableString.replace(/{{|}}/g, '')
|
||||||
|
const variable = variables.find((variable) => {
|
||||||
|
return (
|
||||||
|
matchedVarName === variable.name &&
|
||||||
|
(options.fieldToParse === 'id' || isDefined(variable.value))
|
||||||
|
)
|
||||||
|
}) as VariableWithValue | undefined
|
||||||
|
if (!variable) return ''
|
||||||
|
if (options.fieldToParse === 'id') return variable.id
|
||||||
|
const { value } = variable
|
||||||
|
if (options.escapeForJson)
|
||||||
|
return jsonParse(
|
||||||
|
typeof value !== 'string' ? JSON.stringify(value) : value
|
||||||
|
)
|
||||||
|
const parsedValue = safeStringify(value)
|
||||||
|
if (!parsedValue) return ''
|
||||||
|
return parsedValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonParse = (str: string) =>
|
||||||
|
str
|
||||||
|
.replace(/\n/g, `\\n`)
|
||||||
|
.replace(/"/g, `\\"`)
|
||||||
|
.replace(/\\[^n"]/g, `\\\\ `)
|
15
apps/viewer/src/features/variables/prefillVariables.ts
Normal file
15
apps/viewer/src/features/variables/prefillVariables.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { StartParams, Variable } from '@typebot.io/schemas'
|
||||||
|
import { safeStringify } from './safeStringify'
|
||||||
|
|
||||||
|
export const prefillVariables = (
|
||||||
|
variables: Variable[],
|
||||||
|
prefilledVariables: NonNullable<StartParams['prefilledVariables']>
|
||||||
|
): Variable[] =>
|
||||||
|
variables.map((variable) => {
|
||||||
|
const prefilledVariable = prefilledVariables[variable.name]
|
||||||
|
if (!prefilledVariable) return variable
|
||||||
|
return {
|
||||||
|
...variable,
|
||||||
|
value: safeStringify(prefilledVariable),
|
||||||
|
}
|
||||||
|
})
|
12
apps/viewer/src/features/variables/safeStringify.ts
Normal file
12
apps/viewer/src/features/variables/safeStringify.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
|
||||||
|
export const safeStringify = (val: unknown): string | null => {
|
||||||
|
if (isNotDefined(val)) return null
|
||||||
|
if (typeof val === 'string') return val
|
||||||
|
try {
|
||||||
|
return JSON.stringify(val)
|
||||||
|
} catch {
|
||||||
|
console.warn('Failed to safely stringify variable value', val)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
77
apps/viewer/src/features/variables/updateVariables.ts
Normal file
77
apps/viewer/src/features/variables/updateVariables.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import prisma from '@/lib/prisma'
|
||||||
|
import { isDefined } from '@typebot.io/lib'
|
||||||
|
import {
|
||||||
|
SessionState,
|
||||||
|
VariableWithUnknowValue,
|
||||||
|
VariableWithValue,
|
||||||
|
Variable,
|
||||||
|
} from '@typebot.io/schemas'
|
||||||
|
import { safeStringify } from './safeStringify'
|
||||||
|
|
||||||
|
export const updateVariables =
|
||||||
|
(state: SessionState) =>
|
||||||
|
async (newVariables: VariableWithUnknowValue[]): Promise<SessionState> => ({
|
||||||
|
...state,
|
||||||
|
typebot: {
|
||||||
|
...state.typebot,
|
||||||
|
variables: updateTypebotVariables(state)(newVariables),
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
...state.result,
|
||||||
|
variables: await updateResultVariables(state)(newVariables),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateResultVariables =
|
||||||
|
({ result }: Pick<SessionState, 'result' | 'typebot'>) =>
|
||||||
|
async (
|
||||||
|
newVariables: VariableWithUnknowValue[]
|
||||||
|
): Promise<VariableWithValue[]> => {
|
||||||
|
const serializedNewVariables = newVariables.map((variable) => ({
|
||||||
|
...variable,
|
||||||
|
value: Array.isArray(variable.value)
|
||||||
|
? variable.value.map(safeStringify).filter(isDefined)
|
||||||
|
: safeStringify(variable.value),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const updatedVariables = [
|
||||||
|
...result.variables.filter((existingVariable) =>
|
||||||
|
serializedNewVariables.every(
|
||||||
|
(newVariable) => existingVariable.id !== newVariable.id
|
||||||
|
)
|
||||||
|
),
|
||||||
|
...serializedNewVariables,
|
||||||
|
].filter((variable) => isDefined(variable.value)) as VariableWithValue[]
|
||||||
|
|
||||||
|
if (result.id)
|
||||||
|
await prisma.result.update({
|
||||||
|
where: {
|
||||||
|
id: result.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
variables: updatedVariables,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return updatedVariables
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTypebotVariables =
|
||||||
|
({ typebot }: Pick<SessionState, 'result' | 'typebot'>) =>
|
||||||
|
(newVariables: VariableWithUnknowValue[]): Variable[] => {
|
||||||
|
const serializedNewVariables = newVariables.map((variable) => ({
|
||||||
|
...variable,
|
||||||
|
value: Array.isArray(variable.value)
|
||||||
|
? variable.value.map(safeStringify).filter(isDefined)
|
||||||
|
: safeStringify(variable.value),
|
||||||
|
}))
|
||||||
|
|
||||||
|
return [
|
||||||
|
...typebot.variables.filter((existingVariable) =>
|
||||||
|
serializedNewVariables.every(
|
||||||
|
(newVariable) => existingVariable.id !== newVariable.id
|
||||||
|
)
|
||||||
|
),
|
||||||
|
...serializedNewVariables,
|
||||||
|
]
|
||||||
|
}
|
@ -1,229 +0,0 @@
|
|||||||
import prisma from '@/lib/prisma'
|
|
||||||
import {
|
|
||||||
Result,
|
|
||||||
SessionState,
|
|
||||||
StartParams,
|
|
||||||
Typebot,
|
|
||||||
Variable,
|
|
||||||
VariableWithUnknowValue,
|
|
||||||
VariableWithValue,
|
|
||||||
} from '@typebot.io/schemas'
|
|
||||||
import { isDefined, isNotDefined } from '@typebot.io/lib'
|
|
||||||
|
|
||||||
export const stringContainsVariable = (str: string): boolean =>
|
|
||||||
/\{\{(.*?)\}\}/g.test(str)
|
|
||||||
|
|
||||||
export const parseVariables =
|
|
||||||
(
|
|
||||||
variables: Variable[],
|
|
||||||
options: { fieldToParse?: 'value' | 'id'; escapeForJson?: boolean } = {
|
|
||||||
fieldToParse: 'value',
|
|
||||||
escapeForJson: false,
|
|
||||||
}
|
|
||||||
) =>
|
|
||||||
(text: string | undefined): string => {
|
|
||||||
if (!text || text === '') return ''
|
|
||||||
return text.replace(/\{\{(.*?)\}\}/g, (_, fullVariableString) => {
|
|
||||||
const matchedVarName = fullVariableString.replace(/{{|}}/g, '')
|
|
||||||
const variable = variables.find((variable) => {
|
|
||||||
return (
|
|
||||||
matchedVarName === variable.name &&
|
|
||||||
(options.fieldToParse === 'id' || isDefined(variable.value))
|
|
||||||
)
|
|
||||||
}) as VariableWithValue | undefined
|
|
||||||
if (!variable) return ''
|
|
||||||
if (options.fieldToParse === 'id') return variable.id
|
|
||||||
const { value } = variable
|
|
||||||
if (options.escapeForJson)
|
|
||||||
return jsonParse(
|
|
||||||
typeof value !== 'string' ? JSON.stringify(value) : value
|
|
||||||
)
|
|
||||||
const parsedValue = safeStringify(value)
|
|
||||||
if (!parsedValue) return ''
|
|
||||||
return parsedValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const extractVariablesFromText =
|
|
||||||
(variables: Variable[]) =>
|
|
||||||
(text: string): Variable[] => {
|
|
||||||
const matches = [...text.matchAll(/\{\{(.*?)\}\}/g)]
|
|
||||||
return matches.reduce<Variable[]>((acc, match) => {
|
|
||||||
const variableName = match[1]
|
|
||||||
const variable = variables.find(
|
|
||||||
(variable) => variable.name === variableName
|
|
||||||
)
|
|
||||||
if (!variable) return acc
|
|
||||||
return [...acc, variable]
|
|
||||||
}, [])
|
|
||||||
}
|
|
||||||
|
|
||||||
export const safeStringify = (val: unknown): string | null => {
|
|
||||||
if (isNotDefined(val)) return null
|
|
||||||
if (typeof val === 'string') return val
|
|
||||||
try {
|
|
||||||
return JSON.stringify(val)
|
|
||||||
} catch {
|
|
||||||
console.warn('Failed to safely stringify variable value', val)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const parseCorrectValueType = (
|
|
||||||
value: Variable['value']
|
|
||||||
): string | string[] | boolean | number | null | undefined => {
|
|
||||||
if (value === null) return null
|
|
||||||
if (value === undefined) return undefined
|
|
||||||
if (typeof value !== 'string') return value
|
|
||||||
const isNumberStartingWithZero =
|
|
||||||
value.startsWith('0') && !value.startsWith('0.') && value.length > 1
|
|
||||||
if (typeof value === 'string' && isNumberStartingWithZero) return value
|
|
||||||
if (typeof value === 'number') return value
|
|
||||||
if (value === 'true') return true
|
|
||||||
if (value === 'false') return false
|
|
||||||
if (value === 'null') return null
|
|
||||||
if (value === 'undefined') return undefined
|
|
||||||
// isNaN works with strings
|
|
||||||
if (isNaN(value as unknown as number)) return value
|
|
||||||
return Number(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const jsonParse = (str: string) =>
|
|
||||||
str
|
|
||||||
.replace(/\n/g, `\\n`)
|
|
||||||
.replace(/"/g, `\\"`)
|
|
||||||
.replace(/\\[^n"]/g, `\\\\ `)
|
|
||||||
|
|
||||||
export const deepParseVariable =
|
|
||||||
(variables: Variable[]) =>
|
|
||||||
<T extends Record<string, unknown>>(object: T): T =>
|
|
||||||
Object.keys(object).reduce<T>((newObj, key) => {
|
|
||||||
const currentValue = object[key]
|
|
||||||
|
|
||||||
if (typeof currentValue === 'string')
|
|
||||||
return { ...newObj, [key]: parseVariables(variables)(currentValue) }
|
|
||||||
|
|
||||||
if (currentValue instanceof Object && currentValue.constructor === Object)
|
|
||||||
return {
|
|
||||||
...newObj,
|
|
||||||
[key]: deepParseVariable(variables)(
|
|
||||||
currentValue as Record<string, unknown>
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentValue instanceof Array)
|
|
||||||
return {
|
|
||||||
...newObj,
|
|
||||||
[key]: currentValue.map(deepParseVariable(variables)),
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...newObj, [key]: currentValue }
|
|
||||||
}, {} as T)
|
|
||||||
|
|
||||||
export const prefillVariables = (
|
|
||||||
variables: Typebot['variables'],
|
|
||||||
prefilledVariables: NonNullable<StartParams['prefilledVariables']>
|
|
||||||
): Variable[] =>
|
|
||||||
variables.map((variable) => {
|
|
||||||
const prefilledVariable = prefilledVariables[variable.name]
|
|
||||||
if (!prefilledVariable) return variable
|
|
||||||
return {
|
|
||||||
...variable,
|
|
||||||
value: safeStringify(prefilledVariable),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export const injectVariablesFromExistingResult = (
|
|
||||||
variables: Typebot['variables'],
|
|
||||||
resultVariables: Result['variables']
|
|
||||||
): Variable[] =>
|
|
||||||
variables.map((variable) => {
|
|
||||||
const resultVariable = resultVariables.find(
|
|
||||||
(resultVariable) =>
|
|
||||||
resultVariable.name === variable.name && !variable.value
|
|
||||||
)
|
|
||||||
if (!resultVariable) return variable
|
|
||||||
return {
|
|
||||||
...variable,
|
|
||||||
value: resultVariable.value,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export const updateVariables =
|
|
||||||
(state: SessionState) =>
|
|
||||||
async (newVariables: VariableWithUnknowValue[]): Promise<SessionState> => ({
|
|
||||||
...state,
|
|
||||||
typebot: {
|
|
||||||
...state.typebot,
|
|
||||||
variables: updateTypebotVariables(state)(newVariables),
|
|
||||||
},
|
|
||||||
result: {
|
|
||||||
...state.result,
|
|
||||||
variables: await updateResultVariables(state)(newVariables),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateResultVariables =
|
|
||||||
({ result }: Pick<SessionState, 'result' | 'typebot'>) =>
|
|
||||||
async (
|
|
||||||
newVariables: VariableWithUnknowValue[]
|
|
||||||
): Promise<VariableWithValue[]> => {
|
|
||||||
const serializedNewVariables = newVariables.map((variable) => ({
|
|
||||||
...variable,
|
|
||||||
value: Array.isArray(variable.value)
|
|
||||||
? variable.value.map(safeStringify).filter(isDefined)
|
|
||||||
: safeStringify(variable.value),
|
|
||||||
}))
|
|
||||||
|
|
||||||
const updatedVariables = [
|
|
||||||
...result.variables.filter((existingVariable) =>
|
|
||||||
serializedNewVariables.every(
|
|
||||||
(newVariable) => existingVariable.id !== newVariable.id
|
|
||||||
)
|
|
||||||
),
|
|
||||||
...serializedNewVariables,
|
|
||||||
].filter((variable) => isDefined(variable.value)) as VariableWithValue[]
|
|
||||||
|
|
||||||
if (result.id)
|
|
||||||
await prisma.result.update({
|
|
||||||
where: {
|
|
||||||
id: result.id,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
variables: updatedVariables,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return updatedVariables
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateTypebotVariables =
|
|
||||||
({ typebot }: Pick<SessionState, 'result' | 'typebot'>) =>
|
|
||||||
(newVariables: VariableWithUnknowValue[]): Variable[] => {
|
|
||||||
const serializedNewVariables = newVariables.map((variable) => ({
|
|
||||||
...variable,
|
|
||||||
value: Array.isArray(variable.value)
|
|
||||||
? variable.value.map(safeStringify).filter(isDefined)
|
|
||||||
: safeStringify(variable.value),
|
|
||||||
}))
|
|
||||||
|
|
||||||
return [
|
|
||||||
...typebot.variables.filter((existingVariable) =>
|
|
||||||
serializedNewVariables.every(
|
|
||||||
(newVariable) => existingVariable.id !== newVariable.id
|
|
||||||
)
|
|
||||||
),
|
|
||||||
...serializedNewVariables,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const findUniqueVariableValue =
|
|
||||||
(variables: Variable[]) =>
|
|
||||||
(value: string | undefined): string | string[] | null => {
|
|
||||||
if (!value || !value.startsWith('{{') || !value.endsWith('}}')) return null
|
|
||||||
const variableName = value.slice(2, -2)
|
|
||||||
const variable = variables.find(
|
|
||||||
(variable) => variable.name === variableName
|
|
||||||
)
|
|
||||||
return variable?.value ?? null
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { chatRouter } from '@/features/chat/api'
|
import { chatRouter } from '@/features/chat/api/router'
|
||||||
import { router } from '../../trpc'
|
import { router } from '../../trpc'
|
||||||
|
|
||||||
export const appRouter = router({
|
export const appRouter = router({
|
@ -17,7 +17,8 @@ import {
|
|||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import Cors from 'cors'
|
import Cors from 'cors'
|
||||||
import { getAuthenticatedGoogleClient } from '@/lib/google-sheets'
|
import { getAuthenticatedGoogleClient } from '@/lib/google-sheets'
|
||||||
import { saveErrorLog, saveSuccessLog } from '@/features/logs/api'
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
|
||||||
const cors = initMiddleware(Cors())
|
const cors = initMiddleware(Cors())
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
Variable,
|
Variable,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { parseVariables } from '@/features/variables'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
|
|
||||||
const cors = initMiddleware(Cors())
|
const cors = initMiddleware(Cors())
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { authenticateUser } from '@/features/auth/api'
|
import { authenticateUser } from '@/helpers/authenticateUser'
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
import { methodNotAllowed } from '@typebot.io/lib/api'
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user