diff --git a/packages/bot-engine/blocks/integrations/webhook/executeWebhookBlock.ts b/packages/bot-engine/blocks/integrations/webhook/executeWebhookBlock.ts index c783fa2e1..d691c33d3 100644 --- a/packages/bot-engine/blocks/integrations/webhook/executeWebhookBlock.ts +++ b/packages/bot-engine/blocks/integrations/webhook/executeWebhookBlock.ts @@ -28,6 +28,7 @@ import { } from '@typebot.io/schemas/features/blocks/integrations/webhook/constants' import { env } from '@typebot.io/env' import { parseAnswers } from '@typebot.io/results/parseAnswers' +import { JSONParse } from '@typebot.io/lib/JSONParse' type ParsedWebhook = ExecutableHttpRequest & { basicAuth: { username?: string; password?: string } @@ -326,7 +327,7 @@ export const convertKeyValueTableToObject = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any const safeJsonParse = (json: unknown): { data: any; isJson: boolean } => { try { - return { data: JSON.parse(json as string), isJson: true } + return { data: JSONParse(json as string), isJson: true } } catch (err) { return { data: json, isJson: false } } diff --git a/packages/lib/JSONParse.ts b/packages/lib/JSONParse.ts new file mode 100644 index 000000000..f28c2754e --- /dev/null +++ b/packages/lib/JSONParse.ts @@ -0,0 +1,28 @@ +// Taken from https://github.com/Ivan-Korolenko/json-with-bigint/blob/main/json-with-bigint.js + +/* + Function to parse JSON + If JSON has values presented in a lib's custom format (strings with digits and "n" character at the end), we just parse them to BigInt values (for backward compatibility with previous versions of the lib) + If JSON has values greater than Number.MAX_SAFE_INTEGER, we convert those values to our custom format, then parse them to BigInt values. + Other types of values are not affected and parsed as native JSON.parse() would parse them. + + Big numbers are found and marked using RegEx with these conditions: + - Before the match there is ": OR ":[ OR ":[anyNumberOf(anyCharacters) with no \ before them + - The match itself has more than 16 digits OR (16 digits and any digit of the number is greater than that of the Number.MAX_SAFE_INTEGER). And it may have a - sign at the start + - After the match there is , OR } without " after it OR ] without " after it +*/ +export const JSONParse = (json: string) => { + const numbersBiggerThanMaxInt = + /(?<=[^\\]":[\[]?|[^\\]":\[.*)(-?\d{17,}|-?(?:[9](?:[1-9]07199254740991|0[1-9]7199254740991|00[8-9]199254740991|007[2-9]99254740991|007199[3-9]54740991|0071992[6-9]4740991|00719925[5-9]740991|007199254[8-9]40991|0071992547[5-9]0991|00719925474[1-9]991|00719925474099[2-9])))(?=,|\}[^"]|\][^"])/g + const serializedData = json.replace(numbersBiggerThanMaxInt, `"$1n"`) + + return JSON.parse(serializedData, (_, value) => { + const isCustomFormatBigInt = + typeof value === 'string' && Boolean(value.match(/^-?\d+n$/)) + + if (isCustomFormatBigInt) + return BigInt(value.substring(0, value.length - 1)) + + return value + }) +}