@cubejs-client/core 1.3.14 → 1.3.16

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.
Files changed (100) hide show
  1. package/dist/{cubejs-client-core.js → cubejs-client-core.cjs.js} +1016 -411
  2. package/dist/cubejs-client-core.cjs.js.map +1 -0
  3. package/dist/cubejs-client-core.umd.js +2901 -12088
  4. package/dist/cubejs-client-core.umd.js.map +1 -1
  5. package/dist/src/HttpTransport.d.ts +54 -0
  6. package/dist/src/HttpTransport.d.ts.map +1 -0
  7. package/dist/src/HttpTransport.js +55 -0
  8. package/dist/src/Meta.d.ts +62 -0
  9. package/dist/src/Meta.d.ts.map +1 -0
  10. package/dist/src/Meta.js +150 -0
  11. package/dist/src/ProgressResult.d.ts +8 -0
  12. package/dist/src/ProgressResult.d.ts.map +1 -0
  13. package/dist/src/ProgressResult.js +11 -0
  14. package/dist/src/RequestError.d.ts +6 -0
  15. package/dist/src/RequestError.d.ts.map +1 -0
  16. package/dist/src/RequestError.js +7 -0
  17. package/dist/src/ResultSet.d.ts +430 -0
  18. package/dist/src/ResultSet.d.ts.map +1 -0
  19. package/dist/src/ResultSet.js +952 -0
  20. package/dist/src/SqlQuery.d.ts +17 -0
  21. package/dist/src/SqlQuery.d.ts.map +1 -0
  22. package/dist/src/SqlQuery.js +11 -0
  23. package/dist/src/index.d.ts +194 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +411 -0
  26. package/dist/src/index.umd.d.ts +3 -0
  27. package/dist/src/index.umd.d.ts.map +1 -0
  28. package/dist/src/index.umd.js +6 -0
  29. package/dist/src/time.d.ts +70 -0
  30. package/dist/src/time.d.ts.map +1 -0
  31. package/dist/src/time.js +249 -0
  32. package/dist/src/types.d.ts +424 -0
  33. package/dist/src/types.d.ts.map +1 -0
  34. package/dist/src/types.js +1 -0
  35. package/dist/src/utils.d.ts +19 -0
  36. package/dist/src/utils.d.ts.map +1 -0
  37. package/dist/src/utils.js +294 -0
  38. package/dist/test/CubeApi.test.d.ts +7 -0
  39. package/dist/test/CubeApi.test.d.ts.map +1 -0
  40. package/dist/test/CubeApi.test.js +279 -0
  41. package/dist/test/HttpTransport.test.d.ts +2 -0
  42. package/dist/test/HttpTransport.test.d.ts.map +1 -0
  43. package/dist/test/HttpTransport.test.js +244 -0
  44. package/dist/test/ResultSet.test.d.ts +7 -0
  45. package/dist/test/ResultSet.test.d.ts.map +1 -0
  46. package/dist/test/ResultSet.test.js +1725 -0
  47. package/dist/test/compare-date-range.test.d.ts +2 -0
  48. package/dist/test/compare-date-range.test.d.ts.map +1 -0
  49. package/dist/test/compare-date-range.test.js +742 -0
  50. package/dist/test/data-blending.test.d.ts +2 -0
  51. package/dist/test/data-blending.test.d.ts.map +1 -0
  52. package/dist/test/data-blending.test.js +423 -0
  53. package/dist/test/default-heuristics.test.d.ts +2 -0
  54. package/dist/test/default-heuristics.test.d.ts.map +1 -0
  55. package/dist/test/default-heuristics.test.js +108 -0
  56. package/dist/test/drill-down.test.d.ts +2 -0
  57. package/dist/test/drill-down.test.d.ts.map +1 -0
  58. package/dist/test/drill-down.test.js +373 -0
  59. package/dist/test/fixtures/datablending/load-responses.json +261 -0
  60. package/dist/test/granularity.test.d.ts +2 -0
  61. package/dist/test/granularity.test.d.ts.map +1 -0
  62. package/dist/test/granularity.test.js +218 -0
  63. package/dist/test/helpers.d.ts +283 -0
  64. package/dist/test/helpers.d.ts.map +1 -0
  65. package/dist/test/helpers.js +974 -0
  66. package/dist/test/index.test.d.ts +7 -0
  67. package/dist/test/index.test.d.ts.map +1 -0
  68. package/dist/test/index.test.js +370 -0
  69. package/dist/test/table.test.d.ts +2 -0
  70. package/dist/test/table.test.d.ts.map +1 -0
  71. package/dist/test/table.test.js +757 -0
  72. package/dist/test/utils.test.d.ts +2 -0
  73. package/dist/test/utils.test.d.ts.map +1 -0
  74. package/dist/test/utils.test.js +32 -0
  75. package/package.json +26 -21
  76. package/dist/cubejs-client-core.esm.js +0 -1639
  77. package/dist/cubejs-client-core.esm.js.map +0 -1
  78. package/dist/cubejs-client-core.js.map +0 -1
  79. package/index.d.ts +0 -1338
  80. package/src/HttpTransport.js +0 -60
  81. package/src/HttpTransport.test.js +0 -117
  82. package/src/Meta.js +0 -142
  83. package/src/ProgressResult.js +0 -13
  84. package/src/RequestError.js +0 -7
  85. package/src/ResultSet.js +0 -746
  86. package/src/SqlQuery.js +0 -13
  87. package/src/index.js +0 -398
  88. package/src/index.test.js +0 -454
  89. package/src/index.umd.js +0 -8
  90. package/src/tests/ResultSet.test.js +0 -1655
  91. package/src/tests/compare-date-range.test.js +0 -753
  92. package/src/tests/data-blending.test.js +0 -432
  93. package/src/tests/default-heuristics.test.js +0 -118
  94. package/src/tests/drill-down.test.js +0 -402
  95. package/src/tests/fixtures/datablending/load-responses.json +0 -261
  96. package/src/tests/granularity.test.js +0 -225
  97. package/src/tests/table.test.js +0 -791
  98. package/src/tests/utils.test.js +0 -35
  99. package/src/time.js +0 -296
  100. package/src/utils.js +0 -368
package/src/ResultSet.js DELETED
@@ -1,746 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import {
3
- groupBy, pipe, fromPairs, uniq, filter, map, dropLast, equals, reduce, minBy, maxBy, clone, mergeDeepLeft,
4
- pluck, mergeAll, flatten,
5
- } from 'ramda';
6
-
7
- import { aliasSeries } from './utils';
8
- import {
9
- DateRegex,
10
- dayRange,
11
- internalDayjs,
12
- isPredefinedGranularity,
13
- LocalDateRegex,
14
- TIME_SERIES,
15
- timeSeriesFromCustomInterval
16
- } from './time';
17
-
18
- const groupByToPairs = (keyFn) => {
19
- const acc = new Map();
20
-
21
- return (data) => {
22
- data.forEach((row) => {
23
- const key = keyFn(row);
24
-
25
- if (!acc.has(key)) {
26
- acc.set(key, []);
27
- }
28
-
29
- acc.get(key).push(row);
30
- });
31
-
32
- return Array.from(acc.entries());
33
- };
34
- };
35
-
36
- const unnest = (arr) => {
37
- const res = [];
38
- arr.forEach((subArr) => {
39
- subArr.forEach(element => res.push(element));
40
- });
41
-
42
- return res;
43
- };
44
-
45
- export const QUERY_TYPE = {
46
- REGULAR_QUERY: 'regularQuery',
47
- COMPARE_DATE_RANGE_QUERY: 'compareDateRangeQuery',
48
- BLENDING_QUERY: 'blendingQuery',
49
- };
50
-
51
- class ResultSet {
52
- static measureFromAxis(axisValues) {
53
- return axisValues[axisValues.length - 1];
54
- }
55
-
56
- static timeDimensionMember(td) {
57
- return `${td.dimension}.${td.granularity}`;
58
- }
59
-
60
- static deserialize(data, options = {}) {
61
- return new ResultSet(data.loadResponse, options);
62
- }
63
-
64
- constructor(loadResponse, options = {}) {
65
- this.loadResponse = loadResponse;
66
-
67
- if (this.loadResponse.queryType != null) {
68
- this.queryType = loadResponse.queryType;
69
- this.loadResponses = loadResponse.results;
70
- } else {
71
- this.queryType = QUERY_TYPE.REGULAR_QUERY;
72
- this.loadResponse.pivotQuery = {
73
- ...loadResponse.query,
74
- queryType: this.queryType
75
- };
76
- this.loadResponses = [loadResponse];
77
- }
78
-
79
- if (!Object.values(QUERY_TYPE).includes(this.queryType)) {
80
- throw new Error('Unknown query type');
81
- }
82
-
83
- this.parseDateMeasures = options.parseDateMeasures;
84
- this.options = options;
85
-
86
- this.backwardCompatibleData = [];
87
- }
88
-
89
- drillDown(drillDownLocator, pivotConfig) {
90
- if (this.queryType === QUERY_TYPE.COMPARE_DATE_RANGE_QUERY) {
91
- throw new Error('compareDateRange drillDown query is not currently supported');
92
- }
93
- if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
94
- throw new Error('Data blending drillDown query is not currently supported');
95
- }
96
-
97
- const { query } = this.loadResponses[0];
98
- const { xValues = [], yValues = [] } = drillDownLocator;
99
- const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig);
100
-
101
- const values = [];
102
- normalizedPivotConfig.x.forEach((member, currentIndex) => values.push([member, xValues[currentIndex]]));
103
- normalizedPivotConfig.y.forEach((member, currentIndex) => values.push([member, yValues[currentIndex]]));
104
-
105
- const { filters: parentFilters = [], segments = [] } = this.query();
106
- const { measures } = this.loadResponses[0].annotation;
107
- let [, measureName] = values.find(([member]) => member === 'measures') || [];
108
-
109
- if (measureName === undefined) {
110
- [measureName] = Object.keys(measures);
111
- }
112
-
113
- if (!(measures[measureName] && measures[measureName].drillMembers || []).length) {
114
- return null;
115
- }
116
-
117
- const filters = [
118
- {
119
- member: measureName,
120
- operator: 'measureFilter',
121
- },
122
- ...parentFilters
123
- ];
124
- const timeDimensions = [];
125
-
126
- values.filter(([member]) => member !== 'measures')
127
- .forEach(([member, value]) => {
128
- const [cubeName, dimension, granularity] = member.split('.');
129
-
130
- if (granularity !== undefined) {
131
- const range = dayRange(value, value).snapTo(granularity);
132
- const originalTimeDimension = query.timeDimensions.find((td) => td.dimension);
133
-
134
- let dateRange = [
135
- range.start,
136
- range.end
137
- ];
138
-
139
- if (originalTimeDimension?.dateRange) {
140
- const [originalStart, originalEnd] = originalTimeDimension.dateRange;
141
-
142
- dateRange = [
143
- dayjs(originalStart) > range.start ? dayjs(originalStart) : range.start,
144
- dayjs(originalEnd) < range.end ? dayjs(originalEnd) : range.end,
145
- ];
146
- }
147
-
148
- timeDimensions.push({
149
- dimension: [cubeName, dimension].join('.'),
150
- dateRange: dateRange.map((dt) => dt.format('YYYY-MM-DDTHH:mm:ss.SSS')),
151
- });
152
- } else if (value == null) {
153
- filters.push({
154
- member,
155
- operator: 'notSet',
156
- });
157
- } else {
158
- filters.push({
159
- member,
160
- operator: 'equals',
161
- values: [value.toString()],
162
- });
163
- }
164
- });
165
-
166
- if (
167
- timeDimensions.length === 0 &&
168
- query.timeDimensions.length > 0 &&
169
- query.timeDimensions[0].granularity == null
170
- ) {
171
- timeDimensions.push(query.timeDimensions[0]);
172
- }
173
-
174
- return {
175
- ...measures[measureName].drillMembersGrouped,
176
- filters,
177
- ...(segments.length > 0 ? { segments } : {}),
178
- timeDimensions,
179
- segments,
180
- timezone: query.timezone
181
- };
182
- }
183
-
184
- series(pivotConfig) {
185
- return this.seriesNames(pivotConfig).map(({ title, shortTitle, key }) => ({
186
- title,
187
- shortTitle,
188
- key,
189
- series: this.chartPivot(pivotConfig).map(({ x, ...obj }) => ({ value: obj[key], x }))
190
- }));
191
- }
192
-
193
- axisValues(axis, resultIndex = 0) {
194
- const { query } = this.loadResponses[resultIndex];
195
-
196
- return row => {
197
- const value = (measure) => axis.filter(d => d !== 'measures')
198
- .map(d => (row[d] != null ? row[d] : null)).concat(measure ? [measure] : []);
199
-
200
- if (axis.find(d => d === 'measures') && (query.measures || []).length) {
201
- return query.measures.map(value);
202
- }
203
-
204
- return [value()];
205
- };
206
- }
207
-
208
- axisValuesString(axisValues, delimiter) {
209
- const formatValue = (v) => {
210
- if (v == null) {
211
- return '∅';
212
- } else if (v === '') {
213
- return '[Empty string]';
214
- } else {
215
- return v;
216
- }
217
- };
218
- return axisValues.map(formatValue).join(delimiter || ', ');
219
- }
220
-
221
- static getNormalizedPivotConfig(query = {}, pivotConfig = null) {
222
- const defaultPivotConfig = {
223
- x: [],
224
- y: [],
225
- fillMissingDates: true,
226
- joinDateRange: false
227
- };
228
-
229
- const {
230
- measures = [],
231
- dimensions = []
232
- } = query;
233
-
234
- const timeDimensions = (query.timeDimensions || []).filter(td => !!td.granularity);
235
-
236
- pivotConfig = pivotConfig || (timeDimensions.length ? {
237
- x: timeDimensions.map(td => ResultSet.timeDimensionMember(td)),
238
- y: dimensions
239
- } : {
240
- x: dimensions,
241
- y: []
242
- });
243
-
244
- pivotConfig = mergeDeepLeft(pivotConfig, defaultPivotConfig);
245
-
246
- const substituteTimeDimensionMembers = axis => axis.map(
247
- subDim => (
248
- (
249
- timeDimensions.find(td => td.dimension === subDim) &&
250
- !dimensions.find(d => d === subDim)
251
- ) ?
252
- ResultSet.timeDimensionMember(query.timeDimensions.find(td => td.dimension === subDim)) :
253
- subDim
254
- )
255
- );
256
-
257
- pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x);
258
- pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y);
259
-
260
- const allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
261
- const allDimensions = timeDimensions.map(td => ResultSet.timeDimensionMember(td)).concat(dimensions);
262
-
263
- const dimensionFilter = (key) => allDimensions.includes(key) || key === 'measures';
264
-
265
- pivotConfig.x = pivotConfig.x.concat(
266
- allDimensions.filter(d => !allIncludedDimensions.includes(d) && d !== 'compareDateRange')
267
- )
268
- .filter(dimensionFilter);
269
- pivotConfig.y = pivotConfig.y.filter(dimensionFilter);
270
-
271
- if (!pivotConfig.x.concat(pivotConfig.y).find(d => d === 'measures')) {
272
- pivotConfig.y.push('measures');
273
- }
274
-
275
- if (dimensions.includes('compareDateRange') && !pivotConfig.y.concat(pivotConfig.x).includes('compareDateRange')) {
276
- pivotConfig.y.unshift('compareDateRange');
277
- }
278
-
279
- if (!measures.length) {
280
- pivotConfig.x = pivotConfig.x.filter(d => d !== 'measures');
281
- pivotConfig.y = pivotConfig.y.filter(d => d !== 'measures');
282
- }
283
-
284
- return pivotConfig;
285
- }
286
-
287
- normalizePivotConfig(pivotConfig) {
288
- return ResultSet.getNormalizedPivotConfig(this.loadResponse.pivotQuery, pivotConfig);
289
- }
290
-
291
- timeSeries(timeDimension, resultIndex, annotations) {
292
- if (!timeDimension.granularity) {
293
- return null;
294
- }
295
-
296
- let { dateRange } = timeDimension;
297
-
298
- if (!dateRange) {
299
- const member = ResultSet.timeDimensionMember(timeDimension);
300
- const dates = pipe(
301
- map(row => row[member] && internalDayjs(row[member])),
302
- filter(Boolean)
303
- )(this.timeDimensionBackwardCompatibleData(resultIndex));
304
-
305
- dateRange = dates.length && [
306
- reduce(minBy(d => d.toDate()), dates[0], dates),
307
- reduce(maxBy(d => d.toDate()), dates[0], dates)
308
- ] || null;
309
- }
310
-
311
- if (!dateRange) {
312
- return null;
313
- }
314
-
315
- const padToDay = timeDimension.dateRange ?
316
- timeDimension.dateRange.find(d => d.match(DateRegex)) :
317
- !['hour', 'minute', 'second'].includes(timeDimension.granularity);
318
-
319
- const [start, end] = dateRange;
320
- const range = dayRange(start, end);
321
-
322
- if (isPredefinedGranularity(timeDimension.granularity)) {
323
- return TIME_SERIES[timeDimension.granularity](
324
- padToDay ? range.snapTo('d') : range
325
- );
326
- }
327
-
328
- if (!annotations[`${timeDimension.dimension}.${timeDimension.granularity}`]) {
329
- throw new Error(`Granularity "${timeDimension.granularity}" not found in time dimension "${timeDimension.dimension}"`);
330
- }
331
-
332
- return timeSeriesFromCustomInterval(
333
- start, end, annotations[`${timeDimension.dimension}.${timeDimension.granularity}`].granularity
334
- );
335
- }
336
-
337
- pivot(pivotConfig) {
338
- pivotConfig = this.normalizePivotConfig(pivotConfig);
339
- const { pivotQuery: query } = this.loadResponse;
340
-
341
- const pivotImpl = (resultIndex = 0) => {
342
- let groupByXAxis = groupByToPairs(({ xValues }) => this.axisValuesString(xValues));
343
-
344
- const measureValue = (row, measure) => row[measure] || pivotConfig.fillWithValue || 0;
345
-
346
- if (
347
- pivotConfig.fillMissingDates &&
348
- pivotConfig.x.length === 1 &&
349
- (equals(
350
- pivotConfig.x,
351
- (query.timeDimensions || [])
352
- .filter(td => Boolean(td.granularity))
353
- .map(td => ResultSet.timeDimensionMember(td))
354
- ))
355
- ) {
356
- const series = this.loadResponses.map(
357
- (loadResponse) => this.timeSeries(
358
- loadResponse.query.timeDimensions[0],
359
- resultIndex, loadResponse.annotation.timeDimensions
360
- )
361
- );
362
-
363
- if (series[0]) {
364
- groupByXAxis = (rows) => {
365
- const byXValues = groupBy(
366
- ({ xValues }) => xValues[0],
367
- rows
368
- );
369
- return series[resultIndex].map(d => [d, byXValues[d] || [{ xValues: [d], row: {} }]]);
370
- };
371
- }
372
- }
373
-
374
- const xGrouped = pipe(
375
- map(row => this.axisValues(pivotConfig.x, resultIndex)(row).map(xValues => ({ xValues, row }))),
376
- unnest,
377
- groupByXAxis
378
- )(this.timeDimensionBackwardCompatibleData(resultIndex));
379
-
380
- const yValuesMap = {};
381
- xGrouped.forEach(([, rows]) => {
382
- rows.forEach(({ row }) => {
383
- this.axisValues(pivotConfig.y, resultIndex)(row).forEach((values) => {
384
- if (Object.keys(row).length > 0) {
385
- yValuesMap[values.join()] = values;
386
- }
387
- });
388
- });
389
- });
390
- const allYValues = Object.values(yValuesMap);
391
-
392
- const measureOnX = Boolean(pivotConfig.x.find(d => d === 'measures'));
393
-
394
- return xGrouped.map(([, rows]) => {
395
- const { xValues } = rows[0];
396
- const yGrouped = {};
397
-
398
- rows.forEach(({ row }) => {
399
- const arr = this.axisValues(pivotConfig.y, resultIndex)(row).map(yValues => ({ yValues, row }));
400
- arr.forEach((res) => {
401
- yGrouped[this.axisValuesString(res.yValues)] = res;
402
- });
403
- });
404
-
405
- return {
406
- xValues,
407
- yValuesArray: unnest(allYValues.map(yValues => {
408
- const measure = measureOnX ?
409
- ResultSet.measureFromAxis(xValues) :
410
- ResultSet.measureFromAxis(yValues);
411
-
412
- return [[yValues, measureValue((yGrouped[this.axisValuesString(yValues)] ||
413
- ({ row: {} })).row, measure)]];
414
- }))
415
- };
416
- });
417
- };
418
-
419
- const pivots = this.loadResponses.length > 1
420
- ? this.loadResponses.map((_, index) => pivotImpl(index))
421
- : [];
422
-
423
- return pivots.length
424
- ? this.mergePivots(pivots, pivotConfig.joinDateRange)
425
- : pivotImpl();
426
- }
427
-
428
- mergePivots(pivots, joinDateRange) {
429
- const minLengthPivot = pivots.reduce(
430
- (memo, current) => (memo != null && current.length >= memo.length ? memo : current), null
431
- );
432
-
433
- return minLengthPivot.map((_, index) => {
434
- const xValues = joinDateRange
435
- ? [pivots.map((pivot) => pivot[index] && pivot[index].xValues || []).join(', ')]
436
- : minLengthPivot[index].xValues;
437
-
438
- return {
439
- xValues,
440
- yValuesArray: unnest(pivots.map((pivot) => pivot[index].yValuesArray))
441
- };
442
- });
443
- }
444
-
445
- pivotedRows(pivotConfig) { // TODO
446
- return this.chartPivot(pivotConfig);
447
- }
448
-
449
- chartPivot(pivotConfig) {
450
- const validate = (value) => {
451
- if (this.parseDateMeasures && LocalDateRegex.test(value)) {
452
- return new Date(value);
453
- } else if (!Number.isNaN(Number.parseFloat(value))) {
454
- return Number.parseFloat(value);
455
- }
456
-
457
- return value;
458
- };
459
-
460
- const duplicateMeasures = new Set();
461
- if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
462
- const allMeasures = flatten(this.loadResponses.map(({ query }) => query.measures));
463
- allMeasures.filter((e, i, a) => a.indexOf(e) !== i).forEach(m => duplicateMeasures.add(m));
464
- }
465
-
466
- return this.pivot(pivotConfig).map(({ xValues, yValuesArray }) => {
467
- const yValuesMap = {};
468
-
469
- yValuesArray
470
- .forEach(([yValues, m], i) => {
471
- yValuesMap[this.axisValuesString(aliasSeries(yValues, i, pivotConfig, duplicateMeasures), ',')] = m && validate(m);
472
- });
473
-
474
- return ({
475
- x: this.axisValuesString(xValues, ','),
476
- xValues,
477
- ...yValuesMap
478
- });
479
- });
480
- }
481
-
482
- tablePivot(pivotConfig) {
483
- const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
484
- const isMeasuresPresent = normalizedPivotConfig.x.concat(normalizedPivotConfig.y).includes('measures');
485
-
486
- return this.pivot(normalizedPivotConfig).map(({ xValues, yValuesArray }) => fromPairs(
487
- normalizedPivotConfig.x
488
- .map((key, index) => [key, xValues[index]])
489
- .concat(
490
- isMeasuresPresent ? yValuesArray.map(([yValues, measure]) => [
491
- yValues.length ? yValues.join() : 'value',
492
- measure
493
- ]) : []
494
- )
495
- ));
496
- }
497
-
498
- tableColumns(pivotConfig) {
499
- const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
500
- const annotations = pipe(
501
- pluck('annotation'),
502
- reduce(mergeDeepLeft(), {})
503
- )(this.loadResponses);
504
- const flatMeta = Object.values(annotations).reduce((a, b) => ({ ...a, ...b }), {});
505
- const schema = {};
506
-
507
- const extractFields = (key) => {
508
- const { title, shortTitle, type, format, meta } = flatMeta[key] || {};
509
-
510
- return {
511
- key,
512
- title,
513
- shortTitle,
514
- type,
515
- format,
516
- meta
517
- };
518
- };
519
-
520
- const pivot = this.pivot(normalizedPivotConfig);
521
-
522
- (pivot[0] && pivot[0].yValuesArray || []).forEach(([yValues]) => {
523
- if (yValues.length > 0) {
524
- let currentItem = schema;
525
-
526
- yValues.forEach((value, index) => {
527
- currentItem[`_${value}`] = {
528
- key: value,
529
- memberId: normalizedPivotConfig.y[index] === 'measures'
530
- ? value
531
- : normalizedPivotConfig.y[index],
532
- children: (currentItem[`_${value}`] && currentItem[`_${value}`].children) || {}
533
- };
534
-
535
- currentItem = currentItem[`_${value}`].children;
536
- });
537
- }
538
- });
539
-
540
- const toColumns = (item = {}, path = []) => {
541
- if (Object.keys(item).length === 0) {
542
- return [];
543
- }
544
-
545
- return Object.values(item).map(({ key, ...currentItem }) => {
546
- const children = toColumns(currentItem.children, [
547
- ...path,
548
- key
549
- ]);
550
-
551
- const { title, shortTitle, ...fields } = extractFields(currentItem.memberId);
552
-
553
- const dimensionValue = key !== currentItem.memberId || title == null ? key : '';
554
-
555
- if (!children.length) {
556
- return {
557
- ...fields,
558
- key,
559
- dataIndex: [...path, key].join(),
560
- title: [title, dimensionValue].join(' ').trim(),
561
- shortTitle: dimensionValue || shortTitle,
562
- };
563
- }
564
-
565
- return {
566
- ...fields,
567
- key,
568
- title: [title, dimensionValue].join(' ').trim(),
569
- shortTitle: dimensionValue || shortTitle,
570
- children,
571
- };
572
- });
573
- };
574
-
575
- let otherColumns = [];
576
-
577
- if (!pivot.length && normalizedPivotConfig.y.includes('measures')) {
578
- otherColumns = (this.loadResponses[0].query.measures || []).map(
579
- (key) => ({ ...extractFields(key), dataIndex: key })
580
- );
581
- }
582
-
583
- // Syntatic column to display the measure value
584
- if (!normalizedPivotConfig.y.length && normalizedPivotConfig.x.includes('measures')) {
585
- otherColumns.push({
586
- key: 'value',
587
- dataIndex: 'value',
588
- title: 'Value',
589
- shortTitle: 'Value',
590
- type: 'string',
591
- });
592
- }
593
-
594
- return normalizedPivotConfig.x
595
- .map((key) => {
596
- if (key === 'measures') {
597
- return {
598
- key: 'measures',
599
- dataIndex: 'measures',
600
- title: 'Measures',
601
- shortTitle: 'Measures',
602
- type: 'string',
603
- };
604
- }
605
-
606
- return ({ ...extractFields(key), dataIndex: key });
607
- })
608
- .concat(toColumns(schema))
609
- .concat(otherColumns);
610
- }
611
-
612
- totalRow(pivotConfig) {
613
- return this.chartPivot(pivotConfig)[0];
614
- }
615
-
616
- categories(pivotConfig) { // TODO
617
- return this.chartPivot(pivotConfig);
618
- }
619
-
620
- seriesNames(pivotConfig) {
621
- pivotConfig = this.normalizePivotConfig(pivotConfig);
622
- const measures = pipe(
623
- pluck('annotation'),
624
- pluck('measures'),
625
- mergeAll
626
- )(this.loadResponses);
627
-
628
- const seriesNames = unnest(this.loadResponses.map((_, index) => pipe(
629
- map(this.axisValues(pivotConfig.y, index)),
630
- unnest,
631
- uniq
632
- )(
633
- this.timeDimensionBackwardCompatibleData(index)
634
- )));
635
- const duplicateMeasures = new Set();
636
- if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
637
- const allMeasures = flatten(this.loadResponses.map(({ query }) => query.measures));
638
- allMeasures.filter((e, i, a) => a.indexOf(e) !== i).forEach(m => duplicateMeasures.add(m));
639
- }
640
-
641
- return seriesNames.map((axisValues, i) => {
642
- const aliasedAxis = aliasSeries(axisValues, i, pivotConfig, duplicateMeasures);
643
- return {
644
- title: this.axisValuesString(
645
- pivotConfig.y.find(d => d === 'measures') ?
646
- dropLast(1, aliasedAxis).concat(
647
- measures[
648
- ResultSet.measureFromAxis(axisValues)
649
- ].title
650
- ) :
651
- aliasedAxis, ', '
652
- ),
653
- shortTitle: this.axisValuesString(
654
- pivotConfig.y.find(d => d === 'measures') ?
655
- dropLast(1, aliasedAxis).concat(
656
- measures[
657
- ResultSet.measureFromAxis(axisValues)
658
- ].shortTitle
659
- ) :
660
- aliasedAxis, ', '
661
- ),
662
- key: this.axisValuesString(aliasedAxis, ','),
663
- yValues: axisValues
664
- };
665
- });
666
- }
667
-
668
- query() {
669
- if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
670
- throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
671
- }
672
-
673
- return this.loadResponses[0].query;
674
- }
675
-
676
- pivotQuery() {
677
- return this.loadResponse.pivotQuery || null;
678
- }
679
-
680
- totalRows() {
681
- return this.loadResponses[0].total;
682
- }
683
-
684
- rawData() {
685
- if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
686
- throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
687
- }
688
-
689
- return this.loadResponses[0].data;
690
- }
691
-
692
- annotation() {
693
- if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
694
- throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
695
- }
696
-
697
- return this.loadResponses[0].annotation;
698
- }
699
-
700
- timeDimensionBackwardCompatibleData(resultIndex) {
701
- if (resultIndex === undefined) {
702
- throw new Error('resultIndex is required');
703
- }
704
-
705
- if (!this.backwardCompatibleData[resultIndex]) {
706
- const { data, query } = this.loadResponses[resultIndex];
707
- const timeDimensions = (query.timeDimensions || []).filter(td => Boolean(td.granularity));
708
-
709
- this.backwardCompatibleData[resultIndex] = data.map(row => (
710
- {
711
- ...row,
712
- ...(
713
- fromPairs(Object.keys(row)
714
- .filter(
715
- field => timeDimensions.find(d => d.dimension === field) &&
716
- !row[ResultSet.timeDimensionMember(timeDimensions.find(d => d.dimension === field))]
717
- ).map(field => (
718
- [ResultSet.timeDimensionMember(timeDimensions.find(d => d.dimension === field)), row[field]]
719
- )))
720
- )
721
- }
722
- ));
723
- }
724
-
725
- return this.backwardCompatibleData[resultIndex];
726
- }
727
-
728
- decompose() {
729
- return this.loadResponses.map((result) => new ResultSet({
730
- queryType: QUERY_TYPE.REGULAR_QUERY,
731
- pivotQuery: {
732
- ...result.query,
733
- queryType: QUERY_TYPE.REGULAR_QUERY,
734
- },
735
- results: [result]
736
- }, this.options));
737
- }
738
-
739
- serialize() {
740
- return {
741
- loadResponse: clone(this.loadResponse)
742
- };
743
- }
744
- }
745
-
746
- export default ResultSet;