2
0

🐛 (webhook) Fix variable list parsing in custom body

Closes #687
This commit is contained in:
Baptiste Arnaud
2023-08-18 15:57:52 +02:00
parent a4f7f8fae7
commit ed77f5d124
8 changed files with 36 additions and 25 deletions

View File

@ -186,9 +186,7 @@ export const WebhookAdvancedConfigForm = ({
</AccordionButton> </AccordionButton>
<AccordionPanel pt="4"> <AccordionPanel pt="4">
<TableList<VariableForTest> <TableList<VariableForTest>
initialItems={ initialItems={options?.variablesForTest ?? []}
options?.variablesForTest ?? { byId: {}, allIds: [] }
}
onItemsChange={updateVariablesForTest} onItemsChange={updateVariablesForTest}
Item={VariableForTestInputs} Item={VariableForTestInputs}
addLabel="Add an entry" addLabel="Add an entry"

View File

@ -1,3 +1,5 @@
import { safeStringify } from '@typebot.io/lib/safeStringify'
import { isDefined } from '@typebot.io/lib/utils'
import { Variable, VariableForTest } from '@typebot.io/schemas' import { Variable, VariableForTest } from '@typebot.io/schemas'
export const convertVariablesForTestToVariables = ( export const convertVariablesForTestToVariables = (
@ -13,7 +15,19 @@ export const convertVariablesForTestToVariables = (
const variable = variables.find( const variable = variables.find(
(v) => v.id === variableForTest.variableId (v) => v.id === variableForTest.variableId
) as Variable ) as Variable
return { ...variable, value: variableForTest.value } return { ...variable, value: parseVariableValue(variableForTest.value) }
}, {}), }, {}),
] ]
} }
const parseVariableValue = (value: string | undefined): string | string[] => {
if (!value) return ''
try {
const parsedValue = JSON.parse(value)
if (Array.isArray(parsedValue))
return parsedValue.map(safeStringify).filter(isDefined)
return safeStringify(parsedValue) ?? value
} catch (error) {
return value
}
}

View File

@ -55,10 +55,10 @@ export const continueBotFlow =
const existingVariable = state.typebot.variables.find( const existingVariable = state.typebot.variables.find(
byId(block.options.variableId) byId(block.options.variableId)
) )
if (existingVariable) { if (existingVariable && reply) {
const newVariable = { const newVariable = {
...existingVariable, ...existingVariable,
value: reply, value: safeJsonParse(reply),
} }
newSessionState = updateVariables(state)([newVariable]) newSessionState = updateVariables(state)([newVariable])
} }
@ -318,3 +318,11 @@ export const isReplyValid = (inputValue: string, block: Block): boolean => {
export const canSkip = (inputType: InputBlockType) => export const canSkip = (inputType: InputBlockType) =>
inputType === InputBlockType.FILE inputType === InputBlockType.FILE
export const safeJsonParse = (value: string): unknown => {
try {
return JSON.parse(value)
} catch {
return value
}
}

View File

@ -1,6 +1,6 @@
import { isDefined } from '@typebot.io/lib' import { isDefined } from '@typebot.io/lib'
import { Variable, VariableWithValue } from '@typebot.io/schemas' import { Variable, VariableWithValue } from '@typebot.io/schemas'
import { safeStringify } from './safeStringify' import { safeStringify } from '@typebot.io/lib/safeStringify'
export type ParseVariablesOptions = { export type ParseVariablesOptions = {
fieldToParse?: 'value' | 'id' fieldToParse?: 'value' | 'id'
@ -42,7 +42,9 @@ export const parseVariables =
if (options.escapeForJson) if (options.escapeForJson)
return ( return (
dollarSign + dollarSign +
jsonParse(typeof value !== 'string' ? JSON.stringify(value) : value) (typeof value === 'string'
? jsonParse(value)
: JSON.stringify(value))
) )
const parsedValue = const parsedValue =
dollarSign + dollarSign +

View File

@ -1,5 +1,5 @@
import { StartParams, Variable } from '@typebot.io/schemas' import { StartParams, Variable } from '@typebot.io/schemas'
import { safeStringify } from './safeStringify' import { safeStringify } from '@typebot.io/lib/safeStringify'
export const prefillVariables = ( export const prefillVariables = (
variables: Variable[], variables: Variable[],

View File

@ -5,7 +5,7 @@ import {
VariableWithValue, VariableWithValue,
Variable, Variable,
} from '@typebot.io/schemas' } from '@typebot.io/schemas'
import { safeStringify } from './safeStringify' import { safeStringify } from '@typebot.io/lib/safeStringify'
export const updateVariables = export const updateVariables =
(state: SessionState) => (state: SessionState) =>

View File

@ -1,5 +1,5 @@
import { isNotDefined } from '@typebot.io/lib'
import type { ScriptToExecute } from '@typebot.io/schemas' import type { ScriptToExecute } from '@typebot.io/schemas'
import { safeStringify } from '@typebot.io/lib/safeStringify'
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
@ -15,23 +15,12 @@ export const executeSetVariable = async ({
) )
const replyToSend = await func(...args.map((arg) => arg.value)) const replyToSend = await func(...args.map((arg) => arg.value))
return { return {
replyToSend: safeStringify(replyToSend), replyToSend: safeStringify(replyToSend) ?? undefined,
} }
} catch (err) { } catch (err) {
console.error(err) console.error(err)
return { return {
replyToSend: safeStringify(content), replyToSend: safeStringify(content) ?? undefined,
} }
} }
} }
export const safeStringify = (val: unknown): string | undefined => {
if (isNotDefined(val)) return
if (typeof val === 'string') return val
try {
return JSON.stringify(val)
} catch {
console.warn('Failed to safely stringify variable value', val)
return
}
}

View File

@ -1,4 +1,4 @@
import { isNotDefined } from '@typebot.io/lib' import { isNotDefined } from './utils'
export const safeStringify = (val: unknown): string | null => { export const safeStringify = (val: unknown): string | null => {
if (isNotDefined(val)) return null if (isNotDefined(val)) return null