@cubejs-client/core 1.6.32 → 1.6.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cubejs-client-core.cjs.js +20 -14
- package/dist/cubejs-client-core.cjs.js.map +1 -1
- package/dist/cubejs-client-core.umd.js +20 -14
- package/dist/cubejs-client-core.umd.js.map +1 -1
- package/dist/src/ResultSet.d.ts.map +1 -1
- package/dist/src/ResultSet.js +20 -13
- package/dist/src/format-d3-numeric-locale.d.ts +4 -0
- package/dist/src/format-d3-numeric-locale.d.ts.map +1 -0
- package/dist/src/format-d3-numeric-locale.js +103 -0
- package/dist/src/format.d.ts +17 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/format.js +89 -0
- package/dist/src/index.js +2 -0
- package/dist/test/CubeApi.test.js +37 -37
- package/dist/test/HttpTransport.test.js +3 -3
- package/dist/test/ResultSet.bench.d.ts +2 -0
- package/dist/test/ResultSet.bench.d.ts.map +1 -0
- package/dist/test/ResultSet.bench.js +109 -0
- package/dist/test/ResultSet.test.d.ts +1 -1
- package/dist/test/ResultSet.test.d.ts.map +1 -1
- package/dist/test/ResultSet.test.js +0 -2
- package/dist/test/SqlQuery.test.js +0 -1
- package/dist/test/compare-date-range.test.d.ts +1 -1
- package/dist/test/compare-date-range.test.d.ts.map +1 -1
- package/dist/test/compare-date-range.test.js +0 -2
- package/dist/test/data-blending.test.d.ts +1 -1
- package/dist/test/data-blending.test.d.ts.map +1 -1
- package/dist/test/data-blending.test.js +0 -2
- package/dist/test/dayjs-isolation.test.d.ts +1 -1
- package/dist/test/dayjs-isolation.test.d.ts.map +1 -1
- package/dist/test/dayjs-isolation.test.js +0 -2
- package/dist/test/default-heuristics.test.d.ts +1 -1
- package/dist/test/default-heuristics.test.d.ts.map +1 -1
- package/dist/test/default-heuristics.test.js +4 -5
- package/dist/test/drill-down.test.d.ts +1 -1
- package/dist/test/drill-down.test.d.ts.map +1 -1
- package/dist/test/drill-down.test.js +4 -5
- package/dist/test/format-no-intl.test.d.ts +2 -0
- package/dist/test/format-no-intl.test.d.ts.map +1 -0
- package/dist/test/format-no-intl.test.js +49 -0
- package/dist/test/format.test.d.ts +2 -0
- package/dist/test/format.test.d.ts.map +1 -0
- package/dist/test/format.test.js +87 -0
- package/dist/test/granularity.test.d.ts +1 -1
- package/dist/test/granularity.test.d.ts.map +1 -1
- package/dist/test/granularity.test.js +0 -2
- package/dist/test/index.test.js +2 -2
- package/dist/test/table.test.d.ts +1 -1
- package/dist/test/table.test.d.ts.map +1 -1
- package/dist/test/table.test.js +0 -2
- package/dist/test/utils.test.d.ts +1 -1
- package/dist/test/utils.test.d.ts.map +1 -1
- package/dist/test/utils.test.js +0 -2
- package/package.json +12 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultSet.d.ts","sourceRoot":"","sources":["../../src/ResultSet.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EAAE,eAAe,EAC5B,UAAU,EACV,QAAQ,EACR,KAAK,EACL,gBAAgB,EAAE,SAAS,EAC3B,gBAAgB,EAChB,MAAM,EACN,iBAAiB,EACjB,WAAW,EACX,aAAa,EACd,MAAM,SAAS,CAAC;AA6BjB,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAIhD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAE/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IAExD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAsB;IAExD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAK;IAE7B,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;WAEnD,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM;WAI7C,mBAAmB,CAAC,EAAE,EAAE,aAAa;IAInD;;;;;;;;;;;;;OAaG;WACW,WAAW,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC;gBAI3G,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,gBAAqB;IA2BxG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0DG;IACI,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI;IAmG7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACI,MAAM,CAAC,UAAU,GAAG,GAAG,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE;IAShF,OAAO,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"ResultSet.d.ts","sourceRoot":"","sources":["../../src/ResultSet.ts"],"names":[],"mappings":"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"}
|
package/dist/src/ResultSet.js
CHANGED
|
@@ -259,16 +259,21 @@ export default class ResultSet {
|
|
|
259
259
|
}
|
|
260
260
|
axisValues(axis, resultIndex = 0) {
|
|
261
261
|
const { query } = this.loadResponses[resultIndex];
|
|
262
|
+
const axisWithoutMeasures = axis.filter(d => d !== 'measures');
|
|
263
|
+
const measures = axis.includes('measures') ? (query.measures || []) : [];
|
|
262
264
|
return (row) => {
|
|
263
|
-
const value = (measure) =>
|
|
264
|
-
.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return
|
|
265
|
+
const value = (measure) => {
|
|
266
|
+
const result = axisWithoutMeasures.map((d) => {
|
|
267
|
+
const val = row[d];
|
|
268
|
+
return val != null ? val : null;
|
|
269
|
+
});
|
|
270
|
+
if (measure) {
|
|
271
|
+
result.push(measure);
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
};
|
|
275
|
+
if (measures.length > 0) {
|
|
276
|
+
return measures.map(value);
|
|
272
277
|
}
|
|
273
278
|
return [value()];
|
|
274
279
|
};
|
|
@@ -427,11 +432,13 @@ export default class ResultSet {
|
|
|
427
432
|
};
|
|
428
433
|
}
|
|
429
434
|
}
|
|
430
|
-
const
|
|
435
|
+
const xAxisValues = this.axisValues(normalizedPivotConfig.x, resultIndex);
|
|
436
|
+
const yAxisValues = this.axisValues(normalizedPivotConfig.y, resultIndex);
|
|
437
|
+
const xGrouped = pipe(map((row) => xAxisValues(row).map(xValues => ({ xValues, row }))), unnest, groupByXAxis)(this.timeDimensionBackwardCompatibleData(resultIndex));
|
|
431
438
|
const yValuesMap = {};
|
|
432
439
|
xGrouped.forEach(([, rows]) => {
|
|
433
440
|
rows.forEach(({ row }) => {
|
|
434
|
-
|
|
441
|
+
yAxisValues(row).forEach((values) => {
|
|
435
442
|
if (Object.keys(row).length > 0) {
|
|
436
443
|
yValuesMap[values.join()] = values;
|
|
437
444
|
}
|
|
@@ -439,12 +446,12 @@ export default class ResultSet {
|
|
|
439
446
|
});
|
|
440
447
|
});
|
|
441
448
|
const allYValues = Object.values(yValuesMap);
|
|
442
|
-
const measureOnX =
|
|
449
|
+
const measureOnX = normalizedPivotConfig.x.includes('measures');
|
|
443
450
|
return xGrouped.map(([, rows]) => {
|
|
444
451
|
const { xValues } = rows[0];
|
|
445
452
|
const yGrouped = {};
|
|
446
453
|
rows.forEach(({ row }) => {
|
|
447
|
-
const arr =
|
|
454
|
+
const arr = yAxisValues(row).map(yValues => ({ yValues, row }));
|
|
448
455
|
arr.forEach((res) => {
|
|
449
456
|
yGrouped[this.axisValuesString(res.yValues)] = res;
|
|
450
457
|
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FormatLocaleDefinition, FormatLocaleObject } from 'd3-format';
|
|
2
|
+
export declare const formatD3NumericLocale: Record<string, FormatLocaleDefinition>;
|
|
3
|
+
export declare function getD3NumericLocale(locale: string, currencyCode?: string): FormatLocaleObject;
|
|
4
|
+
//# sourceMappingURL=format-d3-numeric-locale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-d3-numeric-locale.d.ts","sourceRoot":"","sources":["../../src/format-d3-numeric-locale.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAkB5E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAcxE,CAAC;AA8DF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,SAAQ,GAAG,kBAAkB,CAsB3F"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { formatLocale } from 'd3-format';
|
|
2
|
+
import enUS from 'd3-format/locale/en-US.json';
|
|
3
|
+
import enGB from 'd3-format/locale/en-GB.json';
|
|
4
|
+
import zhCN from 'd3-format/locale/zh-CN.json';
|
|
5
|
+
import esES from 'd3-format/locale/es-ES.json';
|
|
6
|
+
import esMX from 'd3-format/locale/es-MX.json';
|
|
7
|
+
import deDE from 'd3-format/locale/de-DE.json';
|
|
8
|
+
import jaJP from 'd3-format/locale/ja-JP.json';
|
|
9
|
+
import frFR from 'd3-format/locale/fr-FR.json';
|
|
10
|
+
import ptBR from 'd3-format/locale/pt-BR.json';
|
|
11
|
+
import koKR from 'd3-format/locale/ko-KR.json';
|
|
12
|
+
import itIT from 'd3-format/locale/it-IT.json';
|
|
13
|
+
import nlNL from 'd3-format/locale/nl-NL.json';
|
|
14
|
+
import ruRU from 'd3-format/locale/ru-RU.json';
|
|
15
|
+
// Pre-built d3 locale definitions for the most popular locales.
|
|
16
|
+
// Used as a fallback when Intl is unavailable (e.g. some edge runtimes).
|
|
17
|
+
export const formatD3NumericLocale = {
|
|
18
|
+
'en-US': enUS,
|
|
19
|
+
'en-GB': enGB,
|
|
20
|
+
'zh-CN': zhCN,
|
|
21
|
+
'es-ES': esES,
|
|
22
|
+
'es-MX': esMX,
|
|
23
|
+
'de-DE': deDE,
|
|
24
|
+
'ja-JP': jaJP,
|
|
25
|
+
'fr-FR': frFR,
|
|
26
|
+
'pt-BR': ptBR,
|
|
27
|
+
'ko-KR': koKR,
|
|
28
|
+
'it-IT': itIT,
|
|
29
|
+
'nl-NL': nlNL,
|
|
30
|
+
'ru-RU': ruRU,
|
|
31
|
+
};
|
|
32
|
+
const currencySymbols = {
|
|
33
|
+
USD: '$',
|
|
34
|
+
EUR: '€',
|
|
35
|
+
GBP: '£',
|
|
36
|
+
JPY: '¥',
|
|
37
|
+
CNY: '¥',
|
|
38
|
+
KRW: '₩',
|
|
39
|
+
INR: '₹',
|
|
40
|
+
RUB: '₽',
|
|
41
|
+
};
|
|
42
|
+
function getCurrencySymbol(locale, currencyCode) {
|
|
43
|
+
try {
|
|
44
|
+
const cf = new Intl.NumberFormat(locale, { style: 'currency', currency: currencyCode });
|
|
45
|
+
const currencyParts = cf.formatToParts(1);
|
|
46
|
+
const currencySymbol = currencyParts.find((p) => p.type === 'currency')?.value ?? currencyCode;
|
|
47
|
+
const firstMeaningfulType = currencyParts.find((p) => !['literal', 'nan'].includes(p.type))?.type;
|
|
48
|
+
const symbolIsPrefix = firstMeaningfulType === 'currency';
|
|
49
|
+
return symbolIsPrefix ? [currencySymbol, ''] : ['', currencySymbol];
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
const symbol = currencySymbols[currencyCode] ?? currencyCode;
|
|
53
|
+
return [symbol, ''];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function deriveGrouping(locale) {
|
|
57
|
+
// en-US → "1,234,567,890" → sizes [1,3,3,3] → [3]
|
|
58
|
+
// en-IN → "1,23,45,67,890" → sizes [1,2,2,2,3] → [3,2]
|
|
59
|
+
const sizes = new Intl.NumberFormat(locale).formatToParts(1234567890)
|
|
60
|
+
.filter((p) => p.type === 'integer')
|
|
61
|
+
.map((p) => p.value.length);
|
|
62
|
+
if (sizes.length <= 1) {
|
|
63
|
+
return [3];
|
|
64
|
+
}
|
|
65
|
+
// d3 repeats the last array element for all remaining groups,
|
|
66
|
+
// so we only need the two rightmost (least-significant) group sizes.
|
|
67
|
+
const first = sizes[sizes.length - 1];
|
|
68
|
+
const second = sizes[sizes.length - 2];
|
|
69
|
+
return first === second ? [first] : [first, second];
|
|
70
|
+
}
|
|
71
|
+
function getD3NumericLocaleFromIntl(locale, currencyCode = 'USD') {
|
|
72
|
+
const nf = new Intl.NumberFormat(locale);
|
|
73
|
+
const numParts = nf.formatToParts(1234567.89);
|
|
74
|
+
const find = (type) => numParts.find((p) => p.type === type)?.value ?? '';
|
|
75
|
+
return {
|
|
76
|
+
decimal: find('decimal') || '.',
|
|
77
|
+
thousands: find('group') || ',',
|
|
78
|
+
grouping: deriveGrouping(locale),
|
|
79
|
+
currency: getCurrencySymbol(locale, currencyCode),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const localeCache = Object.create(null);
|
|
83
|
+
export function getD3NumericLocale(locale, currencyCode = 'USD') {
|
|
84
|
+
const key = `${locale}:${currencyCode}`;
|
|
85
|
+
if (localeCache[key]) {
|
|
86
|
+
return localeCache[key];
|
|
87
|
+
}
|
|
88
|
+
let definition;
|
|
89
|
+
if (formatD3NumericLocale[locale]) {
|
|
90
|
+
definition = { ...formatD3NumericLocale[locale], currency: getCurrencySymbol(locale, currencyCode) };
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
try {
|
|
94
|
+
definition = getD3NumericLocaleFromIntl(locale, currencyCode);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
console.warn('Failed to generate d3 local via Intl, failing back to en-US', e);
|
|
98
|
+
definition = formatD3NumericLocale['en-US'];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
localeCache[key] = formatLocale(definition);
|
|
102
|
+
return localeCache[key];
|
|
103
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DimensionFormat, MeasureFormat, TCubeMemberType } from './types';
|
|
2
|
+
export type FormatValueMember = {
|
|
3
|
+
type: TCubeMemberType;
|
|
4
|
+
format?: DimensionFormat | MeasureFormat;
|
|
5
|
+
/** ISO 4217 currency code (e.g. 'USD', 'EUR'). Used when format is 'currency'. */
|
|
6
|
+
currency?: string;
|
|
7
|
+
/** Time dimension granularity (e.g. 'day', 'month', 'year'). Used for time formatting when no explicit format is set. */
|
|
8
|
+
granularity?: string;
|
|
9
|
+
};
|
|
10
|
+
export type FormatValueOptions = FormatValueMember & {
|
|
11
|
+
/** Locale tag (e.g. 'en-US', 'de-DE', 'nl-NL'). Defaults to the runtime's locale via Intl.NumberFormat. */
|
|
12
|
+
locale?: string;
|
|
13
|
+
/** String to return for null/undefined values. Defaults to '∅'. */
|
|
14
|
+
emptyPlaceholder?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function formatValue(value: any, { type, format, currency, granularity, locale, emptyPlaceholder }: FormatValueOptions): string;
|
|
17
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAqD/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,CAAC,EAAE,eAAe,GAAG,aAAa,CAAC;IACzC,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yHAAyH;IACzH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG;IACnD,2GAA2G;IAC3G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,EACV,EAAE,IAAI,EAAE,MAAM,EAAE,QAAgB,EAAE,WAAW,EAAE,MAAsB,EAAE,gBAAsB,EAAE,EAAE,kBAAkB,GAClH,MAAM,CAgDR"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { format as d3Format } from 'd3-format';
|
|
2
|
+
import { timeFormat } from 'd3-time-format';
|
|
3
|
+
import { getD3NumericLocale } from './format-d3-numeric-locale';
|
|
4
|
+
// Default d3-format specifiers — aligned with the named _2 formats
|
|
5
|
+
// (number_2, currency_2, percent_2) in named-numeric-formats.ts
|
|
6
|
+
const DEFAULT_NUMBER_FORMAT = ',.2f';
|
|
7
|
+
const DEFAULT_CURRENCY_FORMAT = '$,.2f';
|
|
8
|
+
const DEFAULT_PERCENT_FORMAT = '.2%';
|
|
9
|
+
function detectLocale() {
|
|
10
|
+
try {
|
|
11
|
+
return new Intl.NumberFormat().resolvedOptions().locale;
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
console.warn('Failed to detect locale', e);
|
|
15
|
+
return 'en-US';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const currentLocale = detectLocale();
|
|
19
|
+
const DEFAULT_DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S';
|
|
20
|
+
const DEFAULT_DATE_FORMAT = '%Y-%m-%d';
|
|
21
|
+
const DEFAULT_DATE_MONTH_FORMAT = '%Y-%m';
|
|
22
|
+
const DEFAULT_DATE_QUARTER_FORMAT = '%Y-Q%q';
|
|
23
|
+
const DEFAULT_DATE_YEAR_FORMAT = '%Y';
|
|
24
|
+
function getTimeFormatByGrain(grain) {
|
|
25
|
+
switch (grain) {
|
|
26
|
+
case 'day':
|
|
27
|
+
case 'week':
|
|
28
|
+
return DEFAULT_DATE_FORMAT;
|
|
29
|
+
case 'month':
|
|
30
|
+
return DEFAULT_DATE_MONTH_FORMAT;
|
|
31
|
+
case 'quarter':
|
|
32
|
+
return DEFAULT_DATE_QUARTER_FORMAT;
|
|
33
|
+
case 'year':
|
|
34
|
+
return DEFAULT_DATE_YEAR_FORMAT;
|
|
35
|
+
case 'second':
|
|
36
|
+
case 'minute':
|
|
37
|
+
case 'hour':
|
|
38
|
+
default:
|
|
39
|
+
return DEFAULT_DATETIME_FORMAT;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function parseNumber(value) {
|
|
43
|
+
if (value === null || value === undefined) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
return parseFloat(value);
|
|
47
|
+
}
|
|
48
|
+
export function formatValue(value, { type, format, currency = 'USD', granularity, locale = currentLocale, emptyPlaceholder = '∅' }) {
|
|
49
|
+
if (value === null || value === undefined) {
|
|
50
|
+
return emptyPlaceholder;
|
|
51
|
+
}
|
|
52
|
+
if (format && typeof format === 'object') {
|
|
53
|
+
if (format.type === 'custom-numeric') {
|
|
54
|
+
return d3Format(format.value)(parseNumber(value));
|
|
55
|
+
}
|
|
56
|
+
if (format.type === 'custom-time') {
|
|
57
|
+
const date = new Date(value);
|
|
58
|
+
return Number.isNaN(date.getTime()) ? 'Invalid date' : timeFormat(format.value)(date);
|
|
59
|
+
}
|
|
60
|
+
// { type: 'link', label: string } — return value as string
|
|
61
|
+
return String(value);
|
|
62
|
+
}
|
|
63
|
+
if (typeof format === 'string') {
|
|
64
|
+
switch (format) {
|
|
65
|
+
case 'currency':
|
|
66
|
+
return getD3NumericLocale(locale, currency).format(DEFAULT_CURRENCY_FORMAT)(parseNumber(value));
|
|
67
|
+
case 'percent':
|
|
68
|
+
return getD3NumericLocale(locale).format(DEFAULT_PERCENT_FORMAT)(parseNumber(value));
|
|
69
|
+
case 'number':
|
|
70
|
+
return getD3NumericLocale(locale).format(DEFAULT_NUMBER_FORMAT)(parseNumber(value));
|
|
71
|
+
case 'imageUrl':
|
|
72
|
+
case 'id':
|
|
73
|
+
case 'link':
|
|
74
|
+
default:
|
|
75
|
+
return String(value);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// No explicit format — infer from type
|
|
79
|
+
if (type === 'time') {
|
|
80
|
+
const date = new Date(value);
|
|
81
|
+
if (Number.isNaN(date.getTime()))
|
|
82
|
+
return 'Invalid date';
|
|
83
|
+
return timeFormat(getTimeFormatByGrain(granularity))(date);
|
|
84
|
+
}
|
|
85
|
+
if (type === 'number') {
|
|
86
|
+
return getD3NumericLocale(locale, currency).format(DEFAULT_NUMBER_FORMAT)(parseNumber(value));
|
|
87
|
+
}
|
|
88
|
+
return String(value);
|
|
89
|
+
}
|
package/dist/src/index.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @copyright Cube Dev, Inc.
|
|
4
4
|
* @fileoverview Test signal parameter in CubeApi
|
|
5
5
|
*/
|
|
6
|
-
/* globals describe,test,expect,jest,beforeEach */
|
|
7
6
|
/* eslint-disable import/first */
|
|
7
|
+
import { vi } from 'vitest';
|
|
8
8
|
import { CubeApi as CubeApiOriginal } from '../src';
|
|
9
9
|
import HttpTransport from '../src/HttpTransport';
|
|
10
10
|
import RequestError from '../src/RequestError';
|
|
@@ -31,12 +31,12 @@ describe('CubeApi Constructor', () => {
|
|
|
31
31
|
});
|
|
32
32
|
describe('CubeApi Load', () => {
|
|
33
33
|
afterEach(() => {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
vi.restoreAllMocks();
|
|
36
36
|
});
|
|
37
37
|
test('simple query, no options', async () => {
|
|
38
38
|
// Create a spy on the request method
|
|
39
|
-
|
|
39
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
40
40
|
subscribe: (cb) => Promise.resolve(cb({
|
|
41
41
|
status: 200,
|
|
42
42
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -52,7 +52,7 @@ describe('CubeApi Load', () => {
|
|
|
52
52
|
});
|
|
53
53
|
test('simple query + { mutexKey, castNumerics }', async () => {
|
|
54
54
|
// Create a spy on the request method
|
|
55
|
-
|
|
55
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
56
56
|
subscribe: (cb) => Promise.resolve(cb({
|
|
57
57
|
status: 200,
|
|
58
58
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -68,7 +68,7 @@ describe('CubeApi Load', () => {
|
|
|
68
68
|
});
|
|
69
69
|
test('simple query + compact response format', async () => {
|
|
70
70
|
// Create a spy on the request method
|
|
71
|
-
|
|
71
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
72
72
|
subscribe: (cb) => Promise.resolve(cb({
|
|
73
73
|
status: 200,
|
|
74
74
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -84,7 +84,7 @@ describe('CubeApi Load', () => {
|
|
|
84
84
|
});
|
|
85
85
|
test('2 queries', async () => {
|
|
86
86
|
// Create a spy on the request method
|
|
87
|
-
|
|
87
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
88
88
|
subscribe: (cb) => Promise.resolve(cb({
|
|
89
89
|
status: 200,
|
|
90
90
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -99,7 +99,7 @@ describe('CubeApi Load', () => {
|
|
|
99
99
|
expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
|
|
100
100
|
});
|
|
101
101
|
test('simple query + { cache: "no-cache" }', async () => {
|
|
102
|
-
const requestSpy =
|
|
102
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
103
103
|
subscribe: (cb) => Promise.resolve(cb({
|
|
104
104
|
status: 200,
|
|
105
105
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -115,7 +115,7 @@ describe('CubeApi Load', () => {
|
|
|
115
115
|
expect(requestSpy.mock.calls[0]?.[1]?.cache).toBe('no-cache');
|
|
116
116
|
});
|
|
117
117
|
test('simple query + { cache: "must-revalidate" }', async () => {
|
|
118
|
-
const requestSpy =
|
|
118
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
119
119
|
subscribe: (cb) => Promise.resolve(cb({
|
|
120
120
|
status: 200,
|
|
121
121
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -132,7 +132,7 @@ describe('CubeApi Load', () => {
|
|
|
132
132
|
});
|
|
133
133
|
test('2 queries + compact response format', async () => {
|
|
134
134
|
// Create a spy on the request method
|
|
135
|
-
|
|
135
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
136
136
|
subscribe: (cb) => Promise.resolve(cb({
|
|
137
137
|
status: 200,
|
|
138
138
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -149,14 +149,14 @@ describe('CubeApi Load', () => {
|
|
|
149
149
|
});
|
|
150
150
|
describe('CubeApi with Abort Signal', () => {
|
|
151
151
|
afterEach(() => {
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
vi.clearAllMocks();
|
|
153
|
+
vi.restoreAllMocks();
|
|
154
154
|
});
|
|
155
155
|
test('should pass signal from constructor to request', async () => {
|
|
156
156
|
const controller = new AbortController();
|
|
157
157
|
const { signal } = controller;
|
|
158
158
|
// Create a spy on the request method
|
|
159
|
-
const requestSpy =
|
|
159
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
160
160
|
subscribe: (cb) => Promise.resolve(cb({
|
|
161
161
|
status: 200,
|
|
162
162
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -168,7 +168,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
168
168
|
signal
|
|
169
169
|
});
|
|
170
170
|
// Create a second spy on the load method to verify signal is passed to HttpTransport
|
|
171
|
-
|
|
171
|
+
vi.spyOn(cubeApi, 'load');
|
|
172
172
|
await cubeApi.load({
|
|
173
173
|
measures: ['Orders.count']
|
|
174
174
|
});
|
|
@@ -187,7 +187,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
187
187
|
const controller = new AbortController();
|
|
188
188
|
const { signal } = controller;
|
|
189
189
|
// Mock for this specific test
|
|
190
|
-
const requestSpy =
|
|
190
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
191
191
|
subscribe: (cb) => Promise.resolve(cb({
|
|
192
192
|
status: 200,
|
|
193
193
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -205,7 +205,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
205
205
|
const constructorController = new AbortController();
|
|
206
206
|
const optionsController = new AbortController();
|
|
207
207
|
// Mock for this specific test
|
|
208
|
-
const requestSpy =
|
|
208
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
209
209
|
subscribe: (cb) => Promise.resolve(cb({
|
|
210
210
|
status: 200,
|
|
211
211
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -225,7 +225,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
225
225
|
const controller = new AbortController();
|
|
226
226
|
const { signal } = controller;
|
|
227
227
|
// Mock for meta with proper format - include dimensions, segments, and measures with required properties
|
|
228
|
-
const requestSpy =
|
|
228
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
229
229
|
subscribe: (cb) => Promise.resolve(cb({
|
|
230
230
|
status: 200,
|
|
231
231
|
text: () => Promise.resolve(JSON.stringify({
|
|
@@ -277,7 +277,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
277
277
|
const controller = new AbortController();
|
|
278
278
|
const { signal } = controller;
|
|
279
279
|
// Mock for SQL response
|
|
280
|
-
const requestSpy =
|
|
280
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
281
281
|
subscribe: (cb) => Promise.resolve(cb({
|
|
282
282
|
status: 200,
|
|
283
283
|
text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
|
|
@@ -295,7 +295,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
295
295
|
const controller = new AbortController();
|
|
296
296
|
const { signal } = controller;
|
|
297
297
|
// Mock for dryRun response
|
|
298
|
-
const requestSpy =
|
|
298
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
299
299
|
subscribe: (cb) => Promise.resolve(cb({
|
|
300
300
|
status: 200,
|
|
301
301
|
text: () => Promise.resolve('{"queryType":"regular"}'),
|
|
@@ -312,8 +312,8 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
312
312
|
});
|
|
313
313
|
describe('CubeApi cubeSql', () => {
|
|
314
314
|
afterEach(() => {
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
vi.clearAllMocks();
|
|
316
|
+
vi.restoreAllMocks();
|
|
317
317
|
});
|
|
318
318
|
const cubeSqlResponseBody = [
|
|
319
319
|
JSON.stringify({
|
|
@@ -335,7 +335,7 @@ describe('CubeApi cubeSql', () => {
|
|
|
335
335
|
JSON.stringify({ data: [['Active']] }),
|
|
336
336
|
].join('\n');
|
|
337
337
|
test('should parse lastRefreshTime from response', async () => {
|
|
338
|
-
|
|
338
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
339
339
|
subscribe: (cb) => Promise.resolve(cb({
|
|
340
340
|
status: 200,
|
|
341
341
|
text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBody })),
|
|
@@ -357,7 +357,7 @@ describe('CubeApi cubeSql', () => {
|
|
|
357
357
|
]);
|
|
358
358
|
});
|
|
359
359
|
test('should omit lastRefreshTime when not present in response', async () => {
|
|
360
|
-
|
|
360
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
361
361
|
subscribe: (cb) => Promise.resolve(cb({
|
|
362
362
|
status: 200,
|
|
363
363
|
text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBodyNoRefreshTime })),
|
|
@@ -374,12 +374,12 @@ describe('CubeApi cubeSql', () => {
|
|
|
374
374
|
});
|
|
375
375
|
describe('CubeApi with baseRequestId', () => {
|
|
376
376
|
afterEach(() => {
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
vi.clearAllMocks();
|
|
378
|
+
vi.restoreAllMocks();
|
|
379
379
|
});
|
|
380
380
|
test('should pass baseRequestId from options to request', async () => {
|
|
381
381
|
const baseRequestId = 'custom-request-id-123';
|
|
382
|
-
const requestSpy =
|
|
382
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
383
383
|
subscribe: (cb) => Promise.resolve(cb({
|
|
384
384
|
status: 200,
|
|
385
385
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -394,7 +394,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
394
394
|
expect(requestSpy.mock.calls[0]?.[1]?.baseRequestId).toBe(baseRequestId);
|
|
395
395
|
});
|
|
396
396
|
test('should generate baseRequestId if not provided', async () => {
|
|
397
|
-
const requestSpy =
|
|
397
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
398
398
|
subscribe: (cb) => Promise.resolve(cb({
|
|
399
399
|
status: 200,
|
|
400
400
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -412,7 +412,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
412
412
|
});
|
|
413
413
|
test('should pass baseRequestId to sql request', async () => {
|
|
414
414
|
const baseRequestId = 'sql-request-id-456';
|
|
415
|
-
const requestSpy =
|
|
415
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
416
416
|
subscribe: (cb) => Promise.resolve(cb({
|
|
417
417
|
status: 200,
|
|
418
418
|
text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
|
|
@@ -428,7 +428,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
428
428
|
});
|
|
429
429
|
test('should pass baseRequestId to dryRun request', async () => {
|
|
430
430
|
const baseRequestId = 'dryrun-request-id-789';
|
|
431
|
-
const requestSpy =
|
|
431
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
432
432
|
subscribe: (cb) => Promise.resolve(cb({
|
|
433
433
|
status: 200,
|
|
434
434
|
text: () => Promise.resolve('{"queryType":"regular"}'),
|
|
@@ -444,7 +444,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
444
444
|
});
|
|
445
445
|
test('should pass baseRequestId to subscribe request', async () => {
|
|
446
446
|
const baseRequestId = 'subscribe-request-id-abc';
|
|
447
|
-
const requestSpy =
|
|
447
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
448
448
|
subscribe: (cb) => Promise.resolve(cb({
|
|
449
449
|
status: 200,
|
|
450
450
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -465,7 +465,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
465
465
|
});
|
|
466
466
|
test('should pass baseRequestId with multiple queries', async () => {
|
|
467
467
|
const baseRequestId = 'multi-query-request-id';
|
|
468
|
-
const requestSpy =
|
|
468
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
469
469
|
subscribe: (cb) => Promise.resolve(cb({
|
|
470
470
|
status: 200,
|
|
471
471
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -484,7 +484,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
484
484
|
});
|
|
485
485
|
test('should pass baseRequestId to meta request', async () => {
|
|
486
486
|
const baseRequestId = 'meta-request-id-def';
|
|
487
|
-
const requestSpy =
|
|
487
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
488
488
|
subscribe: (cb) => Promise.resolve(cb({
|
|
489
489
|
status: 200,
|
|
490
490
|
text: () => Promise.resolve(JSON.stringify({
|
|
@@ -535,11 +535,11 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
535
535
|
});
|
|
536
536
|
describe('CubeApi Mutex Cancellation', () => {
|
|
537
537
|
afterEach(() => {
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
vi.clearAllMocks();
|
|
539
|
+
vi.restoreAllMocks();
|
|
540
540
|
});
|
|
541
541
|
test('should return null for cancelled query when a newer query invalidates it', async () => {
|
|
542
|
-
|
|
542
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
543
543
|
subscribe: (cb) => Promise.resolve(cb({
|
|
544
544
|
status: 200,
|
|
545
545
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -562,7 +562,7 @@ describe('CubeApi Mutex Cancellation', () => {
|
|
|
562
562
|
expect(second).toBeInstanceOf(ResultSet);
|
|
563
563
|
});
|
|
564
564
|
test('should return ResultSet when no mutex cancellation occurs', async () => {
|
|
565
|
-
|
|
565
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
566
566
|
subscribe: (cb) => Promise.resolve(cb({
|
|
567
567
|
status: 200,
|
|
568
568
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -579,7 +579,7 @@ describe('CubeApi Mutex Cancellation', () => {
|
|
|
579
579
|
});
|
|
580
580
|
test('should propagate non-mutex errors', async () => {
|
|
581
581
|
const errorBody = { error: 'Internal Server Error' };
|
|
582
|
-
|
|
582
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
583
583
|
subscribe: (cb) => Promise.resolve(cb({
|
|
584
584
|
status: 500,
|
|
585
585
|
text: () => Promise.resolve(JSON.stringify(errorBody)),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable import/first */
|
|
2
|
-
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
3
|
import fetch from 'cross-fetch';
|
|
4
|
-
|
|
4
|
+
vi.mock('cross-fetch');
|
|
5
5
|
import HttpTransport from '../src/HttpTransport';
|
|
6
6
|
const mockedFetch = fetch;
|
|
7
7
|
describe('HttpTransport', () => {
|
|
@@ -183,7 +183,7 @@ describe('HttpTransport', () => {
|
|
|
183
183
|
// Mock AbortSignal.timeout
|
|
184
184
|
const originalTimeout = AbortSignal.timeout;
|
|
185
185
|
const mockTimeoutSignal = {};
|
|
186
|
-
AbortSignal.timeout =
|
|
186
|
+
AbortSignal.timeout = vi.fn().mockReturnValue(mockTimeoutSignal);
|
|
187
187
|
const transport = new HttpTransport({
|
|
188
188
|
authorization: 'token',
|
|
189
189
|
apiUrl: 'http://localhost:4000/cubejs-api/v1',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResultSet.bench.d.ts","sourceRoot":"","sources":["../../test/ResultSet.bench.ts"],"names":[],"mappings":""}
|