@cubejs-client/core 1.6.32 → 1.6.34

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 (56) hide show
  1. package/dist/cubejs-client-core.cjs.js +20 -14
  2. package/dist/cubejs-client-core.cjs.js.map +1 -1
  3. package/dist/cubejs-client-core.umd.js +20 -14
  4. package/dist/cubejs-client-core.umd.js.map +1 -1
  5. package/dist/src/ResultSet.d.ts.map +1 -1
  6. package/dist/src/ResultSet.js +20 -13
  7. package/dist/src/format-d3-numeric-locale.d.ts +4 -0
  8. package/dist/src/format-d3-numeric-locale.d.ts.map +1 -0
  9. package/dist/src/format-d3-numeric-locale.js +103 -0
  10. package/dist/src/format.d.ts +17 -0
  11. package/dist/src/format.d.ts.map +1 -0
  12. package/dist/src/format.js +89 -0
  13. package/dist/src/index.js +2 -0
  14. package/dist/src/types.d.ts +13 -0
  15. package/dist/src/types.d.ts.map +1 -1
  16. package/dist/test/CubeApi.test.js +37 -37
  17. package/dist/test/HttpTransport.test.js +3 -3
  18. package/dist/test/ResultSet.bench.d.ts +2 -0
  19. package/dist/test/ResultSet.bench.d.ts.map +1 -0
  20. package/dist/test/ResultSet.bench.js +109 -0
  21. package/dist/test/ResultSet.test.d.ts +1 -1
  22. package/dist/test/ResultSet.test.d.ts.map +1 -1
  23. package/dist/test/ResultSet.test.js +0 -2
  24. package/dist/test/SqlQuery.test.js +0 -1
  25. package/dist/test/compare-date-range.test.d.ts +1 -1
  26. package/dist/test/compare-date-range.test.d.ts.map +1 -1
  27. package/dist/test/compare-date-range.test.js +0 -2
  28. package/dist/test/data-blending.test.d.ts +1 -1
  29. package/dist/test/data-blending.test.d.ts.map +1 -1
  30. package/dist/test/data-blending.test.js +0 -2
  31. package/dist/test/dayjs-isolation.test.d.ts +1 -1
  32. package/dist/test/dayjs-isolation.test.d.ts.map +1 -1
  33. package/dist/test/dayjs-isolation.test.js +0 -2
  34. package/dist/test/default-heuristics.test.d.ts +1 -1
  35. package/dist/test/default-heuristics.test.d.ts.map +1 -1
  36. package/dist/test/default-heuristics.test.js +4 -5
  37. package/dist/test/drill-down.test.d.ts +1 -1
  38. package/dist/test/drill-down.test.d.ts.map +1 -1
  39. package/dist/test/drill-down.test.js +4 -5
  40. package/dist/test/format-no-intl.test.d.ts +2 -0
  41. package/dist/test/format-no-intl.test.d.ts.map +1 -0
  42. package/dist/test/format-no-intl.test.js +49 -0
  43. package/dist/test/format.test.d.ts +2 -0
  44. package/dist/test/format.test.d.ts.map +1 -0
  45. package/dist/test/format.test.js +87 -0
  46. package/dist/test/granularity.test.d.ts +1 -1
  47. package/dist/test/granularity.test.d.ts.map +1 -1
  48. package/dist/test/granularity.test.js +0 -2
  49. package/dist/test/index.test.js +2 -2
  50. package/dist/test/table.test.d.ts +1 -1
  51. package/dist/test/table.test.d.ts.map +1 -1
  52. package/dist/test/table.test.js +0 -2
  53. package/dist/test/utils.test.d.ts +1 -1
  54. package/dist/test/utils.test.d.ts.map +1 -1
  55. package/dist/test/utils.test.js +0 -2
  56. package/package.json +12 -9
@@ -3,8 +3,8 @@
3
3
  * @copyright Cube Dev, Inc.
4
4
  * @fileoverview Test signal parameter in CubeApi
5
5
  */
6
- /* globals describe,test,expect,jest,beforeEach */
7
6
  /* eslint-disable import/first */
7
+ import { vi } from 'vitest';
8
8
  import { CubeApi as CubeApiOriginal } from '../src';
9
9
  import HttpTransport from '../src/HttpTransport';
10
10
  import RequestError from '../src/RequestError';
@@ -31,12 +31,12 @@ describe('CubeApi Constructor', () => {
31
31
  });
32
32
  describe('CubeApi Load', () => {
33
33
  afterEach(() => {
34
- jest.clearAllMocks();
35
- jest.restoreAllMocks();
34
+ vi.clearAllMocks();
35
+ vi.restoreAllMocks();
36
36
  });
37
37
  test('simple query, no options', async () => {
38
38
  // Create a spy on the request method
39
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
39
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
40
40
  subscribe: (cb) => Promise.resolve(cb({
41
41
  status: 200,
42
42
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -52,7 +52,7 @@ describe('CubeApi Load', () => {
52
52
  });
53
53
  test('simple query + { mutexKey, castNumerics }', async () => {
54
54
  // Create a spy on the request method
55
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
55
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
56
56
  subscribe: (cb) => Promise.resolve(cb({
57
57
  status: 200,
58
58
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -68,7 +68,7 @@ describe('CubeApi Load', () => {
68
68
  });
69
69
  test('simple query + compact response format', async () => {
70
70
  // Create a spy on the request method
71
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
71
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
72
72
  subscribe: (cb) => Promise.resolve(cb({
73
73
  status: 200,
74
74
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -84,7 +84,7 @@ describe('CubeApi Load', () => {
84
84
  });
85
85
  test('2 queries', async () => {
86
86
  // Create a spy on the request method
87
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
87
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
88
88
  subscribe: (cb) => Promise.resolve(cb({
89
89
  status: 200,
90
90
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -99,7 +99,7 @@ describe('CubeApi Load', () => {
99
99
  expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
100
100
  });
101
101
  test('simple query + { cache: "no-cache" }', async () => {
102
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
102
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
103
103
  subscribe: (cb) => Promise.resolve(cb({
104
104
  status: 200,
105
105
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -115,7 +115,7 @@ describe('CubeApi Load', () => {
115
115
  expect(requestSpy.mock.calls[0]?.[1]?.cache).toBe('no-cache');
116
116
  });
117
117
  test('simple query + { cache: "must-revalidate" }', async () => {
118
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
118
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
119
119
  subscribe: (cb) => Promise.resolve(cb({
120
120
  status: 200,
121
121
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -132,7 +132,7 @@ describe('CubeApi Load', () => {
132
132
  });
133
133
  test('2 queries + compact response format', async () => {
134
134
  // Create a spy on the request method
135
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
135
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
136
136
  subscribe: (cb) => Promise.resolve(cb({
137
137
  status: 200,
138
138
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -149,14 +149,14 @@ describe('CubeApi Load', () => {
149
149
  });
150
150
  describe('CubeApi with Abort Signal', () => {
151
151
  afterEach(() => {
152
- jest.clearAllMocks();
153
- jest.restoreAllMocks();
152
+ vi.clearAllMocks();
153
+ vi.restoreAllMocks();
154
154
  });
155
155
  test('should pass signal from constructor to request', async () => {
156
156
  const controller = new AbortController();
157
157
  const { signal } = controller;
158
158
  // Create a spy on the request method
159
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
159
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
160
160
  subscribe: (cb) => Promise.resolve(cb({
161
161
  status: 200,
162
162
  text: () => Promise.resolve('{"results":[]}'),
@@ -168,7 +168,7 @@ describe('CubeApi with Abort Signal', () => {
168
168
  signal
169
169
  });
170
170
  // Create a second spy on the load method to verify signal is passed to HttpTransport
171
- jest.spyOn(cubeApi, 'load');
171
+ vi.spyOn(cubeApi, 'load');
172
172
  await cubeApi.load({
173
173
  measures: ['Orders.count']
174
174
  });
@@ -187,7 +187,7 @@ describe('CubeApi with Abort Signal', () => {
187
187
  const controller = new AbortController();
188
188
  const { signal } = controller;
189
189
  // Mock for this specific test
190
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
190
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
191
191
  subscribe: (cb) => Promise.resolve(cb({
192
192
  status: 200,
193
193
  text: () => Promise.resolve('{"results":[]}'),
@@ -205,7 +205,7 @@ describe('CubeApi with Abort Signal', () => {
205
205
  const constructorController = new AbortController();
206
206
  const optionsController = new AbortController();
207
207
  // Mock for this specific test
208
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
208
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
209
209
  subscribe: (cb) => Promise.resolve(cb({
210
210
  status: 200,
211
211
  text: () => Promise.resolve('{"results":[]}'),
@@ -225,7 +225,7 @@ describe('CubeApi with Abort Signal', () => {
225
225
  const controller = new AbortController();
226
226
  const { signal } = controller;
227
227
  // Mock for meta with proper format - include dimensions, segments, and measures with required properties
228
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
228
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
229
229
  subscribe: (cb) => Promise.resolve(cb({
230
230
  status: 200,
231
231
  text: () => Promise.resolve(JSON.stringify({
@@ -277,7 +277,7 @@ describe('CubeApi with Abort Signal', () => {
277
277
  const controller = new AbortController();
278
278
  const { signal } = controller;
279
279
  // Mock for SQL response
280
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
280
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
281
281
  subscribe: (cb) => Promise.resolve(cb({
282
282
  status: 200,
283
283
  text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
@@ -295,7 +295,7 @@ describe('CubeApi with Abort Signal', () => {
295
295
  const controller = new AbortController();
296
296
  const { signal } = controller;
297
297
  // Mock for dryRun response
298
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
298
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
299
299
  subscribe: (cb) => Promise.resolve(cb({
300
300
  status: 200,
301
301
  text: () => Promise.resolve('{"queryType":"regular"}'),
@@ -312,8 +312,8 @@ describe('CubeApi with Abort Signal', () => {
312
312
  });
313
313
  describe('CubeApi cubeSql', () => {
314
314
  afterEach(() => {
315
- jest.clearAllMocks();
316
- jest.restoreAllMocks();
315
+ vi.clearAllMocks();
316
+ vi.restoreAllMocks();
317
317
  });
318
318
  const cubeSqlResponseBody = [
319
319
  JSON.stringify({
@@ -335,7 +335,7 @@ describe('CubeApi cubeSql', () => {
335
335
  JSON.stringify({ data: [['Active']] }),
336
336
  ].join('\n');
337
337
  test('should parse lastRefreshTime from response', async () => {
338
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
338
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
339
339
  subscribe: (cb) => Promise.resolve(cb({
340
340
  status: 200,
341
341
  text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBody })),
@@ -357,7 +357,7 @@ describe('CubeApi cubeSql', () => {
357
357
  ]);
358
358
  });
359
359
  test('should omit lastRefreshTime when not present in response', async () => {
360
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
360
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
361
361
  subscribe: (cb) => Promise.resolve(cb({
362
362
  status: 200,
363
363
  text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBodyNoRefreshTime })),
@@ -374,12 +374,12 @@ describe('CubeApi cubeSql', () => {
374
374
  });
375
375
  describe('CubeApi with baseRequestId', () => {
376
376
  afterEach(() => {
377
- jest.clearAllMocks();
378
- jest.restoreAllMocks();
377
+ vi.clearAllMocks();
378
+ vi.restoreAllMocks();
379
379
  });
380
380
  test('should pass baseRequestId from options to request', async () => {
381
381
  const baseRequestId = 'custom-request-id-123';
382
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
382
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
383
383
  subscribe: (cb) => Promise.resolve(cb({
384
384
  status: 200,
385
385
  text: () => Promise.resolve('{"results":[]}'),
@@ -394,7 +394,7 @@ describe('CubeApi with baseRequestId', () => {
394
394
  expect(requestSpy.mock.calls[0]?.[1]?.baseRequestId).toBe(baseRequestId);
395
395
  });
396
396
  test('should generate baseRequestId if not provided', async () => {
397
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
397
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
398
398
  subscribe: (cb) => Promise.resolve(cb({
399
399
  status: 200,
400
400
  text: () => Promise.resolve('{"results":[]}'),
@@ -412,7 +412,7 @@ describe('CubeApi with baseRequestId', () => {
412
412
  });
413
413
  test('should pass baseRequestId to sql request', async () => {
414
414
  const baseRequestId = 'sql-request-id-456';
415
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
415
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
416
416
  subscribe: (cb) => Promise.resolve(cb({
417
417
  status: 200,
418
418
  text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
@@ -428,7 +428,7 @@ describe('CubeApi with baseRequestId', () => {
428
428
  });
429
429
  test('should pass baseRequestId to dryRun request', async () => {
430
430
  const baseRequestId = 'dryrun-request-id-789';
431
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
431
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
432
432
  subscribe: (cb) => Promise.resolve(cb({
433
433
  status: 200,
434
434
  text: () => Promise.resolve('{"queryType":"regular"}'),
@@ -444,7 +444,7 @@ describe('CubeApi with baseRequestId', () => {
444
444
  });
445
445
  test('should pass baseRequestId to subscribe request', async () => {
446
446
  const baseRequestId = 'subscribe-request-id-abc';
447
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
447
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
448
448
  subscribe: (cb) => Promise.resolve(cb({
449
449
  status: 200,
450
450
  text: () => Promise.resolve('{"results":[]}'),
@@ -465,7 +465,7 @@ describe('CubeApi with baseRequestId', () => {
465
465
  });
466
466
  test('should pass baseRequestId with multiple queries', async () => {
467
467
  const baseRequestId = 'multi-query-request-id';
468
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
468
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
469
469
  subscribe: (cb) => Promise.resolve(cb({
470
470
  status: 200,
471
471
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -484,7 +484,7 @@ describe('CubeApi with baseRequestId', () => {
484
484
  });
485
485
  test('should pass baseRequestId to meta request', async () => {
486
486
  const baseRequestId = 'meta-request-id-def';
487
- const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
487
+ const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
488
488
  subscribe: (cb) => Promise.resolve(cb({
489
489
  status: 200,
490
490
  text: () => Promise.resolve(JSON.stringify({
@@ -535,11 +535,11 @@ describe('CubeApi with baseRequestId', () => {
535
535
  });
536
536
  describe('CubeApi Mutex Cancellation', () => {
537
537
  afterEach(() => {
538
- jest.clearAllMocks();
539
- jest.restoreAllMocks();
538
+ vi.clearAllMocks();
539
+ vi.restoreAllMocks();
540
540
  });
541
541
  test('should return null for cancelled query when a newer query invalidates it', async () => {
542
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
542
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
543
543
  subscribe: (cb) => Promise.resolve(cb({
544
544
  status: 200,
545
545
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -562,7 +562,7 @@ describe('CubeApi Mutex Cancellation', () => {
562
562
  expect(second).toBeInstanceOf(ResultSet);
563
563
  });
564
564
  test('should return ResultSet when no mutex cancellation occurs', async () => {
565
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
565
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
566
566
  subscribe: (cb) => Promise.resolve(cb({
567
567
  status: 200,
568
568
  text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
@@ -579,7 +579,7 @@ describe('CubeApi Mutex Cancellation', () => {
579
579
  });
580
580
  test('should propagate non-mutex errors', async () => {
581
581
  const errorBody = { error: 'Internal Server Error' };
582
- jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
582
+ vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
583
583
  subscribe: (cb) => Promise.resolve(cb({
584
584
  status: 500,
585
585
  text: () => Promise.resolve(JSON.stringify(errorBody)),
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable import/first */
2
- /* globals describe,test,expect,jest,afterEach,beforeAll,beforeEach */
2
+ import { vi } from 'vitest';
3
3
  import fetch from 'cross-fetch';
4
- jest.mock('cross-fetch');
4
+ vi.mock('cross-fetch');
5
5
  import HttpTransport from '../src/HttpTransport';
6
6
  const mockedFetch = fetch;
7
7
  describe('HttpTransport', () => {
@@ -183,7 +183,7 @@ describe('HttpTransport', () => {
183
183
  // Mock AbortSignal.timeout
184
184
  const originalTimeout = AbortSignal.timeout;
185
185
  const mockTimeoutSignal = {};
186
- AbortSignal.timeout = jest.fn().mockReturnValue(mockTimeoutSignal);
186
+ AbortSignal.timeout = vi.fn().mockReturnValue(mockTimeoutSignal);
187
187
  const transport = new HttpTransport({
188
188
  authorization: 'token',
189
189
  apiUrl: 'http://localhost:4000/cubejs-api/v1',
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ResultSet.bench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResultSet.bench.d.ts","sourceRoot":"","sources":["../../test/ResultSet.bench.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { bench, describe } from 'vitest';
2
+ import ResultSet from '../src/ResultSet';
3
+ const STATUSES = ['completed', 'processing', 'shipped'];
4
+ function generateLoadResponse(rowCount) {
5
+ const data = [];
6
+ const startDate = new Date('2020-01-01T00:00:00.000Z');
7
+ for (let i = 0; i < rowCount; i++) {
8
+ const date = new Date(startDate.getTime() + i * 86400000);
9
+ const dateStr = date.toISOString().replace('Z', '');
10
+ data.push({
11
+ 'Orders.createdAt.day': dateStr,
12
+ 'Orders.createdAt': dateStr,
13
+ 'Orders.status': STATUSES[i % 3],
14
+ 'Orders.count': String(Math.floor(Math.random() * 1000)),
15
+ });
16
+ }
17
+ return {
18
+ query: {
19
+ measures: ['Orders.count'],
20
+ dimensions: ['Orders.status'],
21
+ timeDimensions: [
22
+ {
23
+ dimension: 'Orders.createdAt',
24
+ granularity: 'day',
25
+ },
26
+ ],
27
+ },
28
+ data,
29
+ lastRefreshTime: '2024-01-01T00:00:00.000Z',
30
+ usedPreAggregations: {},
31
+ annotation: {
32
+ measures: {
33
+ 'Orders.count': {
34
+ title: 'Orders Count',
35
+ shortTitle: 'Count',
36
+ type: 'number',
37
+ },
38
+ },
39
+ dimensions: {
40
+ 'Orders.status': {
41
+ title: 'Orders Status',
42
+ shortTitle: 'Status',
43
+ type: 'string',
44
+ },
45
+ },
46
+ segments: {},
47
+ timeDimensions: {
48
+ 'Orders.createdAt': {
49
+ title: 'Orders Created at',
50
+ shortTitle: 'Created at',
51
+ type: 'time',
52
+ },
53
+ 'Orders.createdAt.day': {
54
+ title: 'Orders Created at',
55
+ shortTitle: 'Created at',
56
+ type: 'time',
57
+ granularity: {
58
+ name: 'day',
59
+ title: 'day',
60
+ interval: '1 day',
61
+ },
62
+ },
63
+ },
64
+ },
65
+ };
66
+ }
67
+ function computeHourRange(targetHours) {
68
+ const start = new Date('2020-01-01T00:00:00.000Z');
69
+ const end = new Date(start.getTime() + (targetHours - 1) * 3600000);
70
+ return [
71
+ start.toISOString().replace('Z', ''),
72
+ end.toISOString().replace('Z', ''),
73
+ ];
74
+ }
75
+ const ROW_COUNTS = [5000, 10000, 25000, 50000, 100000];
76
+ // Pre-build all ResultSets outside benchmarks to avoid measuring construction time
77
+ const pivotResultSets = new Map();
78
+ for (const count of ROW_COUNTS) {
79
+ pivotResultSets.set(count, new ResultSet(generateLoadResponse(count)));
80
+ }
81
+ describe('pivot', () => {
82
+ for (const count of ROW_COUNTS) {
83
+ const label = `${count / 1000}k rows`;
84
+ const rs = pivotResultSets.get(count);
85
+ bench(`pivot - ${label}`, () => {
86
+ rs.pivot();
87
+ });
88
+ bench(`chartPivot - ${label}`, () => {
89
+ rs.chartPivot();
90
+ });
91
+ bench(`tablePivot - ${label}`, () => {
92
+ rs.tablePivot();
93
+ });
94
+ }
95
+ });
96
+ describe('timeSeries', () => {
97
+ const rs = new ResultSet({});
98
+ for (const count of ROW_COUNTS) {
99
+ const label = `${count / 1000}k hours`;
100
+ const dateRange = computeHourRange(count);
101
+ bench(`timeSeries - ${label}`, () => {
102
+ rs.timeSeries({
103
+ dimension: 'Orders.createdAt',
104
+ granularity: 'hour',
105
+ dateRange,
106
+ });
107
+ });
108
+ }
109
+ });
@@ -3,5 +3,5 @@
3
3
  * @copyright Cube Dev, Inc.
4
4
  * @fileoverview ResultSet class unit tests.
5
5
  */
6
- import 'jest';
6
+ export {};
7
7
  //# sourceMappingURL=ResultSet.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ResultSet.test.d.ts","sourceRoot":"","sources":["../../test/ResultSet.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"ResultSet.test.d.ts","sourceRoot":"","sources":["../../test/ResultSet.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -3,8 +3,6 @@
3
3
  * @copyright Cube Dev, Inc.
4
4
  * @fileoverview ResultSet class unit tests.
5
5
  */
6
- /* globals describe,test,expect */
7
- import 'jest';
8
6
  import ResultSet from '../src/ResultSet';
9
7
  import { DescriptiveQueryResponse } from './helpers';
10
8
  describe('ResultSet', () => {
@@ -3,7 +3,6 @@
3
3
  * @copyright Cube Dev, Inc.
4
4
  * @fileoverview SqlQuery class unit tests.
5
5
  */
6
- /* globals describe,it,expect */
7
6
  import SqlQuery from '../src/SqlQuery';
8
7
  describe('SqlQuery', () => {
9
8
  const mockCacheKeyQueriesTuple = [
@@ -1,2 +1,2 @@
1
- import 'jest';
1
+ export {};
2
2
  //# sourceMappingURL=compare-date-range.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare-date-range.test.d.ts","sourceRoot":"","sources":["../../test/compare-date-range.test.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"compare-date-range.test.d.ts","sourceRoot":"","sources":["../../test/compare-date-range.test.ts"],"names":[],"mappings":""}
@@ -1,5 +1,3 @@
1
- /* globals describe, test, expect */
2
- import 'jest';
3
1
  import ResultSet from '../src/ResultSet';
4
2
  const loadResponses = [
5
3
  {
@@ -1,2 +1,2 @@
1
- import 'jest';
1
+ export {};
2
2
  //# sourceMappingURL=data-blending.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-blending.test.d.ts","sourceRoot":"","sources":["../../test/data-blending.test.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"data-blending.test.d.ts","sourceRoot":"","sources":["../../test/data-blending.test.ts"],"names":[],"mappings":""}
@@ -1,5 +1,3 @@
1
- /* globals describe, test, expect */
2
- import 'jest';
3
1
  import ResultSet from '../src/ResultSet';
4
2
  import { loadResponse, loadResponseWithoutDateRange } from './fixtures/datablending/load-responses.json';
5
3
  describe('data blending', () => {
@@ -1,2 +1,2 @@
1
- import 'jest';
1
+ export {};
2
2
  //# sourceMappingURL=dayjs-isolation.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dayjs-isolation.test.d.ts","sourceRoot":"","sources":["../../test/dayjs-isolation.test.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"dayjs-isolation.test.d.ts","sourceRoot":"","sources":["../../test/dayjs-isolation.test.ts"],"names":[],"mappings":""}
@@ -1,5 +1,3 @@
1
- /* globals describe,test,expect */
2
- import 'jest';
3
1
  import dayjs from 'dayjs';
4
2
  import { internalDayjs } from '../src/time';
5
3
  describe('Dayjs Instance Isolation', () => {
@@ -1,2 +1,2 @@
1
- import 'jest';
1
+ export {};
2
2
  //# sourceMappingURL=default-heuristics.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"default-heuristics.test.d.ts","sourceRoot":"","sources":["../../test/default-heuristics.test.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"default-heuristics.test.d.ts","sourceRoot":"","sources":["../../test/default-heuristics.test.ts"],"names":[],"mappings":""}
@@ -1,9 +1,8 @@
1
- /* globals jest, describe, expect, it */
2
- import 'jest';
1
+ import { vi } from 'vitest';
3
2
  import { defaultHeuristics } from '../src/utils';
4
- jest.mock('moment-range', () => {
5
- const Moment = jest.requireActual('moment');
6
- const MomentRange = jest.requireActual('moment-range');
3
+ vi.mock('moment-range', async () => {
4
+ const Moment = await vi.importActual('moment');
5
+ const MomentRange = await vi.importActual('moment-range');
7
6
  const moment = MomentRange.extendMoment(Moment);
8
7
  return {
9
8
  extendMoment: () => moment,
@@ -1,2 +1,2 @@
1
- import 'jest';
1
+ export {};
2
2
  //# sourceMappingURL=drill-down.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drill-down.test.d.ts","sourceRoot":"","sources":["../../test/drill-down.test.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"drill-down.test.d.ts","sourceRoot":"","sources":["../../test/drill-down.test.ts"],"names":[],"mappings":""}
@@ -1,9 +1,8 @@
1
- /* globals jest, describe, expect, it */
2
- import 'jest';
1
+ import { vi } from 'vitest';
3
2
  import ResultSet from '../src/ResultSet';
4
- jest.mock('moment-range', () => {
5
- const Moment = jest.requireActual('moment');
6
- const MomentRange = jest.requireActual('moment-range');
3
+ vi.mock('moment-range', async () => {
4
+ const Moment = await vi.importActual('moment');
5
+ const MomentRange = await vi.importActual('moment-range');
7
6
  const moment = MomentRange.extendMoment(Moment);
8
7
  return {
9
8
  extendMoment: () => moment,
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format-no-intl.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-no-intl.test.d.ts","sourceRoot":"","sources":["../../test/format-no-intl.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
2
+ describe('formatValue without Intl', () => {
3
+ const originalIntl = globalThis.Intl;
4
+ beforeAll(() => {
5
+ vi.resetModules();
6
+ // @ts-expect-error — intentionally removing Intl to simulate environments where it is unavailable
7
+ delete globalThis.Intl;
8
+ });
9
+ afterAll(() => {
10
+ globalThis.Intl = originalIntl;
11
+ });
12
+ it('detectLocale falls back to en-US and formatting works', async () => {
13
+ const { formatValue } = await import('../src/format');
14
+ // number type uses the detected locale (should be en-US fallback)
15
+ expect(formatValue(1234.56, { type: 'number' })).toBe('1,234.56');
16
+ });
17
+ it('currency formatting falls back to en-US locale definition', async () => {
18
+ const { formatValue } = await import('../src/format');
19
+ expect(formatValue(1234.56, { type: 'number', format: 'currency' })).toBe('$1,234.56');
20
+ });
21
+ it('percent formatting works without Intl', async () => {
22
+ const { formatValue } = await import('../src/format');
23
+ expect(formatValue(0.1234, { type: 'number', format: 'percent' })).toBe('12.34%');
24
+ });
25
+ it('time formatting works without Intl', async () => {
26
+ const { formatValue } = await import('../src/format');
27
+ expect(formatValue('2024-03-15T00:00:00.000', { type: 'time', granularity: 'day' })).toBe('2024-03-15');
28
+ });
29
+ it('null/undefined still return emptyPlaceholder', async () => {
30
+ const { formatValue } = await import('../src/format');
31
+ expect(formatValue(null, { type: 'number' })).toBe('∅');
32
+ expect(formatValue(undefined, { type: 'number' })).toBe('∅');
33
+ });
34
+ // Known locale (de-DE) — pre-built d3 definition is used,
35
+ // getCurrencySymbol falls back to the static currencySymbols map.
36
+ it('known locale (de-DE) uses pre-built locale definition', async () => {
37
+ const { formatValue } = await import('../src/format');
38
+ expect(formatValue(1234.56, { type: 'number', format: 'number', locale: 'de-DE' })).toBe('1.234,56');
39
+ expect(formatValue(1234.56, { type: 'number', format: 'currency', currency: 'EUR', locale: 'de-DE' })).toBe('€1.234,56');
40
+ expect(formatValue(0.1234, { type: 'number', format: 'percent', locale: 'de-DE' })).toBe('12,34%');
41
+ });
42
+ // Unknown locale (sv-SE) — getD3NumericLocaleFromIntl throws,
43
+ // falls back entirely to en-US.
44
+ it('unknown locale (sv-SE) falls back to en-US', async () => {
45
+ const { formatValue } = await import('../src/format');
46
+ expect(formatValue(1234.56, { type: 'number', format: 'number', locale: 'sv-SE' })).toBe('1,234.56');
47
+ expect(formatValue(1234.56, { type: 'number', format: 'currency', currency: 'USD', locale: 'sv-SE' })).toBe('$1,234.56');
48
+ });
49
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.test.d.ts","sourceRoot":"","sources":["../../test/format.test.ts"],"names":[],"mappings":""}