@cubejs-client/core 1.5.0 → 1.5.2
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 +77 -27
- package/dist/cubejs-client-core.cjs.js.map +1 -1
- package/dist/cubejs-client-core.umd.js +78 -28
- package/dist/cubejs-client-core.umd.js.map +1 -1
- package/dist/src/ResultSet.d.ts.map +1 -1
- package/dist/src/ResultSet.js +4 -3
- package/dist/src/time.d.ts +3 -1
- package/dist/src/time.d.ts.map +1 -1
- package/dist/src/time.js +54 -15
- package/dist/test/drill-down.test.js +226 -0
- package/package.json +3 -3
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"ResultSet.d.ts","sourceRoot":"","sources":["../../src/ResultSet.ts"],"names":[],"mappings":"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"}
|
package/dist/src/ResultSet.js
CHANGED
|
@@ -152,7 +152,7 @@ export default class ResultSet {
|
|
|
152
152
|
normalizedPivotConfig?.x.forEach((member, currentIndex) => values.push([member, xValues[currentIndex]]));
|
|
153
153
|
normalizedPivotConfig?.y.forEach((member, currentIndex) => values.push([member, yValues[currentIndex]]));
|
|
154
154
|
const { filters: parentFilters = [], segments = [] } = this.query();
|
|
155
|
-
const { measures } = this.loadResponses[0].annotation;
|
|
155
|
+
const { measures, timeDimensions: timeDimensionsAnnotation } = this.loadResponses[0].annotation;
|
|
156
156
|
let [, measureName] = values.find(([member]) => member === 'measures') || [];
|
|
157
157
|
if (measureName === undefined) {
|
|
158
158
|
[measureName] = Object.keys(measures);
|
|
@@ -172,7 +172,8 @@ export default class ResultSet {
|
|
|
172
172
|
.forEach(([member, value]) => {
|
|
173
173
|
const [cubeName, dimension, granularity] = member.split('.');
|
|
174
174
|
if (granularity !== undefined) {
|
|
175
|
-
|
|
175
|
+
// dayRange.snapTo now handles both predefined and custom granularities
|
|
176
|
+
const range = dayRange(value, value, timeDimensionsAnnotation).snapTo(granularity);
|
|
176
177
|
const originalTimeDimension = query.timeDimensions?.find((td) => td.dimension);
|
|
177
178
|
let dateRange = [
|
|
178
179
|
range.start,
|
|
@@ -357,7 +358,7 @@ export default class ResultSet {
|
|
|
357
358
|
timeDimension.dateRange.find(d => d.match(DateRegex)) :
|
|
358
359
|
!['hour', 'minute', 'second'].includes(timeDimension.granularity);
|
|
359
360
|
const [start, end] = dateRange;
|
|
360
|
-
const range = dayRange(start, end);
|
|
361
|
+
const range = dayRange(start, end, annotations);
|
|
361
362
|
if (isPredefinedGranularity(timeDimension.granularity)) {
|
|
362
363
|
return TIME_SERIES[timeDimension.granularity](padToDay ? range.snapTo('d') : range);
|
|
363
364
|
}
|
package/dist/src/time.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ export declare const TIME_SERIES: Record<string, (range: DayRange) => string[]>;
|
|
|
25
25
|
export declare const isPredefinedGranularity: (granularity: TimeDimensionGranularity) => boolean;
|
|
26
26
|
export declare const DateRegex: RegExp;
|
|
27
27
|
export declare const LocalDateRegex: RegExp;
|
|
28
|
-
export declare const dayRange: (from: any, to: any) => DayRange;
|
|
29
28
|
/**
|
|
30
29
|
* Parse PostgreSQL-like interval string into object
|
|
31
30
|
* E.g. '2 years 15 months 100 weeks 99 hours 15 seconds'
|
|
@@ -55,6 +54,9 @@ export declare function addInterval(date: dayjs.Dayjs, interval: ParsedInterval)
|
|
|
55
54
|
* @returns {dayjs}
|
|
56
55
|
*/
|
|
57
56
|
export declare function subtractInterval(date: dayjs.Dayjs, interval: ParsedInterval): dayjs.Dayjs;
|
|
57
|
+
export declare const dayRange: (from: any, to: any, annotations?: Record<string, {
|
|
58
|
+
granularity?: Granularity;
|
|
59
|
+
}>) => DayRange;
|
|
58
60
|
/**
|
|
59
61
|
* Returns the time series points for the custom interval
|
|
60
62
|
* TODO: It's almost a copy/paste of timeSeriesFromCustomInterval from
|
package/dist/src/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAGjC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACnB,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAC5C,QAAQ,GACN,QAAQ,GACR,MAAM,GACN,KAAK,GACL,MAAM,GACN,OAAO,GACP,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAAG,kCAAkC,GAAG,MAAM,CAAC;AAEnF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,eAAe,EAU1C,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAIzC,eAAO,MAAM,aAAa,YAAa,GAAG,EAAE,KAAG,MAAM,KAAuD,CAAC;AAE7G,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,EAAE,CAWrE,CAAC;AAEF,eAAO,MAAM,uBAAuB,gBAAiB,wBAAwB,KAAG,OAAqC,CAAC;AAEtH,eAAO,MAAM,SAAS,QAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,QAAkD,CAAC;AAE9E
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAGjC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACnB,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAC5C,QAAQ,GACN,QAAQ,GACR,MAAM,GACN,KAAK,GACL,MAAM,GACN,OAAO,GACP,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAAG,kCAAkC,GAAG,MAAM,CAAC;AAEnF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,eAAe,EAU1C,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAIzC,eAAO,MAAM,aAAa,YAAa,GAAG,EAAE,KAAG,MAAM,KAAuD,CAAC;AAE7G,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,EAAE,CAWrE,CAAC;AAEF,eAAO,MAAM,uBAAuB,gBAAiB,wBAAwB,KAAG,OAAqC,CAAC;AAEtH,eAAO,MAAM,SAAS,QAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,QAAkD,CAAC;AAE9E;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,cAAc,CAczE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,GAAG,KAAK,CAAC,KAAK,CAQpF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,GAAG,KAAK,CAAC,KAAK,CAQzF;AA4CD,eAAO,MAAM,QAAQ,SAAU,GAAG,MAAM,GAAG,gBAAgB,OAAO,MAAM,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC,KAAG,QA8DzG,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,SAAU,MAAM,MAAM,MAAM,eAAe,WAAW,KAAG,MAAM,EAkBvG,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,aAAc,MAAM,KAAG,MAkB1D,CAAC;AAIF,eAAO,MAAM,0BAA0B,OAAQ,MAAM,MAAM,MAAM,KAAG,MAWnE,CAAC;AAEF,eAAO,MAAM,cAAc,YAAa,MAAM,KAAG,MA4DhD,CAAC"}
|
package/dist/src/time.js
CHANGED
|
@@ -34,21 +34,6 @@ export const TIME_SERIES = {
|
|
|
34
34
|
export const isPredefinedGranularity = (granularity) => !!TIME_SERIES[granularity];
|
|
35
35
|
export const DateRegex = /^\d\d\d\d-\d\d-\d\d$/;
|
|
36
36
|
export const LocalDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z?$/;
|
|
37
|
-
export const dayRange = (from, to) => ({
|
|
38
|
-
by: (value) => {
|
|
39
|
-
const results = [];
|
|
40
|
-
let start = internalDayjs(from);
|
|
41
|
-
const end = internalDayjs(to);
|
|
42
|
-
while (start.startOf(value).isBefore(end) || start.isSame(end)) {
|
|
43
|
-
results.push(start);
|
|
44
|
-
start = start.add(1, value);
|
|
45
|
-
}
|
|
46
|
-
return results;
|
|
47
|
-
},
|
|
48
|
-
snapTo: (value) => dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value)),
|
|
49
|
-
start: internalDayjs(from),
|
|
50
|
-
end: internalDayjs(to),
|
|
51
|
-
});
|
|
52
37
|
/**
|
|
53
38
|
* Parse PostgreSQL-like interval string into object
|
|
54
39
|
* E.g. '2 years 15 months 100 weeks 99 hours 15 seconds'
|
|
@@ -135,6 +120,60 @@ function alignToOrigin(startDate, interval, origin) {
|
|
|
135
120
|
}
|
|
136
121
|
return alignedDate;
|
|
137
122
|
}
|
|
123
|
+
export const dayRange = (from, to, annotations) => ({
|
|
124
|
+
by: (value) => {
|
|
125
|
+
const results = [];
|
|
126
|
+
let start = internalDayjs(from);
|
|
127
|
+
const end = internalDayjs(to);
|
|
128
|
+
while (start.startOf(value).isBefore(end) || start.isSame(end)) {
|
|
129
|
+
results.push(start);
|
|
130
|
+
start = start.add(1, value);
|
|
131
|
+
}
|
|
132
|
+
return results;
|
|
133
|
+
},
|
|
134
|
+
snapTo: (value) => {
|
|
135
|
+
// Check if this is a custom granularity
|
|
136
|
+
if (!isPredefinedGranularity(value) && annotations) {
|
|
137
|
+
// Try to find the custom granularity metadata
|
|
138
|
+
// The annotation key might be in format "Cube.dimension.granularity"
|
|
139
|
+
// So we need to search through all annotations
|
|
140
|
+
let customGranularity;
|
|
141
|
+
for (const key of Object.keys(annotations)) {
|
|
142
|
+
if (key.endsWith(`.${value}`) && annotations[key].granularity) {
|
|
143
|
+
customGranularity = annotations[key].granularity;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (customGranularity?.interval) {
|
|
148
|
+
// For custom granularities, calculate the range for the bucket
|
|
149
|
+
const intervalParsed = parseSqlInterval(customGranularity.interval);
|
|
150
|
+
let intervalStart = internalDayjs(from);
|
|
151
|
+
// origin and offset are mutually exclusive
|
|
152
|
+
// If either is specified, align to it
|
|
153
|
+
if (customGranularity.origin || customGranularity.offset) {
|
|
154
|
+
let origin;
|
|
155
|
+
if (customGranularity.origin) {
|
|
156
|
+
// Absolute origin time
|
|
157
|
+
origin = internalDayjs(customGranularity.origin);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// offset is relative to start of year
|
|
161
|
+
origin = addInterval(internalDayjs().startOf('year'), parseSqlInterval(customGranularity.offset));
|
|
162
|
+
}
|
|
163
|
+
// Align the value to the origin to find the actual bucket start
|
|
164
|
+
intervalStart = alignToOrigin(intervalStart, intervalParsed, origin);
|
|
165
|
+
}
|
|
166
|
+
// End is start + interval - 1 millisecond (to stay within the bucket)
|
|
167
|
+
const intervalEnd = addInterval(intervalStart, intervalParsed).subtract(1, 'millisecond');
|
|
168
|
+
return dayRange(intervalStart, intervalEnd, annotations);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Default behavior for predefined granularities
|
|
172
|
+
return dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value), annotations);
|
|
173
|
+
},
|
|
174
|
+
start: internalDayjs(from),
|
|
175
|
+
end: internalDayjs(to),
|
|
176
|
+
});
|
|
138
177
|
/**
|
|
139
178
|
* Returns the time series points for the custom interval
|
|
140
179
|
* TODO: It's almost a copy/paste of timeSeriesFromCustomInterval from
|
|
@@ -370,4 +370,230 @@ describe('drill down query', () => {
|
|
|
370
370
|
timezone: 'UTC',
|
|
371
371
|
});
|
|
372
372
|
});
|
|
373
|
+
it('handles custom granularity with interval and origin', () => {
|
|
374
|
+
const EVALUATION_PERIOD = 5;
|
|
375
|
+
const LAST_EVALUATED_AT = '2020-08-01T00:00:00.000';
|
|
376
|
+
const customGranularityResponse = {
|
|
377
|
+
queryType: 'regularQuery',
|
|
378
|
+
results: [
|
|
379
|
+
{
|
|
380
|
+
query: {
|
|
381
|
+
measures: ['Transactions.count'],
|
|
382
|
+
timeDimensions: [
|
|
383
|
+
{
|
|
384
|
+
dimension: 'Transactions.createdAt',
|
|
385
|
+
granularity: 'alerting_monitor',
|
|
386
|
+
dateRange: ['2020-08-01T00:00:00.000', '2020-08-01T01:00:00.000'],
|
|
387
|
+
},
|
|
388
|
+
],
|
|
389
|
+
filters: [],
|
|
390
|
+
timezone: 'UTC',
|
|
391
|
+
order: [],
|
|
392
|
+
dimensions: [],
|
|
393
|
+
},
|
|
394
|
+
data: [
|
|
395
|
+
{
|
|
396
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:00:00.000',
|
|
397
|
+
'Transactions.createdAt': '2020-08-01T00:00:00.000',
|
|
398
|
+
'Transactions.count': 10,
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:05:00.000',
|
|
402
|
+
'Transactions.createdAt': '2020-08-01T00:05:00.000',
|
|
403
|
+
'Transactions.count': 15,
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:10:00.000',
|
|
407
|
+
'Transactions.createdAt': '2020-08-01T00:10:00.000',
|
|
408
|
+
'Transactions.count': 8,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
annotation: {
|
|
412
|
+
measures: {
|
|
413
|
+
'Transactions.count': {
|
|
414
|
+
title: 'Transactions Count',
|
|
415
|
+
shortTitle: 'Count',
|
|
416
|
+
type: 'number',
|
|
417
|
+
drillMembers: ['Transactions.id', 'Transactions.createdAt'],
|
|
418
|
+
drillMembersGrouped: {
|
|
419
|
+
measures: [],
|
|
420
|
+
dimensions: ['Transactions.id', 'Transactions.createdAt'],
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
dimensions: {},
|
|
425
|
+
segments: {},
|
|
426
|
+
timeDimensions: {
|
|
427
|
+
'Transactions.createdAt.alerting_monitor': {
|
|
428
|
+
title: 'Transaction created at',
|
|
429
|
+
shortTitle: 'Created at',
|
|
430
|
+
type: 'time',
|
|
431
|
+
granularity: {
|
|
432
|
+
name: 'alerting_monitor',
|
|
433
|
+
title: 'Alerting Monitor',
|
|
434
|
+
interval: `${EVALUATION_PERIOD} minutes`,
|
|
435
|
+
origin: LAST_EVALUATED_AT,
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
'Transactions.createdAt': {
|
|
439
|
+
title: 'Transaction created at',
|
|
440
|
+
shortTitle: 'Created at',
|
|
441
|
+
type: 'time',
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
],
|
|
447
|
+
pivotQuery: {
|
|
448
|
+
measures: ['Transactions.count'],
|
|
449
|
+
timeDimensions: [
|
|
450
|
+
{
|
|
451
|
+
dimension: 'Transactions.createdAt',
|
|
452
|
+
granularity: 'alerting_monitor',
|
|
453
|
+
dateRange: ['2020-08-01T00:00:00.000', '2020-08-01T01:00:00.000'],
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
filters: [],
|
|
457
|
+
timezone: 'UTC',
|
|
458
|
+
order: [],
|
|
459
|
+
dimensions: [],
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
const resultSet = new ResultSet(customGranularityResponse);
|
|
463
|
+
// Test drilling down on the second data point (00:05:00)
|
|
464
|
+
expect(resultSet.drillDown({ xValues: ['2020-08-01T00:05:00.000'] })).toEqual({
|
|
465
|
+
measures: [],
|
|
466
|
+
segments: [],
|
|
467
|
+
dimensions: ['Transactions.id', 'Transactions.createdAt'],
|
|
468
|
+
filters: [
|
|
469
|
+
{
|
|
470
|
+
member: 'Transactions.count',
|
|
471
|
+
operator: 'measureFilter',
|
|
472
|
+
},
|
|
473
|
+
],
|
|
474
|
+
timeDimensions: [
|
|
475
|
+
{
|
|
476
|
+
dimension: 'Transactions.createdAt',
|
|
477
|
+
// Should create a date range for the 5-minute interval starting at 00:05:00
|
|
478
|
+
dateRange: ['2020-08-01T00:05:00.000', '2020-08-01T00:09:59.999'],
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
timezone: 'UTC',
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
it('handles custom granularity with non-aligned origin', () => {
|
|
485
|
+
const EVALUATION_PERIOD = 5;
|
|
486
|
+
const NON_ALIGNED_ORIGIN = '2020-08-01T00:02:00.000'; // Origin at 00:02 instead of 00:00
|
|
487
|
+
const customGranularityResponse = {
|
|
488
|
+
queryType: 'regularQuery',
|
|
489
|
+
results: [
|
|
490
|
+
{
|
|
491
|
+
query: {
|
|
492
|
+
measures: ['Transactions.count'],
|
|
493
|
+
timeDimensions: [
|
|
494
|
+
{
|
|
495
|
+
dimension: 'Transactions.createdAt',
|
|
496
|
+
granularity: 'alerting_monitor',
|
|
497
|
+
dateRange: ['2020-08-01T00:00:00.000', '2020-08-01T01:00:00.000'],
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
filters: [],
|
|
501
|
+
timezone: 'UTC',
|
|
502
|
+
order: [],
|
|
503
|
+
dimensions: [],
|
|
504
|
+
},
|
|
505
|
+
data: [
|
|
506
|
+
{
|
|
507
|
+
// First bucket starts at 00:02:00 (origin)
|
|
508
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:02:00.000',
|
|
509
|
+
'Transactions.createdAt': '2020-08-01T00:02:00.000',
|
|
510
|
+
'Transactions.count': 10,
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
// Second bucket starts at 00:07:00 (origin + 5 minutes)
|
|
514
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:07:00.000',
|
|
515
|
+
'Transactions.createdAt': '2020-08-01T00:07:00.000',
|
|
516
|
+
'Transactions.count': 15,
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
// Third bucket starts at 00:12:00 (origin + 10 minutes)
|
|
520
|
+
'Transactions.createdAt.alerting_monitor': '2020-08-01T00:12:00.000',
|
|
521
|
+
'Transactions.createdAt': '2020-08-01T00:12:00.000',
|
|
522
|
+
'Transactions.count': 8,
|
|
523
|
+
},
|
|
524
|
+
],
|
|
525
|
+
annotation: {
|
|
526
|
+
measures: {
|
|
527
|
+
'Transactions.count': {
|
|
528
|
+
title: 'Transactions Count',
|
|
529
|
+
shortTitle: 'Count',
|
|
530
|
+
type: 'number',
|
|
531
|
+
drillMembers: ['Transactions.id', 'Transactions.createdAt'],
|
|
532
|
+
drillMembersGrouped: {
|
|
533
|
+
measures: [],
|
|
534
|
+
dimensions: ['Transactions.id', 'Transactions.createdAt'],
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
dimensions: {},
|
|
539
|
+
segments: {},
|
|
540
|
+
timeDimensions: {
|
|
541
|
+
'Transactions.createdAt.alerting_monitor': {
|
|
542
|
+
title: 'Transaction created at',
|
|
543
|
+
shortTitle: 'Created at',
|
|
544
|
+
type: 'time',
|
|
545
|
+
granularity: {
|
|
546
|
+
name: 'alerting_monitor',
|
|
547
|
+
title: 'Alerting Monitor',
|
|
548
|
+
interval: `${EVALUATION_PERIOD} minutes`,
|
|
549
|
+
origin: NON_ALIGNED_ORIGIN,
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
'Transactions.createdAt': {
|
|
553
|
+
title: 'Transaction created at',
|
|
554
|
+
shortTitle: 'Created at',
|
|
555
|
+
type: 'time',
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
],
|
|
561
|
+
pivotQuery: {
|
|
562
|
+
measures: ['Transactions.count'],
|
|
563
|
+
timeDimensions: [
|
|
564
|
+
{
|
|
565
|
+
dimension: 'Transactions.createdAt',
|
|
566
|
+
granularity: 'alerting_monitor',
|
|
567
|
+
dateRange: ['2020-08-01T00:00:00.000', '2020-08-01T01:00:00.000'],
|
|
568
|
+
},
|
|
569
|
+
],
|
|
570
|
+
filters: [],
|
|
571
|
+
timezone: 'UTC',
|
|
572
|
+
order: [],
|
|
573
|
+
dimensions: [],
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
const resultSet = new ResultSet(customGranularityResponse);
|
|
577
|
+
// Test drilling down on the second data point (00:07:00)
|
|
578
|
+
// Since origin is 00:02:00, the bucket is 00:07:00 - 00:11:59
|
|
579
|
+
expect(resultSet.drillDown({ xValues: ['2020-08-01T00:07:00.000'] })).toEqual({
|
|
580
|
+
measures: [],
|
|
581
|
+
segments: [],
|
|
582
|
+
dimensions: ['Transactions.id', 'Transactions.createdAt'],
|
|
583
|
+
filters: [
|
|
584
|
+
{
|
|
585
|
+
member: 'Transactions.count',
|
|
586
|
+
operator: 'measureFilter',
|
|
587
|
+
},
|
|
588
|
+
],
|
|
589
|
+
timeDimensions: [
|
|
590
|
+
{
|
|
591
|
+
dimension: 'Transactions.createdAt',
|
|
592
|
+
// Should align to origin: bucket starts at 00:07:00 (origin + 5min)
|
|
593
|
+
dateRange: ['2020-08-01T00:07:00.000', '2020-08-01T00:11:59.999'],
|
|
594
|
+
},
|
|
595
|
+
],
|
|
596
|
+
timezone: 'UTC',
|
|
597
|
+
});
|
|
598
|
+
});
|
|
373
599
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubejs-client/core",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"engines": {},
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@cubejs-backend/linter": "1.5.
|
|
41
|
+
"@cubejs-backend/linter": "1.5.2",
|
|
42
42
|
"@types/jest": "^29",
|
|
43
43
|
"@types/moment-range": "^4.0.0",
|
|
44
44
|
"@types/ramda": "^0.27.34",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"eslintConfig": {
|
|
51
51
|
"extends": "../cubejs-linter"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "1e757cdc3ef005d24388d0f6e9be3d708595cb1d"
|
|
54
54
|
}
|