From 1b2a3b7363aeafeac05465357bab06190db76f9d Mon Sep 17 00:00:00 2001 From: Alonso Vega Date: Thu, 19 Dec 2024 10:14:26 -0600 Subject: [PATCH] fix(client): check compatibility with check function --- presto-client/src/client.ts | 25 ++++++++---------------- presto-client/src/utils.ts | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 presto-client/src/utils.ts diff --git a/presto-client/src/client.ts b/presto-client/src/client.ts index d5f65fe..51b4672 100644 --- a/presto-client/src/client.ts +++ b/presto-client/src/client.ts @@ -8,20 +8,7 @@ import { QueryInfo, Table, } from './types' - -function digitsToBigInt(_: string, value: unknown, { source }: { source: string }) { - // Ignore non-numbers - if (typeof value !== 'number') return value - - // If not an integer, use the value - // TODO: Check if Presto can return floats that could also lose precision - if (!Number.isInteger(value)) return value - - // If number is a safe integer, we can use it - if (Number.isSafeInteger(value)) return value - - return BigInt(source) -} +import { parseWithBigInts, isJsonParseContextAvailable } from './utils' export class PrestoClient { private baseUrl: string @@ -351,9 +338,13 @@ export class PrestoClient { private async prestoConversionToJSON({ response }: { response: Response }): Promise { const text = await response.text() - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore JSON.parse with a 3 argument reviver is a stage 3 proposal with some support, allow it here. - return JSON.parse(text, digitsToBigInt) + if (isJsonParseContextAvailable()) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore JSON.parse with a 3 argument reviver is a stage 3 proposal with some support, allow it here. + return JSON.parse(text, parseWithBigInts) + } else { + return JSON.parse(text) + } } } diff --git a/presto-client/src/utils.ts b/presto-client/src/utils.ts new file mode 100644 index 0000000..082c474 --- /dev/null +++ b/presto-client/src/utils.ts @@ -0,0 +1,39 @@ +/** + * Parses a JSON including bigger numbers into BigInts + * @param _ Key + * @param value Parsed value + * @param context Context with source text + * @returns Parsed object with BigInts where required + */ +export function parseWithBigInts(_: string, value: unknown, { source }: { source: string }) { + // Ignore non-numbers + if (typeof value !== 'number') return value + + // If not an integer, use the value + // TODO: Check if Presto can return floats that could also lose precision + if (!Number.isInteger(value)) return value + + // If number is a safe integer, we can use it + if (Number.isSafeInteger(value)) return value + + return BigInt(source) +} + +/** + * Checks if JSON.parse reviver callback has a context parameter + * See also: + * - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#browser_compatibility + * - https://github.com/tc39/proposal-json-parse-with-source + * + * This implementation is based on suggestion here: + * - https://github.com/tc39/proposal-json-parse-with-source/issues/40 + */ +export function isJsonParseContextAvailable() { + let contextAvailable + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + JSON.parse('"x"', function (key, value, x) { + contextAvailable = typeof x !== 'undefined' + }) + return contextAvailable +}