@cubejs-client/core 0.35.0 → 0.36.0

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.
@@ -43,7 +43,6 @@ function removeEmptyQueryFields(_query) {
43
43
  return null;
44
44
  }
45
45
  }
46
-
47
46
  if (key === 'order' && value) {
48
47
  if (Array.isArray(value) && !value.length) {
49
48
  return null;
@@ -51,13 +50,13 @@ function removeEmptyQueryFields(_query) {
51
50
  return null;
52
51
  }
53
52
  }
54
-
55
53
  return [key, value];
56
54
  }).filter(Boolean));
57
55
  }
58
56
  function validateQuery(_query) {
59
57
  const query = _query || {};
60
- return removeEmptyQueryFields({ ...query,
58
+ return removeEmptyQueryFields({
59
+ ...query,
61
60
  filters: (query.filters || []).filter(f => f.operator),
62
61
  timeDimensions: (query.timeDimensions || []).filter(td => !(!td.dateRange && !td.granularity))
63
62
  });
@@ -67,7 +66,6 @@ function areQueriesEqual(query1 = {}, query2 = {}) {
67
66
  }
68
67
  function defaultOrder(query) {
69
68
  const granularity = (query.timeDimensions || []).find(d => d.granularity);
70
-
71
69
  if (granularity) {
72
70
  return {
73
71
  [granularity.dimension]: 'asc'
@@ -81,7 +79,6 @@ function defaultOrder(query) {
81
79
  [query.dimensions[0]]: 'asc'
82
80
  };
83
81
  }
84
-
85
82
  return {};
86
83
  }
87
84
  function defaultHeuristics(newState, oldQuery = {}, options) {
@@ -99,130 +96,134 @@ function defaultHeuristics(newState, oldQuery = {}, options) {
99
96
  ...props
100
97
  };
101
98
  let newQuery = null;
102
-
103
99
  if (!areQueriesEqual(query, oldQuery)) {
104
100
  newQuery = query;
105
101
  }
106
-
107
102
  if (Array.isArray(newQuery) || Array.isArray(oldQuery)) {
108
103
  return newState;
109
104
  }
110
-
111
105
  if (newQuery) {
112
106
  if ((oldQuery.timeDimensions || []).length === 1 && (newQuery.timeDimensions || []).length === 1 && newQuery.timeDimensions[0].granularity && oldQuery.timeDimensions[0].granularity !== newQuery.timeDimensions[0].granularity) {
113
- state = { ...state,
107
+ state = {
108
+ ...state,
114
109
  sessionGranularity: newQuery.timeDimensions[0].granularity
115
110
  };
116
111
  }
117
-
118
112
  if ((oldQuery.measures || []).length === 0 && (newQuery.measures || []).length > 0 || (oldQuery.measures || []).length === 1 && (newQuery.measures || []).length === 1 && oldQuery.measures[0] !== newQuery.measures[0]) {
119
113
  const [td] = newQuery.timeDimensions || [];
120
114
  const defaultTimeDimension = meta.defaultTimeDimensionNameFor(newQuery.measures[0]);
121
- newQuery = { ...newQuery,
115
+ newQuery = {
116
+ ...newQuery,
122
117
  timeDimensions: defaultTimeDimension ? [{
123
118
  dimension: defaultTimeDimension,
124
119
  granularity: td && td.granularity || granularity,
125
120
  dateRange: td && td.dateRange
126
121
  }] : []
127
122
  };
128
- return { ...state,
123
+ return {
124
+ ...state,
129
125
  pivotConfig: null,
130
126
  shouldApplyHeuristicOrder: true,
131
127
  query: newQuery,
132
128
  chartType: defaultTimeDimension ? 'line' : 'number'
133
129
  };
134
130
  }
135
-
136
131
  if ((oldQuery.dimensions || []).length === 0 && (newQuery.dimensions || []).length > 0) {
137
- newQuery = { ...newQuery,
138
- timeDimensions: (newQuery.timeDimensions || []).map(td => ({ ...td,
132
+ newQuery = {
133
+ ...newQuery,
134
+ timeDimensions: (newQuery.timeDimensions || []).map(td => ({
135
+ ...td,
139
136
  granularity: undefined
140
137
  }))
141
138
  };
142
- return { ...state,
139
+ return {
140
+ ...state,
143
141
  pivotConfig: null,
144
142
  shouldApplyHeuristicOrder: true,
145
143
  query: newQuery,
146
144
  chartType: 'table'
147
145
  };
148
146
  }
149
-
150
147
  if ((oldQuery.dimensions || []).length > 0 && (newQuery.dimensions || []).length === 0) {
151
- newQuery = { ...newQuery,
152
- timeDimensions: (newQuery.timeDimensions || []).map(td => ({ ...td,
148
+ newQuery = {
149
+ ...newQuery,
150
+ timeDimensions: (newQuery.timeDimensions || []).map(td => ({
151
+ ...td,
153
152
  granularity: td.granularity || granularity
154
153
  }))
155
154
  };
156
- return { ...state,
155
+ return {
156
+ ...state,
157
157
  pivotConfig: null,
158
158
  shouldApplyHeuristicOrder: true,
159
159
  query: newQuery,
160
160
  chartType: (newQuery.timeDimensions || []).length ? 'line' : 'number'
161
161
  };
162
162
  }
163
-
164
163
  if (((oldQuery.dimensions || []).length > 0 || (oldQuery.measures || []).length > 0) && (newQuery.dimensions || []).length === 0 && (newQuery.measures || []).length === 0) {
165
- newQuery = { ...newQuery,
164
+ newQuery = {
165
+ ...newQuery,
166
166
  timeDimensions: [],
167
167
  filters: []
168
168
  };
169
- return { ...state,
169
+ return {
170
+ ...state,
170
171
  pivotConfig: null,
171
172
  shouldApplyHeuristicOrder: true,
172
173
  query: newQuery,
173
174
  sessionGranularity: null
174
175
  };
175
176
  }
176
-
177
177
  return state;
178
178
  }
179
-
180
179
  if (state.chartType) {
181
180
  const newChartType = state.chartType;
182
-
183
181
  if ((newChartType === 'line' || newChartType === 'area') && (oldQuery.timeDimensions || []).length === 1 && !oldQuery.timeDimensions[0].granularity) {
184
182
  const [td] = oldQuery.timeDimensions;
185
- return { ...state,
183
+ return {
184
+ ...state,
186
185
  pivotConfig: null,
187
- query: { ...oldQuery,
188
- timeDimensions: [{ ...td,
186
+ query: {
187
+ ...oldQuery,
188
+ timeDimensions: [{
189
+ ...td,
189
190
  granularity
190
191
  }]
191
192
  }
192
193
  };
193
194
  }
194
-
195
195
  if ((newChartType === 'pie' || newChartType === 'table' || newChartType === 'number') && (oldQuery.timeDimensions || []).length === 1 && oldQuery.timeDimensions[0].granularity) {
196
196
  const [td] = oldQuery.timeDimensions;
197
- return { ...state,
197
+ return {
198
+ ...state,
198
199
  pivotConfig: null,
199
200
  shouldApplyHeuristicOrder: true,
200
- query: { ...oldQuery,
201
- timeDimensions: [{ ...td,
201
+ query: {
202
+ ...oldQuery,
203
+ timeDimensions: [{
204
+ ...td,
202
205
  granularity: undefined
203
206
  }]
204
207
  }
205
208
  };
206
209
  }
207
210
  }
208
-
209
211
  return state;
210
212
  }
211
213
  function isQueryPresent(query) {
212
214
  if (!query) {
213
215
  return false;
214
216
  }
215
-
216
217
  return (Array.isArray(query) ? query : [query]).every(q => q.measures && q.measures.length || q.dimensions && q.dimensions.length || q.timeDimensions && q.timeDimensions.length);
217
218
  }
218
219
  function movePivotItem(pivotConfig, sourceIndex, destinationIndex, sourceAxis, destinationAxis) {
219
- const nextPivotConfig = { ...pivotConfig,
220
+ const nextPivotConfig = {
221
+ ...pivotConfig,
220
222
  x: [...pivotConfig.x],
221
223
  y: [...pivotConfig.y]
222
224
  };
223
225
  const id = pivotConfig[sourceAxis][sourceIndex];
224
226
  const lastIndex = nextPivotConfig[destinationAxis].length - 1;
225
-
226
227
  if (id === 'measures') {
227
228
  destinationIndex = lastIndex + 1;
228
229
  } else if (sourceAxis === destinationAxis && destinationIndex >= lastIndex && nextPivotConfig[destinationAxis][lastIndex] === 'measures') {
@@ -230,7 +231,6 @@ function movePivotItem(pivotConfig, sourceIndex, destinationIndex, sourceAxis, d
230
231
  } else if (sourceAxis !== destinationAxis && destinationIndex > lastIndex && nextPivotConfig[destinationAxis][lastIndex] === 'measures') {
231
232
  destinationIndex = lastIndex;
232
233
  }
233
-
234
234
  nextPivotConfig[sourceAxis].splice(sourceIndex, 1);
235
235
  nextPivotConfig[destinationAxis].splice(destinationIndex, 0, id);
236
236
  return nextPivotConfig;
@@ -246,7 +246,6 @@ function flattenFilters(filters = []) {
246
246
  if (filter.or || filter.and) {
247
247
  return [...memo, ...flattenFilters(filter.or || filter.and)];
248
248
  }
249
-
250
249
  return [...memo, filter];
251
250
  }, []);
252
251
  }
@@ -266,14 +265,16 @@ function getOrderMembersFromOrder(orderMembers, order) {
266
265
  entries.forEach(([memberId, currentOrder]) => {
267
266
  if (currentOrder !== 'none' && indexedOrderMembers[memberId]) {
268
267
  ids.add(memberId);
269
- nextOrderMembers.push({ ...indexedOrderMembers[memberId],
268
+ nextOrderMembers.push({
269
+ ...indexedOrderMembers[memberId],
270
270
  order: currentOrder
271
271
  });
272
272
  }
273
273
  });
274
274
  orderMembers.forEach(member => {
275
275
  if (!ids.has(member.id)) {
276
- nextOrderMembers.push({ ...member,
276
+ nextOrderMembers.push({
277
+ ...member,
277
278
  order: member.order || 'none'
278
279
  });
279
280
  }
@@ -282,23 +283,22 @@ function getOrderMembersFromOrder(orderMembers, order) {
282
283
  }
283
284
  function aliasSeries(values, index, pivotConfig, duplicateMeasures) {
284
285
  const nonNullValues = values.filter(value => value != null);
285
-
286
286
  if (pivotConfig && pivotConfig.aliasSeries && pivotConfig.aliasSeries[index]) {
287
287
  return [pivotConfig.aliasSeries[index], ...nonNullValues];
288
288
  } else if (duplicateMeasures.has(nonNullValues[0])) {
289
289
  return [index, ...nonNullValues];
290
290
  }
291
-
292
291
  return nonNullValues;
293
292
  }
294
293
 
295
- dayjs.extend(quarterOfYear); // When granularity is week, weekStart Value must be 1. However, since the client can change it globally (https://day.js.org/docs/en/i18n/changing-locale)
296
- // So the function below has been added.
294
+ dayjs.extend(quarterOfYear);
297
295
 
298
- const internalDayjs = (...args) => dayjs(...args).locale({ ...en,
296
+ // When granularity is week, weekStart Value must be 1. However, since the client can change it globally (https://day.js.org/docs/en/i18n/changing-locale)
297
+ // So the function below has been added.
298
+ const internalDayjs = (...args) => dayjs(...args).locale({
299
+ ...en,
299
300
  weekStart: 1
300
301
  });
301
-
302
302
  const TIME_SERIES = {
303
303
  day: range => range.by('d').map(d => d.format('YYYY-MM-DDT00:00:00.000')),
304
304
  month: range => range.snapTo('month').by('M').map(d => d.format('YYYY-MM-01T00:00:00.000')),
@@ -311,23 +311,19 @@ const TIME_SERIES = {
311
311
  };
312
312
  const DateRegex = /^\d\d\d\d-\d\d-\d\d$/;
313
313
  const LocalDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z?$/;
314
-
315
314
  const groupByToPairs = keyFn => {
316
315
  const acc = new Map();
317
316
  return data => {
318
317
  data.forEach(row => {
319
318
  const key = keyFn(row);
320
-
321
319
  if (!acc.has(key)) {
322
320
  acc.set(key, []);
323
321
  }
324
-
325
322
  acc.get(key).push(row);
326
323
  });
327
324
  return Array.from(acc.entries());
328
325
  };
329
326
  };
330
-
331
327
  const unnest = arr => {
332
328
  const res = [];
333
329
  arr.forEach(subArr => {
@@ -335,18 +331,15 @@ const unnest = arr => {
335
331
  });
336
332
  return res;
337
333
  };
338
-
339
334
  const dayRange = (from, to) => ({
340
335
  by: value => {
341
336
  const results = [];
342
337
  let start = internalDayjs(from);
343
338
  const end = internalDayjs(to);
344
-
345
339
  while (start.isBefore(end) || start.isSame(end)) {
346
340
  results.push(start);
347
341
  start = start.add(1, value);
348
342
  }
349
-
350
343
  return results;
351
344
  },
352
345
  snapTo: value => dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value)),
@@ -358,52 +351,43 @@ const QUERY_TYPE = {
358
351
  COMPARE_DATE_RANGE_QUERY: 'compareDateRangeQuery',
359
352
  BLENDING_QUERY: 'blendingQuery'
360
353
  };
361
-
362
354
  class ResultSet {
363
355
  static measureFromAxis(axisValues) {
364
356
  return axisValues[axisValues.length - 1];
365
357
  }
366
-
367
358
  static timeDimensionMember(td) {
368
359
  return `${td.dimension}.${td.granularity}`;
369
360
  }
370
-
371
361
  static deserialize(data, options = {}) {
372
362
  return new ResultSet(data.loadResponse, options);
373
363
  }
374
-
375
364
  constructor(loadResponse, options = {}) {
376
365
  this.loadResponse = loadResponse;
377
-
378
366
  if (this.loadResponse.queryType != null) {
379
367
  this.queryType = loadResponse.queryType;
380
368
  this.loadResponses = loadResponse.results;
381
369
  } else {
382
370
  this.queryType = QUERY_TYPE.REGULAR_QUERY;
383
- this.loadResponse.pivotQuery = { ...loadResponse.query,
371
+ this.loadResponse.pivotQuery = {
372
+ ...loadResponse.query,
384
373
  queryType: this.queryType
385
374
  };
386
375
  this.loadResponses = [loadResponse];
387
376
  }
388
-
389
377
  if (!Object.values(QUERY_TYPE).includes(this.queryType)) {
390
378
  throw new Error('Unknown query type');
391
379
  }
392
-
393
380
  this.parseDateMeasures = options.parseDateMeasures;
394
381
  this.options = options;
395
382
  this.backwardCompatibleData = [];
396
383
  }
397
-
398
384
  drillDown(drillDownLocator, pivotConfig) {
399
385
  if (this.queryType === QUERY_TYPE.COMPARE_DATE_RANGE_QUERY) {
400
386
  throw new Error('compareDateRange drillDown query is not currently supported');
401
387
  }
402
-
403
388
  if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
404
389
  throw new Error('Data blending drillDown query is not currently supported');
405
390
  }
406
-
407
391
  const {
408
392
  query
409
393
  } = this.loadResponses[0];
@@ -423,15 +407,12 @@ class ResultSet {
423
407
  measures
424
408
  } = this.loadResponses[0].annotation;
425
409
  let [, measureName] = values.find(([member]) => member === 'measures') || [];
426
-
427
410
  if (measureName === undefined) {
428
411
  [measureName] = Object.keys(measures);
429
412
  }
430
-
431
413
  if (!(measures[measureName] && measures[measureName].drillMembers || []).length) {
432
414
  return null;
433
415
  }
434
-
435
416
  const filters = [{
436
417
  member: measureName,
437
418
  operator: 'measureFilter'
@@ -439,17 +420,14 @@ class ResultSet {
439
420
  const timeDimensions = [];
440
421
  values.filter(([member]) => member !== 'measures').forEach(([member, value]) => {
441
422
  const [cubeName, dimension, granularity] = member.split('.');
442
-
443
423
  if (granularity !== undefined) {
444
424
  const range = dayRange(value, value).snapTo(granularity);
445
425
  const originalTimeDimension = query.timeDimensions.find(td => td.dimension);
446
426
  let dateRange = [range.start, range.end];
447
-
448
427
  if (originalTimeDimension?.dateRange) {
449
428
  const [originalStart, originalEnd] = originalTimeDimension.dateRange;
450
429
  dateRange = [dayjs(originalStart) > range.start ? dayjs(originalStart) : range.start, dayjs(originalEnd) < range.end ? dayjs(originalEnd) : range.end];
451
430
  }
452
-
453
431
  timeDimensions.push({
454
432
  dimension: [cubeName, dimension].join('.'),
455
433
  dateRange: dateRange.map(dt => dt.format('YYYY-MM-DDTHH:mm:ss.SSS'))
@@ -467,12 +445,11 @@ class ResultSet {
467
445
  });
468
446
  }
469
447
  });
470
-
471
448
  if (timeDimensions.length === 0 && query.timeDimensions.length > 0 && query.timeDimensions[0].granularity == null) {
472
449
  timeDimensions.push(query.timeDimensions[0]);
473
450
  }
474
-
475
- return { ...measures[measureName].drillMembersGrouped,
451
+ return {
452
+ ...measures[measureName].drillMembersGrouped,
476
453
  filters,
477
454
  ...(segments.length > 0 ? {
478
455
  segments
@@ -482,7 +459,6 @@ class ResultSet {
482
459
  timezone: query.timezone
483
460
  };
484
461
  }
485
-
486
462
  series(pivotConfig) {
487
463
  return this.seriesNames(pivotConfig).map(({
488
464
  title,
@@ -501,22 +477,18 @@ class ResultSet {
501
477
  }))
502
478
  }));
503
479
  }
504
-
505
480
  axisValues(axis, resultIndex = 0) {
506
481
  const {
507
482
  query
508
483
  } = this.loadResponses[resultIndex];
509
484
  return row => {
510
485
  const value = measure => axis.filter(d => d !== 'measures').map(d => row[d] != null ? row[d] : null).concat(measure ? [measure] : []);
511
-
512
486
  if (axis.find(d => d === 'measures') && (query.measures || []).length) {
513
487
  return query.measures.map(value);
514
488
  }
515
-
516
489
  return [value()];
517
490
  };
518
491
  }
519
-
520
492
  axisValuesString(axisValues, delimiter) {
521
493
  const formatValue = v => {
522
494
  if (v == null) {
@@ -527,10 +499,8 @@ class ResultSet {
527
499
  return v;
528
500
  }
529
501
  };
530
-
531
502
  return axisValues.map(formatValue).join(delimiter || ', ');
532
503
  }
533
-
534
504
  static getNormalizedPivotConfig(query = {}, pivotConfig = null) {
535
505
  const defaultPivotConfig = {
536
506
  x: [],
@@ -551,85 +521,64 @@ class ResultSet {
551
521
  y: []
552
522
  });
553
523
  pivotConfig = mergeDeepLeft(pivotConfig, defaultPivotConfig);
554
-
555
524
  const substituteTimeDimensionMembers = axis => axis.map(subDim => timeDimensions.find(td => td.dimension === subDim) && !dimensions.find(d => d === subDim) ? ResultSet.timeDimensionMember(query.timeDimensions.find(td => td.dimension === subDim)) : subDim);
556
-
557
525
  pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x);
558
526
  pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y);
559
527
  const allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
560
528
  const allDimensions = timeDimensions.map(td => ResultSet.timeDimensionMember(td)).concat(dimensions);
561
-
562
529
  const dimensionFilter = key => allDimensions.includes(key) || key === 'measures';
563
-
564
530
  pivotConfig.x = pivotConfig.x.concat(allDimensions.filter(d => !allIncludedDimensions.includes(d) && d !== 'compareDateRange')).filter(dimensionFilter);
565
531
  pivotConfig.y = pivotConfig.y.filter(dimensionFilter);
566
-
567
532
  if (!pivotConfig.x.concat(pivotConfig.y).find(d => d === 'measures')) {
568
533
  pivotConfig.y.push('measures');
569
534
  }
570
-
571
535
  if (dimensions.includes('compareDateRange') && !pivotConfig.y.concat(pivotConfig.x).includes('compareDateRange')) {
572
536
  pivotConfig.y.unshift('compareDateRange');
573
537
  }
574
-
575
538
  if (!measures.length) {
576
539
  pivotConfig.x = pivotConfig.x.filter(d => d !== 'measures');
577
540
  pivotConfig.y = pivotConfig.y.filter(d => d !== 'measures');
578
541
  }
579
-
580
542
  return pivotConfig;
581
543
  }
582
-
583
544
  normalizePivotConfig(pivotConfig) {
584
545
  return ResultSet.getNormalizedPivotConfig(this.loadResponse.pivotQuery, pivotConfig);
585
546
  }
586
-
587
547
  timeSeries(timeDimension, resultIndex) {
588
548
  if (!timeDimension.granularity) {
589
549
  return null;
590
550
  }
591
-
592
551
  let {
593
552
  dateRange
594
553
  } = timeDimension;
595
-
596
554
  if (!dateRange) {
597
555
  const member = ResultSet.timeDimensionMember(timeDimension);
598
556
  const dates = pipe(map(row => row[member] && internalDayjs(row[member])), filter(Boolean))(this.timeDimensionBackwardCompatibleData(resultIndex));
599
557
  dateRange = dates.length && [reduce(minBy(d => d.toDate()), dates[0], dates), reduce(maxBy(d => d.toDate()), dates[0], dates)] || null;
600
558
  }
601
-
602
559
  if (!dateRange) {
603
560
  return null;
604
561
  }
605
-
606
562
  const padToDay = timeDimension.dateRange ? timeDimension.dateRange.find(d => d.match(DateRegex)) : !['hour', 'minute', 'second'].includes(timeDimension.granularity);
607
563
  const [start, end] = dateRange;
608
564
  const range = dayRange(start, end);
609
-
610
565
  if (!TIME_SERIES[timeDimension.granularity]) {
611
566
  throw new Error(`Unsupported time granularity: ${timeDimension.granularity}`);
612
567
  }
613
-
614
568
  return TIME_SERIES[timeDimension.granularity](padToDay ? range.snapTo('d') : range);
615
569
  }
616
-
617
570
  pivot(pivotConfig) {
618
571
  pivotConfig = this.normalizePivotConfig(pivotConfig);
619
572
  const {
620
573
  pivotQuery: query
621
574
  } = this.loadResponse;
622
-
623
575
  const pivotImpl = (resultIndex = 0) => {
624
576
  let groupByXAxis = groupByToPairs(({
625
577
  xValues
626
578
  }) => this.axisValuesString(xValues));
627
-
628
579
  const measureValue = (row, measure) => row[measure] || 0;
629
-
630
580
  if (pivotConfig.fillMissingDates && pivotConfig.x.length === 1 && equals(pivotConfig.x, (query.timeDimensions || []).filter(td => Boolean(td.granularity)).map(td => ResultSet.timeDimensionMember(td)))) {
631
581
  const series = this.loadResponses.map(loadResponse => this.timeSeries(loadResponse.query.timeDimensions[0], resultIndex));
632
-
633
582
  if (series[0]) {
634
583
  groupByXAxis = rows => {
635
584
  const byXValues = groupBy(({
@@ -642,7 +591,6 @@ class ResultSet {
642
591
  };
643
592
  }
644
593
  }
645
-
646
594
  const xGrouped = pipe(map(row => this.axisValues(pivotConfig.x, resultIndex)(row).map(xValues => ({
647
595
  xValues,
648
596
  row
@@ -688,11 +636,9 @@ class ResultSet {
688
636
  };
689
637
  });
690
638
  };
691
-
692
639
  const pivots = this.loadResponses.length > 1 ? this.loadResponses.map((_, index) => pivotImpl(index)) : [];
693
640
  return pivots.length ? this.mergePivots(pivots, pivotConfig.joinDateRange) : pivotImpl();
694
641
  }
695
-
696
642
  mergePivots(pivots, joinDateRange) {
697
643
  const minLengthPivot = pivots.reduce((memo, current) => memo != null && current.length >= memo.length ? memo : current, null);
698
644
  return minLengthPivot.map((_, index) => {
@@ -703,12 +649,10 @@ class ResultSet {
703
649
  };
704
650
  });
705
651
  }
706
-
707
652
  pivotedRows(pivotConfig) {
708
653
  // TODO
709
654
  return this.chartPivot(pivotConfig);
710
655
  }
711
-
712
656
  chartPivot(pivotConfig) {
713
657
  const validate = value => {
714
658
  if (this.parseDateMeasures && LocalDateRegex.test(value)) {
@@ -716,19 +660,15 @@ class ResultSet {
716
660
  } else if (!Number.isNaN(Number.parseFloat(value))) {
717
661
  return Number.parseFloat(value);
718
662
  }
719
-
720
663
  return value;
721
664
  };
722
-
723
665
  const duplicateMeasures = new Set();
724
-
725
666
  if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
726
667
  const allMeasures = flatten(this.loadResponses.map(({
727
668
  query
728
669
  }) => query.measures));
729
670
  allMeasures.filter((e, i, a) => a.indexOf(e) !== i).forEach(m => duplicateMeasures.add(m));
730
671
  }
731
-
732
672
  return this.pivot(pivotConfig).map(({
733
673
  xValues,
734
674
  yValuesArray
@@ -744,7 +684,6 @@ class ResultSet {
744
684
  };
745
685
  });
746
686
  }
747
-
748
687
  tablePivot(pivotConfig) {
749
688
  const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
750
689
  const isMeasuresPresent = normalizedPivotConfig.x.concat(normalizedPivotConfig.y).includes('measures');
@@ -753,15 +692,14 @@ class ResultSet {
753
692
  yValuesArray
754
693
  }) => fromPairs(normalizedPivotConfig.x.map((key, index) => [key, xValues[index]]).concat(isMeasuresPresent ? yValuesArray.map(([yValues, measure]) => [yValues.length ? yValues.join() : 'value', measure]) : [])));
755
694
  }
756
-
757
695
  tableColumns(pivotConfig) {
758
696
  const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
759
697
  const annotations = pipe(pluck('annotation'), reduce(mergeDeepLeft(), {}))(this.loadResponses);
760
- const flatMeta = Object.values(annotations).reduce((a, b) => ({ ...a,
698
+ const flatMeta = Object.values(annotations).reduce((a, b) => ({
699
+ ...a,
761
700
  ...b
762
701
  }), {});
763
702
  const schema = {};
764
-
765
703
  const extractFields = key => {
766
704
  const {
767
705
  title,
@@ -779,7 +717,6 @@ class ResultSet {
779
717
  meta
780
718
  };
781
719
  };
782
-
783
720
  const pivot = this.pivot(normalizedPivotConfig);
784
721
  (pivot[0] && pivot[0].yValuesArray || []).forEach(([yValues]) => {
785
722
  if (yValues.length > 0) {
@@ -794,12 +731,10 @@ class ResultSet {
794
731
  });
795
732
  }
796
733
  });
797
-
798
734
  const toColumns = (item = {}, path = []) => {
799
735
  if (Object.keys(item).length === 0) {
800
736
  return [];
801
737
  }
802
-
803
738
  return Object.values(item).map(({
804
739
  key,
805
740
  ...currentItem
@@ -811,17 +746,17 @@ class ResultSet {
811
746
  ...fields
812
747
  } = extractFields(currentItem.memberId);
813
748
  const dimensionValue = key !== currentItem.memberId || title == null ? key : '';
814
-
815
749
  if (!children.length) {
816
- return { ...fields,
750
+ return {
751
+ ...fields,
817
752
  key,
818
753
  dataIndex: [...path, key].join(),
819
754
  title: [title, dimensionValue].join(' ').trim(),
820
755
  shortTitle: dimensionValue || shortTitle
821
756
  };
822
757
  }
823
-
824
- return { ...fields,
758
+ return {
759
+ ...fields,
825
760
  key,
826
761
  title: [title, dimensionValue].join(' ').trim(),
827
762
  shortTitle: dimensionValue || shortTitle,
@@ -829,16 +764,15 @@ class ResultSet {
829
764
  };
830
765
  });
831
766
  };
832
-
833
767
  let otherColumns = [];
834
-
835
768
  if (!pivot.length && normalizedPivotConfig.y.includes('measures')) {
836
- otherColumns = (this.loadResponses[0].query.measures || []).map(key => ({ ...extractFields(key),
769
+ otherColumns = (this.loadResponses[0].query.measures || []).map(key => ({
770
+ ...extractFields(key),
837
771
  dataIndex: key
838
772
  }));
839
- } // Syntatic column to display the measure value
840
-
773
+ }
841
774
 
775
+ // Syntatic column to display the measure value
842
776
  if (!normalizedPivotConfig.y.length && normalizedPivotConfig.x.includes('measures')) {
843
777
  otherColumns.push({
844
778
  key: 'value',
@@ -848,7 +782,6 @@ class ResultSet {
848
782
  type: 'string'
849
783
  });
850
784
  }
851
-
852
785
  return normalizedPivotConfig.x.map(key => {
853
786
  if (key === 'measures') {
854
787
  return {
@@ -859,35 +792,30 @@ class ResultSet {
859
792
  type: 'string'
860
793
  };
861
794
  }
862
-
863
- return { ...extractFields(key),
795
+ return {
796
+ ...extractFields(key),
864
797
  dataIndex: key
865
798
  };
866
799
  }).concat(toColumns(schema)).concat(otherColumns);
867
800
  }
868
-
869
801
  totalRow(pivotConfig) {
870
802
  return this.chartPivot(pivotConfig)[0];
871
803
  }
872
-
873
804
  categories(pivotConfig) {
874
805
  // TODO
875
806
  return this.chartPivot(pivotConfig);
876
807
  }
877
-
878
808
  seriesNames(pivotConfig) {
879
809
  pivotConfig = this.normalizePivotConfig(pivotConfig);
880
810
  const measures = pipe(pluck('annotation'), pluck('measures'), mergeAll)(this.loadResponses);
881
811
  const seriesNames = unnest(this.loadResponses.map((_, index) => pipe(map(this.axisValues(pivotConfig.y, index)), unnest, uniq)(this.timeDimensionBackwardCompatibleData(index))));
882
812
  const duplicateMeasures = new Set();
883
-
884
813
  if (this.queryType === QUERY_TYPE.BLENDING_QUERY) {
885
814
  const allMeasures = flatten(this.loadResponses.map(({
886
815
  query
887
816
  }) => query.measures));
888
817
  allMeasures.filter((e, i, a) => a.indexOf(e) !== i).forEach(m => duplicateMeasures.add(m));
889
818
  }
890
-
891
819
  return seriesNames.map((axisValues, i) => {
892
820
  const aliasedAxis = aliasSeries(axisValues, i, pivotConfig, duplicateMeasures);
893
821
  return {
@@ -898,97 +826,80 @@ class ResultSet {
898
826
  };
899
827
  });
900
828
  }
901
-
902
829
  query() {
903
830
  if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
904
831
  throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
905
832
  }
906
-
907
833
  return this.loadResponses[0].query;
908
834
  }
909
-
910
835
  pivotQuery() {
911
836
  return this.loadResponse.pivotQuery || null;
912
837
  }
913
-
914
838
  totalRows() {
915
839
  return this.loadResponses[0].total;
916
840
  }
917
-
918
841
  rawData() {
919
842
  if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
920
843
  throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
921
844
  }
922
-
923
845
  return this.loadResponses[0].data;
924
846
  }
925
-
926
847
  annotation() {
927
848
  if (this.queryType !== QUERY_TYPE.REGULAR_QUERY) {
928
849
  throw new Error(`Method is not supported for a '${this.queryType}' query type. Please use decompose`);
929
850
  }
930
-
931
851
  return this.loadResponses[0].annotation;
932
852
  }
933
-
934
853
  timeDimensionBackwardCompatibleData(resultIndex) {
935
854
  if (resultIndex === undefined) {
936
855
  throw new Error('resultIndex is required');
937
856
  }
938
-
939
857
  if (!this.backwardCompatibleData[resultIndex]) {
940
858
  const {
941
859
  data,
942
860
  query
943
861
  } = this.loadResponses[resultIndex];
944
862
  const timeDimensions = (query.timeDimensions || []).filter(td => Boolean(td.granularity));
945
- this.backwardCompatibleData[resultIndex] = data.map(row => ({ ...row,
863
+ this.backwardCompatibleData[resultIndex] = data.map(row => ({
864
+ ...row,
946
865
  ...fromPairs(Object.keys(row).filter(field => timeDimensions.find(d => d.dimension === field) && !row[ResultSet.timeDimensionMember(timeDimensions.find(d => d.dimension === field))]).map(field => [ResultSet.timeDimensionMember(timeDimensions.find(d => d.dimension === field)), row[field]]))
947
866
  }));
948
867
  }
949
-
950
868
  return this.backwardCompatibleData[resultIndex];
951
869
  }
952
-
953
870
  decompose() {
954
871
  return this.loadResponses.map(result => new ResultSet({
955
872
  queryType: QUERY_TYPE.REGULAR_QUERY,
956
- pivotQuery: { ...result.query,
873
+ pivotQuery: {
874
+ ...result.query,
957
875
  queryType: QUERY_TYPE.REGULAR_QUERY
958
876
  },
959
877
  results: [result]
960
878
  }, this.options));
961
879
  }
962
-
963
880
  serialize() {
964
881
  return {
965
882
  loadResponse: clone(this.loadResponse)
966
883
  };
967
884
  }
968
-
969
885
  }
970
886
 
971
887
  class SqlQuery {
972
888
  constructor(sqlQuery) {
973
889
  this.sqlQuery = sqlQuery;
974
890
  }
975
-
976
891
  rawQuery() {
977
892
  return this.sqlQuery.sql;
978
893
  }
979
-
980
894
  sql() {
981
895
  return this.rawQuery().sql[0];
982
896
  }
983
-
984
897
  }
985
898
 
986
899
  /**
987
900
  * @module @cubejs-client/core
988
901
  */
989
-
990
902
  const memberMap = memberArray => fromPairs(memberArray.map(m => [m.name, m]));
991
-
992
903
  const operators = {
993
904
  string: [{
994
905
  name: 'contains',
@@ -1072,10 +983,10 @@ const operators = {
1072
983
  title: 'before or on date'
1073
984
  }]
1074
985
  };
986
+
1075
987
  /**
1076
988
  * Contains information about available cubes and it's members.
1077
989
  */
1078
-
1079
990
  class Meta {
1080
991
  constructor(metaResponse) {
1081
992
  this.meta = metaResponse;
@@ -1089,21 +1000,17 @@ class Meta {
1089
1000
  segments: memberMap(c.segments)
1090
1001
  }]));
1091
1002
  }
1092
-
1093
1003
  membersForQuery(query, memberType) {
1094
1004
  return unnest$1(this.cubes.map(c => c[memberType])).sort((a, b) => a.title > b.title ? 1 : -1);
1095
1005
  }
1096
-
1097
1006
  membersGroupedByCube() {
1098
1007
  const memberKeys = ['measures', 'dimensions', 'segments', 'timeDimensions'];
1099
1008
  return this.cubes.reduce((memo, cube) => {
1100
1009
  memberKeys.forEach(key => {
1101
1010
  let members = cube[key];
1102
-
1103
1011
  if (key === 'timeDimensions') {
1104
1012
  members = cube.dimensions.filter(m => m.type === 'time');
1105
1013
  }
1106
-
1107
1014
  memo[key] = [...memo[key], {
1108
1015
  cubeName: cube.name,
1109
1016
  cubeTitle: cube.title,
@@ -1120,60 +1027,47 @@ class Meta {
1120
1027
  timeDimensions: []
1121
1028
  });
1122
1029
  }
1123
-
1124
1030
  resolveMember(memberName, memberType) {
1125
1031
  const [cube] = memberName.split('.');
1126
-
1127
1032
  if (!this.cubesMap[cube]) {
1128
1033
  return {
1129
1034
  title: memberName,
1130
1035
  error: `Cube not found ${cube} for path '${memberName}'`
1131
1036
  };
1132
1037
  }
1133
-
1134
1038
  const memberTypes = Array.isArray(memberType) ? memberType : [memberType];
1135
1039
  const member = memberTypes.map(type => this.cubesMap[cube][type] && this.cubesMap[cube][type][memberName]).find(m => m);
1136
-
1137
1040
  if (!member) {
1138
1041
  return {
1139
1042
  title: memberName,
1140
1043
  error: `Path not found '${memberName}'`
1141
1044
  };
1142
1045
  }
1143
-
1144
1046
  return member;
1145
1047
  }
1146
-
1147
1048
  defaultTimeDimensionNameFor(memberName) {
1148
1049
  const [cube] = memberName.split('.');
1149
-
1150
1050
  if (!this.cubesMap[cube]) {
1151
1051
  return null;
1152
1052
  }
1153
-
1154
1053
  return Object.keys(this.cubesMap[cube].dimensions || {}).find(d => this.cubesMap[cube].dimensions[d].type === 'time');
1155
1054
  }
1156
-
1157
1055
  filterOperatorsForMember(memberName, memberType) {
1158
1056
  const member = this.resolveMember(memberName, memberType);
1159
1057
  return operators[member.type] || operators.string;
1160
1058
  }
1161
-
1162
1059
  }
1163
1060
 
1164
1061
  class ProgressResult {
1165
1062
  constructor(progressResponse) {
1166
1063
  this.progressResponse = progressResponse;
1167
1064
  }
1168
-
1169
1065
  stage() {
1170
1066
  return this.progressResponse.stage;
1171
1067
  }
1172
-
1173
1068
  timeElapsed() {
1174
1069
  return this.progressResponse.timeElapsed;
1175
1070
  }
1176
-
1177
1071
  }
1178
1072
 
1179
1073
  class HttpTransport {
@@ -1190,7 +1084,6 @@ class HttpTransport {
1190
1084
  this.headers = headers;
1191
1085
  this.credentials = credentials;
1192
1086
  }
1193
-
1194
1087
  request(method, {
1195
1088
  baseRequestId,
1196
1089
  ...params
@@ -1198,19 +1091,19 @@ class HttpTransport {
1198
1091
  let spanCounter = 1;
1199
1092
  const searchParams = new URLSearchParams(params && Object.keys(params).map(k => ({
1200
1093
  [k]: typeof params[k] === 'object' ? JSON.stringify(params[k]) : params[k]
1201
- })).reduce((a, b) => ({ ...a,
1094
+ })).reduce((a, b) => ({
1095
+ ...a,
1202
1096
  ...b
1203
1097
  }), {}));
1204
1098
  let url = `${this.apiUrl}/${method}${searchParams.toString().length ? `?${searchParams}` : ''}`;
1205
1099
  const requestMethod = this.method || (url.length < 2000 ? 'GET' : 'POST');
1206
-
1207
1100
  if (requestMethod === 'POST') {
1208
1101
  url = `${this.apiUrl}/${method}`;
1209
1102
  this.headers['Content-Type'] = 'application/json';
1210
- } // Currently, all methods make GET requests. If a method makes a request with a body payload,
1211
- // remember to add {'Content-Type': 'application/json'} to the header.
1212
-
1103
+ }
1213
1104
 
1105
+ // Currently, all methods make GET requests. If a method makes a request with a body payload,
1106
+ // remember to add {'Content-Type': 'application/json'} to the header.
1214
1107
  const runRequest = () => fetch(url, {
1215
1108
  method: requestMethod,
1216
1109
  headers: {
@@ -1221,25 +1114,20 @@ class HttpTransport {
1221
1114
  credentials: this.credentials,
1222
1115
  body: requestMethod === 'POST' ? JSON.stringify(params) : null
1223
1116
  });
1224
-
1225
1117
  return {
1226
1118
  /* eslint no-unsafe-finally: off */
1227
1119
  async subscribe(callback) {
1228
1120
  let result = {
1229
1121
  error: 'network Error' // add default error message
1230
-
1231
1122
  };
1232
-
1233
1123
  try {
1234
1124
  result = await runRequest();
1235
1125
  } finally {
1236
1126
  return callback(result, () => this.subscribe(callback));
1237
1127
  }
1238
1128
  }
1239
-
1240
1129
  };
1241
1130
  }
1242
-
1243
1131
  }
1244
1132
 
1245
1133
  class RequestError extends Error {
@@ -1248,20 +1136,18 @@ class RequestError extends Error {
1248
1136
  this.response = response;
1249
1137
  this.status = status;
1250
1138
  }
1251
-
1252
1139
  }
1253
1140
 
1254
1141
  let mutexCounter = 0;
1255
1142
  const MUTEX_ERROR = 'Mutex has been changed';
1143
+
1256
1144
  /**
1257
1145
  * Query result dataset formats enum.
1258
1146
  */
1259
-
1260
1147
  const ResultType = {
1261
1148
  DEFAULT: 'default',
1262
1149
  COMPACT: 'compact'
1263
1150
  };
1264
-
1265
1151
  function mutexPromise(promise) {
1266
1152
  return new Promise(async (resolve, reject) => {
1267
1153
  try {
@@ -1273,20 +1159,16 @@ function mutexPromise(promise) {
1273
1159
  }
1274
1160
  });
1275
1161
  }
1276
-
1277
1162
  class CubeApi {
1278
1163
  constructor(apiToken, options) {
1279
1164
  if (apiToken !== null && !Array.isArray(apiToken) && typeof apiToken === 'object') {
1280
1165
  options = apiToken;
1281
1166
  apiToken = undefined;
1282
1167
  }
1283
-
1284
1168
  options = options || {};
1285
-
1286
1169
  if (!options.transport && !options.apiUrl) {
1287
1170
  throw new Error('The `apiUrl` option is required');
1288
1171
  }
1289
-
1290
1172
  this.apiToken = apiToken;
1291
1173
  this.apiUrl = options.apiUrl;
1292
1174
  this.method = options.method;
@@ -1301,52 +1183,41 @@ class CubeApi {
1301
1183
  });
1302
1184
  this.pollInterval = options.pollInterval || 5;
1303
1185
  this.parseDateMeasures = options.parseDateMeasures;
1186
+ this.castNumerics = typeof options.castNumerics === 'boolean' ? options.castNumerics : false;
1304
1187
  this.updateAuthorizationPromise = null;
1305
1188
  }
1306
-
1307
1189
  request(method, params) {
1308
1190
  return this.transport.request(method, {
1309
1191
  baseRequestId: v4(),
1310
1192
  ...params
1311
1193
  });
1312
1194
  }
1313
-
1314
1195
  loadMethod(request, toResult, options, callback) {
1315
1196
  const mutexValue = ++mutexCounter;
1316
-
1317
1197
  if (typeof options === 'function' && !callback) {
1318
1198
  callback = options;
1319
1199
  options = undefined;
1320
1200
  }
1321
-
1322
1201
  options = options || {};
1323
1202
  const mutexKey = options.mutexKey || 'default';
1324
-
1325
1203
  if (options.mutexObj) {
1326
1204
  options.mutexObj[mutexKey] = mutexValue;
1327
1205
  }
1328
-
1329
1206
  const requestPromise = this.updateTransportAuthorization().then(() => request());
1330
1207
  let skipAuthorizationUpdate = true;
1331
1208
  let unsubscribed = false;
1332
-
1333
1209
  const checkMutex = async () => {
1334
1210
  const requestInstance = await requestPromise;
1335
-
1336
1211
  if (options.mutexObj && options.mutexObj[mutexKey] !== mutexValue) {
1337
1212
  unsubscribed = true;
1338
-
1339
1213
  if (requestInstance.unsubscribe) {
1340
1214
  await requestInstance.unsubscribe();
1341
1215
  }
1342
-
1343
1216
  throw MUTEX_ERROR;
1344
1217
  }
1345
1218
  };
1346
-
1347
1219
  const loadImpl = async (response, next) => {
1348
1220
  const requestInstance = await requestPromise;
1349
-
1350
1221
  const subscribeNext = async () => {
1351
1222
  if (options.subscribe && !unsubscribed) {
1352
1223
  if (requestInstance.unsubscribe) {
@@ -1356,100 +1227,74 @@ class CubeApi {
1356
1227
  return next();
1357
1228
  }
1358
1229
  }
1359
-
1360
1230
  return null;
1361
1231
  };
1362
-
1363
1232
  const continueWait = async wait => {
1364
1233
  if (!unsubscribed) {
1365
1234
  if (wait) {
1366
1235
  await new Promise(resolve => setTimeout(() => resolve(), this.pollInterval * 1000));
1367
1236
  }
1368
-
1369
1237
  return next();
1370
1238
  }
1371
-
1372
1239
  return null;
1373
1240
  };
1374
-
1375
1241
  if (options.subscribe && !skipAuthorizationUpdate) {
1376
1242
  await this.updateTransportAuthorization();
1377
1243
  }
1378
-
1379
1244
  skipAuthorizationUpdate = false;
1380
-
1381
1245
  if (response.status === 502) {
1382
1246
  await checkMutex();
1383
1247
  return continueWait(true);
1384
1248
  }
1385
-
1386
1249
  let body = {};
1387
1250
  let text = '';
1388
-
1389
1251
  try {
1390
1252
  text = await response.text();
1391
1253
  body = JSON.parse(text);
1392
1254
  } catch (_) {
1393
1255
  body.error = text;
1394
1256
  }
1395
-
1396
1257
  if (body.error === 'Continue wait') {
1397
1258
  await checkMutex();
1398
-
1399
1259
  if (options.progressCallback) {
1400
1260
  options.progressCallback(new ProgressResult(body));
1401
1261
  }
1402
-
1403
1262
  return continueWait();
1404
1263
  }
1405
-
1406
1264
  if (response.status !== 200) {
1407
1265
  await checkMutex();
1408
-
1409
1266
  if (!options.subscribe && requestInstance.unsubscribe) {
1410
1267
  await requestInstance.unsubscribe();
1411
1268
  }
1412
-
1413
1269
  const error = new RequestError(body.error, body, response.status); // TODO error class
1414
-
1415
1270
  if (callback) {
1416
1271
  callback(error);
1417
1272
  } else {
1418
1273
  throw error;
1419
1274
  }
1420
-
1421
1275
  return subscribeNext();
1422
1276
  }
1423
-
1424
1277
  await checkMutex();
1425
-
1426
1278
  if (!options.subscribe && requestInstance.unsubscribe) {
1427
1279
  await requestInstance.unsubscribe();
1428
1280
  }
1429
-
1430
1281
  const result = toResult(body);
1431
-
1432
1282
  if (callback) {
1433
1283
  callback(null, result);
1434
1284
  } else {
1435
1285
  return result;
1436
1286
  }
1437
-
1438
1287
  return subscribeNext();
1439
1288
  };
1440
-
1441
1289
  const promise = requestPromise.then(requestInstance => mutexPromise(requestInstance.subscribe(loadImpl)));
1442
-
1443
1290
  if (callback) {
1444
1291
  return {
1445
1292
  unsubscribe: async () => {
1446
1293
  const requestInstance = await requestPromise;
1447
1294
  unsubscribed = true;
1448
-
1449
1295
  if (requestInstance.unsubscribe) {
1450
1296
  return requestInstance.unsubscribe();
1451
1297
  }
1452
-
1453
1298
  return null;
1454
1299
  }
1455
1300
  };
@@ -1457,22 +1302,18 @@ class CubeApi {
1457
1302
  return promise;
1458
1303
  }
1459
1304
  }
1460
-
1461
1305
  async updateTransportAuthorization() {
1462
1306
  if (this.updateAuthorizationPromise) {
1463
1307
  await this.updateAuthorizationPromise;
1464
1308
  return;
1465
1309
  }
1466
-
1467
1310
  if (typeof this.apiToken === 'function') {
1468
1311
  this.updateAuthorizationPromise = new Promise(async (resolve, reject) => {
1469
1312
  try {
1470
1313
  const token = await this.apiToken();
1471
-
1472
1314
  if (this.transport.authorization !== token) {
1473
1315
  this.transport.authorization = token;
1474
1316
  }
1475
-
1476
1317
  resolve();
1477
1318
  } catch (error) {
1478
1319
  reject(error);
@@ -1483,6 +1324,7 @@ class CubeApi {
1483
1324
  await this.updateAuthorizationPromise;
1484
1325
  }
1485
1326
  }
1327
+
1486
1328
  /**
1487
1329
  * Add system properties to a query object.
1488
1330
  * @param {Query} query
@@ -1490,17 +1332,17 @@ class CubeApi {
1490
1332
  * @returns {void}
1491
1333
  * @private
1492
1334
  */
1493
-
1494
-
1495
1335
  patchQueryInternal(query, responseFormat) {
1496
1336
  if (responseFormat === ResultType.COMPACT && query.responseFormat !== ResultType.COMPACT) {
1497
- return { ...query,
1337
+ return {
1338
+ ...query,
1498
1339
  responseFormat: ResultType.COMPACT
1499
1340
  };
1500
1341
  } else {
1501
1342
  return query;
1502
1343
  }
1503
1344
  }
1345
+
1504
1346
  /**
1505
1347
  * Process result fetched from the gateway#load method according
1506
1348
  * to the network protocol.
@@ -1508,19 +1350,17 @@ class CubeApi {
1508
1350
  * @returns ResultSet
1509
1351
  * @private
1510
1352
  */
1511
-
1512
-
1513
1353
  loadResponseInternal(response, options = {}) {
1514
1354
  if (response.results.length) {
1515
1355
  if (options.castNumerics) {
1516
1356
  response.results.forEach(result => {
1517
- const numericMembers = Object.entries({ ...result.annotation.measures,
1357
+ const numericMembers = Object.entries({
1358
+ ...result.annotation.measures,
1518
1359
  ...result.annotation.dimensions
1519
1360
  }).map(([k, v]) => {
1520
1361
  if (v.type === 'number') {
1521
1362
  return k;
1522
1363
  }
1523
-
1524
1364
  return undefined;
1525
1365
  }).filter(Boolean);
1526
1366
  result.data = result.data.map(row => {
@@ -1533,7 +1373,6 @@ class CubeApi {
1533
1373
  });
1534
1374
  });
1535
1375
  }
1536
-
1537
1376
  if (response.results[0].query.responseFormat && response.results[0].query.responseFormat === ResultType.COMPACT) {
1538
1377
  response.results.forEach((result, j) => {
1539
1378
  const data = [];
@@ -1548,13 +1387,15 @@ class CubeApi {
1548
1387
  });
1549
1388
  }
1550
1389
  }
1551
-
1552
1390
  return new ResultSet(response, {
1553
1391
  parseDateMeasures: this.parseDateMeasures
1554
1392
  });
1555
1393
  }
1556
-
1557
1394
  load(query, options, callback, responseFormat = ResultType.DEFAULT) {
1395
+ options = {
1396
+ castNumerics: this.castNumerics,
1397
+ ...options
1398
+ };
1558
1399
  if (responseFormat === ResultType.COMPACT) {
1559
1400
  if (Array.isArray(query)) {
1560
1401
  query = query.map(q => this.patchQueryInternal(q, ResultType.COMPACT));
@@ -1562,14 +1403,16 @@ class CubeApi {
1562
1403
  query = this.patchQueryInternal(query, ResultType.COMPACT);
1563
1404
  }
1564
1405
  }
1565
-
1566
1406
  return this.loadMethod(() => this.request('load', {
1567
1407
  query,
1568
1408
  queryType: 'multi'
1569
1409
  }), response => this.loadResponseInternal(response, options), options, callback);
1570
1410
  }
1571
-
1572
1411
  subscribe(query, options, callback, responseFormat = ResultType.DEFAULT) {
1412
+ options = {
1413
+ castNumerics: this.castNumerics,
1414
+ ...options
1415
+ };
1573
1416
  if (responseFormat === ResultType.COMPACT) {
1574
1417
  if (Array.isArray(query)) {
1575
1418
  query = query.map(q => this.patchQueryInternal(q, ResultType.COMPACT));
@@ -1577,33 +1420,28 @@ class CubeApi {
1577
1420
  query = this.patchQueryInternal(query, ResultType.COMPACT);
1578
1421
  }
1579
1422
  }
1580
-
1581
1423
  return this.loadMethod(() => this.request('subscribe', {
1582
1424
  query,
1583
1425
  queryType: 'multi'
1584
- }), response => this.loadResponseInternal(response, options), { ...options,
1426
+ }), response => this.loadResponseInternal(response, options), {
1427
+ ...options,
1585
1428
  subscribe: true
1586
1429
  }, callback);
1587
1430
  }
1588
-
1589
1431
  sql(query, options, callback) {
1590
1432
  return this.loadMethod(() => this.request('sql', {
1591
1433
  query
1592
1434
  }), response => Array.isArray(response) ? response.map(body => new SqlQuery(body)) : new SqlQuery(response), options, callback);
1593
1435
  }
1594
-
1595
1436
  meta(options, callback) {
1596
1437
  return this.loadMethod(() => this.request('meta'), body => new Meta(body), options, callback);
1597
1438
  }
1598
-
1599
1439
  dryRun(query, options, callback) {
1600
1440
  return this.loadMethod(() => this.request('dry-run', {
1601
1441
  query
1602
1442
  }), response => response, options, callback);
1603
1443
  }
1604
-
1605
1444
  }
1606
-
1607
1445
  var index = ((apiToken, options) => new CubeApi(apiToken, options));
1608
1446
 
1609
1447
  export default index;