@cubejs-client/core 1.5.1 → 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.
@@ -226,25 +226,17 @@ var isPredefinedGranularity = function isPredefinedGranularity(granularity) {
226
226
  };
227
227
  var DateRegex = /^\d\d\d\d-\d\d-\d\d$/;
228
228
  var LocalDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z?$/;
229
- var _dayRange = function dayRange(from, to) {
230
- return {
231
- by: function by(value) {
232
- var results = [];
233
- var start = internalDayjs(from);
234
- var end = internalDayjs(to);
235
- while (start.startOf(value).isBefore(end) || start.isSame(end)) {
236
- results.push(start);
237
- start = start.add(1, value);
238
- }
239
- return results;
240
- },
241
- snapTo: function snapTo(value) {
242
- return _dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value));
243
- },
244
- start: internalDayjs(from),
245
- end: internalDayjs(to)
246
- };
247
- };
229
+
230
+ /**
231
+ * Parse PostgreSQL-like interval string into object
232
+ * E.g. '2 years 15 months 100 weeks 99 hours 15 seconds'
233
+ * Negative units are also supported
234
+ * E.g. '-2 months 5 days -10 hours'
235
+ *
236
+ * TODO: It's copy/paste of parseSqlInterval from @cubejs-backend/shared [time.ts]
237
+ * It's not referenced to omit imports of moment.js staff.
238
+ * Probably one day we should choose one implementation and reuse it in other places.
239
+ */
248
240
  function parseSqlInterval(intervalStr) {
249
241
  var interval = {};
250
242
  var parts = intervalStr.split(/\s+/);
@@ -331,12 +323,67 @@ function alignToOrigin(startDate, interval, origin) {
331
323
  }
332
324
  return alignedDate;
333
325
  }
326
+ var _dayRange = function dayRange(from, to, annotations) {
327
+ return {
328
+ by: function by(value) {
329
+ var results = [];
330
+ var start = internalDayjs(from);
331
+ var end = internalDayjs(to);
332
+ while (start.startOf(value).isBefore(end) || start.isSame(end)) {
333
+ results.push(start);
334
+ start = start.add(1, value);
335
+ }
336
+ return results;
337
+ },
338
+ snapTo: function snapTo(value) {
339
+ // Check if this is a custom granularity
340
+ if (!isPredefinedGranularity(value) && annotations) {
341
+ var _customGranularity;
342
+ // Try to find the custom granularity metadata
343
+ // The annotation key might be in format "Cube.dimension.granularity"
344
+ // So we need to search through all annotations
345
+ var customGranularity;
346
+ for (var _i = 0, _Object$keys = Object.keys(annotations); _i < _Object$keys.length; _i++) {
347
+ var key = _Object$keys[_i];
348
+ if (key.endsWith(".".concat(value)) && annotations[key].granularity) {
349
+ customGranularity = annotations[key].granularity;
350
+ break;
351
+ }
352
+ }
353
+ if ((_customGranularity = customGranularity) !== null && _customGranularity !== void 0 && _customGranularity.interval) {
354
+ // For custom granularities, calculate the range for the bucket
355
+ var intervalParsed = parseSqlInterval(customGranularity.interval);
356
+ var intervalStart = internalDayjs(from);
334
357
 
335
- /**
336
- * Returns the time series points for the custom interval
337
- * TODO: It's almost a copy/paste of timeSeriesFromCustomInterval from
338
- * @cubejs-backend/shared [time.ts] but operates with dayjs instead of moment.js
339
- */
358
+ // origin and offset are mutually exclusive
359
+ // If either is specified, align to it
360
+ if (customGranularity.origin || customGranularity.offset) {
361
+ var origin;
362
+ if (customGranularity.origin) {
363
+ // Absolute origin time
364
+ origin = internalDayjs(customGranularity.origin);
365
+ } else {
366
+ // offset is relative to start of year
367
+ origin = addInterval(internalDayjs().startOf('year'), parseSqlInterval(customGranularity.offset));
368
+ }
369
+
370
+ // Align the value to the origin to find the actual bucket start
371
+ intervalStart = alignToOrigin(intervalStart, intervalParsed, origin);
372
+ }
373
+
374
+ // End is start + interval - 1 millisecond (to stay within the bucket)
375
+ var intervalEnd = addInterval(intervalStart, intervalParsed).subtract(1, 'millisecond');
376
+ return _dayRange(intervalStart, intervalEnd, annotations);
377
+ }
378
+ }
379
+
380
+ // Default behavior for predefined granularities
381
+ return _dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value), annotations);
382
+ },
383
+ start: internalDayjs(from),
384
+ end: internalDayjs(to)
385
+ };
386
+ };
340
387
  var timeSeriesFromCustomInterval = function timeSeriesFromCustomInterval(from, to, granularity) {
341
388
  var intervalParsed = parseSqlInterval(granularity.interval);
342
389
  var start = internalDayjs(from);
@@ -846,7 +893,9 @@ var ResultSet = /*#__PURE__*/function () {
846
893
  parentFilters = _this$query$filters === void 0 ? [] : _this$query$filters,
847
894
  _this$query$segments = _this$query.segments,
848
895
  segments = _this$query$segments === void 0 ? [] : _this$query$segments;
849
- var measures = this.loadResponses[0].annotation.measures;
896
+ var _this$loadResponses$ = this.loadResponses[0].annotation,
897
+ measures = _this$loadResponses$.measures,
898
+ timeDimensionsAnnotation = _this$loadResponses$.timeDimensions;
850
899
  var _ref = values.find(function (_ref3) {
851
900
  var _ref4 = _slicedToArray__default['default'](_ref3, 1),
852
901
  member = _ref4[0];
@@ -882,7 +931,8 @@ var ResultSet = /*#__PURE__*/function () {
882
931
  granularity = _member$split2[2];
883
932
  if (granularity !== undefined) {
884
933
  var _query$timeDimensions;
885
- var range = _dayRange(value, value).snapTo(granularity);
934
+ // dayRange.snapTo now handles both predefined and custom granularities
935
+ var range = _dayRange(value, value, timeDimensionsAnnotation).snapTo(granularity);
886
936
  var originalTimeDimension = (_query$timeDimensions = query.timeDimensions) === null || _query$timeDimensions === void 0 ? void 0 : _query$timeDimensions.find(function (td) {
887
937
  return td.dimension;
888
938
  });
@@ -1053,7 +1103,7 @@ var ResultSet = /*#__PURE__*/function () {
1053
1103
  _dateRange2 = _slicedToArray__default['default'](_dateRange, 2),
1054
1104
  start = _dateRange2[0],
1055
1105
  end = _dateRange2[1];
1056
- var range = _dayRange(start, end);
1106
+ var range = _dayRange(start, end, annotations);
1057
1107
  if (isPredefinedGranularity(timeDimension.granularity)) {
1058
1108
  return TIME_SERIES[timeDimension.granularity](padToDay ? range.snapTo('d') : range);
1059
1109
  }