diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 92474fdbf456..1782a251504e 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -184,7 +184,7 @@ "@types/jest": "^26.0.3", "@types/jquery": "^3.5.8", "@types/js-levenshtein": "^1.1.0", - "@types/json-bigint": "^1.0.0", + "@types/json-bigint": "^1.0.1", "@types/react": "^16.9.43", "@types/react-dom": "^16.9.8", "@types/react-gravatar": "^2.6.8", @@ -18200,10 +18200,9 @@ "dev": true }, "node_modules/@types/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-WW+0cfH3ovFN6ROV+p/Xfw36dT6s16hbXBYIG49PYw6+j6e+AkpqYccctgxwyicBmC8CZDBnPhOH94shFhXgHQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.1.tgz", + "integrity": "sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw==" }, "node_modules/@types/json-schema": { "version": "7.0.9", @@ -54794,6 +54793,7 @@ "@types/d3-time-format": "^2.1.0", "@types/enzyme": "^3.10.5", "@types/fetch-mock": "^7.3.3", + "@types/json-bigint": "^1.0.1", "@types/lodash": "^4.14.149", "@types/math-expression-evaluator": "^1.2.1", "@types/node": "^18.0.0", @@ -69195,6 +69195,7 @@ "@types/d3-time-format": "^2.1.0", "@types/enzyme": "^3.10.5", "@types/fetch-mock": "^7.3.3", + "@types/json-bigint": "^1.0.1", "@types/lodash": "^4.14.149", "@types/math-expression-evaluator": "^1.2.1", "@types/node": "^18.0.0", @@ -71074,10 +71075,9 @@ "dev": true }, "@types/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-WW+0cfH3ovFN6ROV+p/Xfw36dT6s16hbXBYIG49PYw6+j6e+AkpqYccctgxwyicBmC8CZDBnPhOH94shFhXgHQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.1.tgz", + "integrity": "sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw==" }, "@types/json-schema": { "version": "7.0.9", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index b6a44c8bb677..5d09c502d214 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -248,7 +248,7 @@ "@types/jest": "^26.0.3", "@types/jquery": "^3.5.8", "@types/js-levenshtein": "^1.1.0", - "@types/json-bigint": "^1.0.0", + "@types/json-bigint": "^1.0.1", "@types/react": "^16.9.43", "@types/react-dom": "^16.9.8", "@types/react-gravatar": "^2.6.8", diff --git a/superset-frontend/packages/superset-ui-core/package.json b/superset-frontend/packages/superset-ui-core/package.json index 1958fe1a49fa..7faa531a67cd 100644 --- a/superset-frontend/packages/superset-ui-core/package.json +++ b/superset-frontend/packages/superset-ui-core/package.json @@ -27,9 +27,9 @@ }, "devDependencies": { "@emotion/styled": "^11.3.0", - "resize-observer-polyfill": "1.5.1", "fetch-mock": "^6.5.2", - "jest-mock-console": "^1.0.0" + "jest-mock-console": "^1.0.0", + "resize-observer-polyfill": "1.5.1" }, "dependencies": { "@babel/runtime": "^7.1.2", @@ -38,14 +38,15 @@ "@types/d3-scale": "^2.1.1", "@types/d3-time": "^3.0.0", "@types/d3-time-format": "^2.1.0", + "@types/enzyme": "^3.10.5", + "@types/fetch-mock": "^7.3.3", + "@types/json-bigint": "^1.0.1", "@types/lodash": "^4.14.149", "@types/math-expression-evaluator": "^1.2.1", "@types/node": "^18.0.0", + "@types/prop-types": "^15.7.2", "@types/rison": "0.0.6", "@types/seedrandom": "^2.4.28", - "@types/fetch-mock": "^7.3.3", - "@types/enzyme": "^3.10.5", - "@types/prop-types": "^15.7.2", "@vx/responsive": "^0.0.199", "csstype": "^2.6.4", "d3-format": "^1.3.2", @@ -72,8 +73,8 @@ "@types/react": "*", "@types/react-loadable": "*", "@types/tinycolor2": "*", - "tinycolor2": "*", "react": "^16.13.1", - "react-loadable": "^5.5.0" + "react-loadable": "^5.5.0", + "tinycolor2": "*" } } diff --git a/superset-frontend/packages/superset-ui-core/src/connection/callApi/parseResponse.ts b/superset-frontend/packages/superset-ui-core/src/connection/callApi/parseResponse.ts index a0b9f149113a..e0e5e0ebbe23 100644 --- a/superset-frontend/packages/superset-ui-core/src/connection/callApi/parseResponse.ts +++ b/superset-frontend/packages/superset-ui-core/src/connection/callApi/parseResponse.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import JSONbig from 'json-bigint'; import { ParseMethod, TextResponse, JsonResponse } from '../types'; @@ -25,7 +26,7 @@ export default async function parseResponse( ) { type ReturnType = T extends 'raw' | null ? Response - : T extends 'json' | undefined + : T extends 'json' | 'json-bigint' | undefined ? JsonResponse : T extends 'text' ? TextResponse @@ -46,6 +47,15 @@ export default async function parseResponse( }; return result as ReturnType; } + if (parseMethod === 'json-bigint') { + const rawData = await response.text(); + const json = JSONbig.parse(rawData); + const result: JsonResponse = { + response, + json, + }; + return result as ReturnType; + } // by default treat this as json if (parseMethod === undefined || parseMethod === 'json') { const json = await response.json(); @@ -56,6 +66,6 @@ export default async function parseResponse( return result as ReturnType; } throw new Error( - `Expected parseResponse=json|text|raw|null, got '${parseMethod}'.`, + `Expected parseResponse=json|json-bigint|text|raw|null, got '${parseMethod}'.`, ); } diff --git a/superset-frontend/packages/superset-ui-core/src/connection/types.ts b/superset-frontend/packages/superset-ui-core/src/connection/types.ts index 80b40da030c2..a63ffd8b68a0 100644 --- a/superset-frontend/packages/superset-ui-core/src/connection/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/connection/types.ts @@ -70,7 +70,13 @@ export type Method = RequestInit['method']; export type Mode = RequestInit['mode']; export type Redirect = RequestInit['redirect']; export type ClientTimeout = number | undefined; -export type ParseMethod = 'json' | 'text' | 'raw' | null | undefined; +export type ParseMethod = + | 'json' + | 'json-bigint' + | 'text' + | 'raw' + | null + | undefined; export type Signal = RequestInit['signal']; export type Stringify = boolean; export type Url = string; diff --git a/superset-frontend/packages/superset-ui-core/test/connection/callApi/parseResponse.test.ts b/superset-frontend/packages/superset-ui-core/test/connection/callApi/parseResponse.test.ts index d54be27e9c8f..6b54adbd5cf8 100644 --- a/superset-frontend/packages/superset-ui-core/test/connection/callApi/parseResponse.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/connection/callApi/parseResponse.test.ts @@ -137,6 +137,17 @@ describe('parseResponse()', () => { expect(responseRaw.bodyUsed).toBe(false); }); + it('resolves to big number value if `parseMethod=json-bigint`', async () => { + const mockBigIntUrl = '/mock/get/bigInt'; + const mockGetBigIntPayload = '{ "value": 9223372036854775807 }'; + fetchMock.get(mockBigIntUrl, mockGetBigIntPayload); + const responseBigNumber = await parseResponse( + callApi({ url: mockBigIntUrl, method: 'GET' }), + 'json-bigint', + ); + expect(`${responseBigNumber.json.value}`).toEqual('9223372036854775807'); + }); + it('rejects if request.ok=false', async () => { expect.assertions(3); const mockNotOkayUrl = '/mock/notokay/url'; diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index 7811c0edd8d7..0da9295b3a02 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -17,7 +17,6 @@ * under the License. */ import shortid from 'shortid'; -import JSONbig from 'json-bigint'; import { t, SupersetClient } from '@superset-ui/core'; import invert from 'lodash/invert'; import mapKeys from 'lodash/mapKeys'; @@ -306,12 +305,9 @@ export function fetchQueryResults(query, displayLimit) { return SupersetClient.get({ endpoint: `/superset/results/${query.resultsKey}/?rows=${displayLimit}`, - parseMethod: 'text', + parseMethod: 'json-bigint', }) - .then(({ text = '{}' }) => { - const bigIntJson = JSONbig.parse(text); - return dispatch(querySuccess(query, bigIntJson)); - }) + .then(({ json }) => dispatch(querySuccess(query, json))) .catch(response => getClientErrorObject(response).then(error => { const message = @@ -352,12 +348,11 @@ export function runQuery(query) { endpoint: `/superset/sql_json/${search}`, body: JSON.stringify(postPayload), headers: { 'Content-Type': 'application/json' }, - parseMethod: 'text', + parseMethod: 'json-bigint', }) - .then(({ text = '{}' }) => { + .then(({ json }) => { if (!query.runAsync) { - const bigIntJson = JSONbig.parse(text); - dispatch(querySuccess(query, bigIntJson)); + dispatch(querySuccess(query, json)); } }) .catch(response => diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index dea41497b82c..f59c2da7199f 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -139,6 +139,7 @@ const legacyChartDataRequest = async ( ...requestParams, url, postPayload: { form_data: formData }, + parseMethod: 'json-bigint', }; const clientMethod = @@ -196,6 +197,7 @@ const v1ChartDataRequest = async ( url, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), + parseMethod: 'json-bigint', }; return SupersetClient.post(querySettings);