@cubejs-client/core 1.3.15 → 1.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/{cubejs-client-core.js → cubejs-client-core.cjs.js} +1016 -411
  2. package/dist/cubejs-client-core.cjs.js.map +1 -0
  3. package/dist/cubejs-client-core.umd.js +2901 -12088
  4. package/dist/cubejs-client-core.umd.js.map +1 -1
  5. package/dist/src/HttpTransport.d.ts +54 -0
  6. package/dist/src/HttpTransport.d.ts.map +1 -0
  7. package/dist/src/HttpTransport.js +55 -0
  8. package/dist/src/Meta.d.ts +62 -0
  9. package/dist/src/Meta.d.ts.map +1 -0
  10. package/dist/src/Meta.js +150 -0
  11. package/dist/src/ProgressResult.d.ts +8 -0
  12. package/dist/src/ProgressResult.d.ts.map +1 -0
  13. package/dist/src/ProgressResult.js +11 -0
  14. package/dist/src/RequestError.d.ts +6 -0
  15. package/dist/src/RequestError.d.ts.map +1 -0
  16. package/dist/src/RequestError.js +7 -0
  17. package/dist/src/ResultSet.d.ts +430 -0
  18. package/dist/src/ResultSet.d.ts.map +1 -0
  19. package/dist/src/ResultSet.js +952 -0
  20. package/dist/src/SqlQuery.d.ts +17 -0
  21. package/dist/src/SqlQuery.d.ts.map +1 -0
  22. package/dist/src/SqlQuery.js +11 -0
  23. package/dist/src/index.d.ts +194 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +411 -0
  26. package/dist/src/index.umd.d.ts +3 -0
  27. package/dist/src/index.umd.d.ts.map +1 -0
  28. package/dist/src/index.umd.js +6 -0
  29. package/dist/src/time.d.ts +70 -0
  30. package/dist/src/time.d.ts.map +1 -0
  31. package/dist/src/time.js +249 -0
  32. package/dist/src/types.d.ts +424 -0
  33. package/dist/src/types.d.ts.map +1 -0
  34. package/dist/src/types.js +1 -0
  35. package/dist/src/utils.d.ts +19 -0
  36. package/dist/src/utils.d.ts.map +1 -0
  37. package/dist/src/utils.js +294 -0
  38. package/dist/test/CubeApi.test.d.ts +7 -0
  39. package/dist/test/CubeApi.test.d.ts.map +1 -0
  40. package/dist/test/CubeApi.test.js +279 -0
  41. package/dist/test/HttpTransport.test.d.ts +2 -0
  42. package/dist/test/HttpTransport.test.d.ts.map +1 -0
  43. package/dist/test/HttpTransport.test.js +244 -0
  44. package/dist/test/ResultSet.test.d.ts +7 -0
  45. package/dist/test/ResultSet.test.d.ts.map +1 -0
  46. package/dist/test/ResultSet.test.js +1725 -0
  47. package/dist/test/compare-date-range.test.d.ts +2 -0
  48. package/dist/test/compare-date-range.test.d.ts.map +1 -0
  49. package/dist/test/compare-date-range.test.js +742 -0
  50. package/dist/test/data-blending.test.d.ts +2 -0
  51. package/dist/test/data-blending.test.d.ts.map +1 -0
  52. package/dist/test/data-blending.test.js +423 -0
  53. package/dist/test/default-heuristics.test.d.ts +2 -0
  54. package/dist/test/default-heuristics.test.d.ts.map +1 -0
  55. package/dist/test/default-heuristics.test.js +108 -0
  56. package/dist/test/drill-down.test.d.ts +2 -0
  57. package/dist/test/drill-down.test.d.ts.map +1 -0
  58. package/dist/test/drill-down.test.js +373 -0
  59. package/dist/test/fixtures/datablending/load-responses.json +261 -0
  60. package/dist/test/granularity.test.d.ts +2 -0
  61. package/dist/test/granularity.test.d.ts.map +1 -0
  62. package/dist/test/granularity.test.js +218 -0
  63. package/dist/test/helpers.d.ts +283 -0
  64. package/dist/test/helpers.d.ts.map +1 -0
  65. package/dist/test/helpers.js +974 -0
  66. package/dist/test/index.test.d.ts +7 -0
  67. package/dist/test/index.test.d.ts.map +1 -0
  68. package/dist/test/index.test.js +370 -0
  69. package/dist/test/table.test.d.ts +2 -0
  70. package/dist/test/table.test.d.ts.map +1 -0
  71. package/dist/test/table.test.js +757 -0
  72. package/dist/test/utils.test.d.ts +2 -0
  73. package/dist/test/utils.test.d.ts.map +1 -0
  74. package/dist/test/utils.test.js +32 -0
  75. package/package.json +26 -21
  76. package/dist/cubejs-client-core.esm.js +0 -1639
  77. package/dist/cubejs-client-core.esm.js.map +0 -1
  78. package/dist/cubejs-client-core.js.map +0 -1
  79. package/index.d.ts +0 -1338
  80. package/src/HttpTransport.js +0 -60
  81. package/src/HttpTransport.test.js +0 -117
  82. package/src/Meta.js +0 -142
  83. package/src/ProgressResult.js +0 -13
  84. package/src/RequestError.js +0 -7
  85. package/src/ResultSet.js +0 -746
  86. package/src/SqlQuery.js +0 -13
  87. package/src/index.js +0 -398
  88. package/src/index.test.js +0 -454
  89. package/src/index.umd.js +0 -8
  90. package/src/tests/ResultSet.test.js +0 -1655
  91. package/src/tests/compare-date-range.test.js +0 -753
  92. package/src/tests/data-blending.test.js +0 -432
  93. package/src/tests/default-heuristics.test.js +0 -118
  94. package/src/tests/drill-down.test.js +0 -402
  95. package/src/tests/fixtures/datablending/load-responses.json +0 -261
  96. package/src/tests/granularity.test.js +0 -225
  97. package/src/tests/table.test.js +0 -791
  98. package/src/tests/utils.test.js +0 -35
  99. package/src/time.js +0 -296
  100. package/src/utils.js +0 -368
@@ -0,0 +1,294 @@
1
+ import { clone, equals, fromPairs, indexBy, prop, toPairs } from 'ramda';
2
+ import { DEFAULT_GRANULARITY } from './time';
3
+ export function removeEmptyQueryFields(_query) {
4
+ const query = _query || {};
5
+ return fromPairs(toPairs(query).flatMap(([key, value]) => {
6
+ if (['measures', 'dimensions', 'segments', 'timeDimensions', 'filters'].includes(key)) {
7
+ if (Array.isArray(value) && value.length === 0) {
8
+ return [];
9
+ }
10
+ }
11
+ if (key === 'order' && value) {
12
+ if (Array.isArray(value) && value.length === 0) {
13
+ return [];
14
+ }
15
+ else if (!Object.keys(value).length) {
16
+ return [];
17
+ }
18
+ }
19
+ return [[key, value]];
20
+ }));
21
+ }
22
+ export function validateQuery(_query) {
23
+ const query = _query || {};
24
+ return removeEmptyQueryFields({
25
+ ...query,
26
+ filters: (query.filters || []).filter((f) => 'operator' in f),
27
+ timeDimensions: (query.timeDimensions || []).filter((td) => !(!td.dateRange && !td.granularity)),
28
+ });
29
+ }
30
+ export function areQueriesEqual(query1, query2) {
31
+ return (equals(Object.entries(query1?.order || {}), Object.entries(query2?.order || {})) && equals(query1, query2));
32
+ }
33
+ export function defaultOrder(query) {
34
+ const granularity = (query.timeDimensions || []).find((d) => d.granularity);
35
+ if (granularity) {
36
+ return {
37
+ [granularity.dimension]: 'asc',
38
+ };
39
+ }
40
+ else if ((query.measures || []).length > 0 &&
41
+ (query.dimensions || []).length > 0) {
42
+ return {
43
+ [query.measures[0]]: 'desc',
44
+ };
45
+ }
46
+ else if ((query.dimensions || []).length > 0) {
47
+ return {
48
+ [query.dimensions[0]]: 'asc',
49
+ };
50
+ }
51
+ return {};
52
+ }
53
+ export function defaultHeuristics(newState, oldQuery, options) {
54
+ const { query, ...props } = clone(newState);
55
+ const { meta, sessionGranularity } = options;
56
+ const granularity = sessionGranularity || DEFAULT_GRANULARITY;
57
+ let state = {
58
+ shouldApplyHeuristicOrder: false,
59
+ pivotConfig: null,
60
+ query,
61
+ ...props,
62
+ };
63
+ let newQuery = null;
64
+ if (!areQueriesEqual(query, oldQuery)) {
65
+ newQuery = query;
66
+ }
67
+ if (Array.isArray(newQuery) || Array.isArray(oldQuery)) {
68
+ return {
69
+ shouldApplyHeuristicOrder: false,
70
+ pivotConfig: null,
71
+ ...newState,
72
+ };
73
+ }
74
+ if (newQuery) {
75
+ if ((oldQuery.timeDimensions || []).length === 1 &&
76
+ (newQuery.timeDimensions || []).length === 1 &&
77
+ newQuery.timeDimensions[0].granularity &&
78
+ oldQuery.timeDimensions[0].granularity !==
79
+ newQuery.timeDimensions[0].granularity) {
80
+ state = {
81
+ ...state,
82
+ sessionGranularity: newQuery.timeDimensions[0].granularity,
83
+ };
84
+ }
85
+ if (((oldQuery.measures || []).length === 0 &&
86
+ (newQuery.measures || []).length > 0) ||
87
+ ((oldQuery.measures || []).length === 1 &&
88
+ (newQuery.measures || []).length === 1 &&
89
+ oldQuery.measures[0] !== newQuery.measures[0])) {
90
+ const [td] = newQuery.timeDimensions || [];
91
+ const defaultTimeDimension = meta.defaultTimeDimensionNameFor(newQuery.measures[0]);
92
+ newQuery = {
93
+ ...newQuery,
94
+ timeDimensions: defaultTimeDimension
95
+ ? [
96
+ {
97
+ dimension: defaultTimeDimension,
98
+ granularity: td?.granularity || granularity,
99
+ dateRange: td?.dateRange,
100
+ },
101
+ ]
102
+ : [],
103
+ };
104
+ return {
105
+ ...state,
106
+ pivotConfig: null,
107
+ shouldApplyHeuristicOrder: true,
108
+ query: newQuery,
109
+ chartType: defaultTimeDimension ? 'line' : 'number',
110
+ };
111
+ }
112
+ if ((oldQuery.dimensions || []).length === 0 &&
113
+ (newQuery.dimensions || []).length > 0) {
114
+ newQuery = {
115
+ ...newQuery,
116
+ timeDimensions: (newQuery.timeDimensions || []).map((td) => ({
117
+ ...td,
118
+ granularity: undefined,
119
+ })),
120
+ };
121
+ return {
122
+ ...state,
123
+ pivotConfig: null,
124
+ shouldApplyHeuristicOrder: true,
125
+ query: newQuery,
126
+ chartType: 'table',
127
+ };
128
+ }
129
+ if ((oldQuery.dimensions || []).length > 0 &&
130
+ (newQuery.dimensions || []).length === 0) {
131
+ newQuery = {
132
+ ...newQuery,
133
+ timeDimensions: (newQuery.timeDimensions || []).map((td) => ({
134
+ ...td,
135
+ granularity: td.granularity || granularity,
136
+ })),
137
+ };
138
+ return {
139
+ ...state,
140
+ pivotConfig: null,
141
+ shouldApplyHeuristicOrder: true,
142
+ query: newQuery,
143
+ chartType: (newQuery.timeDimensions || []).length ? 'line' : 'number',
144
+ };
145
+ }
146
+ if (((oldQuery.dimensions || []).length > 0 ||
147
+ (oldQuery.measures || []).length > 0) &&
148
+ (newQuery.dimensions || []).length === 0 &&
149
+ (newQuery.measures || []).length === 0) {
150
+ newQuery = {
151
+ ...newQuery,
152
+ timeDimensions: [],
153
+ filters: [],
154
+ };
155
+ return {
156
+ ...state,
157
+ pivotConfig: null,
158
+ shouldApplyHeuristicOrder: true,
159
+ query: newQuery,
160
+ sessionGranularity: null,
161
+ };
162
+ }
163
+ return state;
164
+ }
165
+ if (state.chartType) {
166
+ const newChartType = state.chartType;
167
+ if ((newChartType === 'line' || newChartType === 'area') &&
168
+ (oldQuery.timeDimensions || []).length === 1 &&
169
+ !oldQuery.timeDimensions[0].granularity) {
170
+ const [td] = oldQuery.timeDimensions;
171
+ return {
172
+ ...state,
173
+ pivotConfig: null,
174
+ query: {
175
+ ...oldQuery,
176
+ timeDimensions: [{ ...td, granularity }],
177
+ },
178
+ };
179
+ }
180
+ if ((newChartType === 'pie' ||
181
+ newChartType === 'table' ||
182
+ newChartType === 'number') &&
183
+ (oldQuery.timeDimensions || []).length === 1 &&
184
+ oldQuery.timeDimensions[0].granularity) {
185
+ const [td] = oldQuery.timeDimensions;
186
+ return {
187
+ ...state,
188
+ pivotConfig: null,
189
+ shouldApplyHeuristicOrder: true,
190
+ query: {
191
+ ...oldQuery,
192
+ timeDimensions: [{ ...td, granularity: undefined }],
193
+ },
194
+ };
195
+ }
196
+ }
197
+ return state;
198
+ }
199
+ export function isQueryPresent(query) {
200
+ if (!query) {
201
+ return false;
202
+ }
203
+ return (Array.isArray(query) ? query : [query]).every((q) => q.measures?.length || q.dimensions?.length || q.timeDimensions?.length);
204
+ }
205
+ export function movePivotItem(pivotConfig, sourceIndex, destinationIndex, sourceAxis, destinationAxis) {
206
+ const nextPivotConfig = {
207
+ ...pivotConfig,
208
+ x: [...(pivotConfig.x || [])],
209
+ y: [...(pivotConfig.y || [])],
210
+ };
211
+ const id = pivotConfig[sourceAxis][sourceIndex];
212
+ const lastIndex = nextPivotConfig[destinationAxis].length - 1;
213
+ if (id === 'measures') {
214
+ destinationIndex = lastIndex + 1;
215
+ }
216
+ else if (sourceAxis === destinationAxis &&
217
+ destinationIndex >= lastIndex &&
218
+ nextPivotConfig[destinationAxis][lastIndex] === 'measures') {
219
+ destinationIndex = lastIndex - 1;
220
+ }
221
+ else if (sourceAxis !== destinationAxis &&
222
+ destinationIndex > lastIndex &&
223
+ nextPivotConfig[destinationAxis][lastIndex] === 'measures') {
224
+ destinationIndex = lastIndex;
225
+ }
226
+ nextPivotConfig[sourceAxis].splice(sourceIndex, 1);
227
+ nextPivotConfig[destinationAxis].splice(destinationIndex, 0, id);
228
+ return nextPivotConfig;
229
+ }
230
+ export function moveItemInArray(list, sourceIndex, destinationIndex) {
231
+ const result = [...list];
232
+ const [removed] = result.splice(sourceIndex, 1);
233
+ result.splice(destinationIndex, 0, removed);
234
+ return result;
235
+ }
236
+ export function flattenFilters(filters = []) {
237
+ return filters.reduce((memo, filter) => {
238
+ if ('or' in filter) {
239
+ return [...memo, ...flattenFilters(filter.or)];
240
+ }
241
+ if ('and' in filter) {
242
+ return [...memo, ...flattenFilters(filter.and)];
243
+ }
244
+ return [...memo, filter];
245
+ }, []);
246
+ }
247
+ export function getQueryMembers(query = {}) {
248
+ const keys = ['measures', 'dimensions', 'segments'];
249
+ const members = new Set();
250
+ keys.forEach((key) => (query[key] || []).forEach((member) => members.add(member)));
251
+ (query.timeDimensions || []).forEach((td) => members.add(td.dimension));
252
+ const filters = flattenFilters(query.filters);
253
+ filters.forEach((filter) => {
254
+ const member = filter.dimension || filter.member;
255
+ if (typeof member === 'string') {
256
+ members.add(member);
257
+ }
258
+ });
259
+ return [...members];
260
+ }
261
+ export function getOrderMembersFromOrder(orderMembers, order) {
262
+ const ids = new Set();
263
+ const indexedOrderMembers = indexBy(prop('id'), orderMembers);
264
+ const entries = Array.isArray(order) ? order : Object.entries(order || {});
265
+ const nextOrderMembers = [];
266
+ entries.forEach(([memberId, currentOrder]) => {
267
+ if (currentOrder !== 'none' && indexedOrderMembers[memberId]) {
268
+ ids.add(memberId);
269
+ nextOrderMembers.push({
270
+ ...indexedOrderMembers[memberId],
271
+ order: currentOrder,
272
+ });
273
+ }
274
+ });
275
+ orderMembers.forEach((member) => {
276
+ if (!ids.has(member.id)) {
277
+ nextOrderMembers.push({
278
+ ...member,
279
+ order: member.order || 'none',
280
+ });
281
+ }
282
+ });
283
+ return nextOrderMembers;
284
+ }
285
+ export function aliasSeries(values, index, pivotConfig, duplicateMeasures = new Set()) {
286
+ const nonNullValues = values.filter((value) => value != null);
287
+ if (pivotConfig?.aliasSeries?.[index]) {
288
+ return [pivotConfig.aliasSeries[index], ...nonNullValues];
289
+ }
290
+ else if (duplicateMeasures.has(nonNullValues[0])) {
291
+ return [index, ...nonNullValues];
292
+ }
293
+ return nonNullValues;
294
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license MIT License
3
+ * @copyright Cube Dev, Inc.
4
+ * @fileoverview Test signal parameter in CubeApi
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=CubeApi.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CubeApi.test.d.ts","sourceRoot":"","sources":["../../test/CubeApi.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,279 @@
1
+ /**
2
+ * @license MIT License
3
+ * @copyright Cube Dev, Inc.
4
+ * @fileoverview Test signal parameter in CubeApi
5
+ */
6
+ /* globals describe,test,expect,jest,beforeEach */
7
+ /* eslint-disable import/first */
8
+ import { CubeApi as CubeApiOriginal } from '../src';
9
+ import HttpTransport from '../src/HttpTransport';
10
+ import { DescriptiveQueryRequest, DescriptiveQueryRequestCompact, DescriptiveQueryResponse, NumericCastedData } from './helpers';
11
+ import ResultSet from '../src/ResultSet';
12
+ class CubeApi extends CubeApiOriginal {
13
+ getTransport() {
14
+ return this.transport;
15
+ }
16
+ makeRequest(method, params) {
17
+ return this.request(method, params);
18
+ }
19
+ }
20
+ describe('CubeApi Constructor', () => {
21
+ test('throw error if no api url', async () => {
22
+ try {
23
+ const _cubeApi = new CubeApi('token', {});
24
+ throw new Error('Should not get here');
25
+ }
26
+ catch (e) {
27
+ expect(e.message).toBe('The `apiUrl` option is required');
28
+ }
29
+ });
30
+ });
31
+ describe('CubeApi Load', () => {
32
+ afterEach(() => {
33
+ jest.clearAllMocks();
34
+ jest.restoreAllMocks();
35
+ });
36
+ test('simple query, no options', async () => {
37
+ // Create a spy on the request method
38
+ jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
39
+ subscribe: (cb) => Promise.resolve(cb({
40
+ status: 200,
41
+ text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
42
+ json: () => Promise.resolve(DescriptiveQueryResponse)
43
+ }, async () => undefined))
44
+ }));
45
+ const cubeApi = new CubeApi('token', {
46
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
47
+ });
48
+ const res = await cubeApi.load(DescriptiveQueryRequest);
49
+ expect(res).toBeInstanceOf(ResultSet);
50
+ expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
51
+ });
52
+ test('simple query + { mutexKey, castNumerics }', async () => {
53
+ // Create a spy on the request method
54
+ jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
55
+ subscribe: (cb) => Promise.resolve(cb({
56
+ status: 200,
57
+ text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
58
+ json: () => Promise.resolve(DescriptiveQueryResponse)
59
+ }, async () => undefined))
60
+ }));
61
+ const cubeApi = new CubeApi({
62
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
63
+ });
64
+ const res = await cubeApi.load(DescriptiveQueryRequest, { mutexKey: 'mutexKey', castNumerics: true });
65
+ expect(res).toBeInstanceOf(ResultSet);
66
+ expect(res.rawData()).toEqual(NumericCastedData);
67
+ });
68
+ test('simple query + compact response format', async () => {
69
+ // Create a spy on the request method
70
+ jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
71
+ subscribe: (cb) => Promise.resolve(cb({
72
+ status: 200,
73
+ text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
74
+ json: () => Promise.resolve(DescriptiveQueryResponse)
75
+ }, async () => undefined))
76
+ }));
77
+ const cubeApi = new CubeApi('token', {
78
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
79
+ });
80
+ const res = await cubeApi.load(DescriptiveQueryRequestCompact, undefined, undefined, 'compact');
81
+ expect(res).toBeInstanceOf(ResultSet);
82
+ expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
83
+ });
84
+ test('2 queries', async () => {
85
+ // Create a spy on the request method
86
+ jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
87
+ subscribe: (cb) => Promise.resolve(cb({
88
+ status: 200,
89
+ text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
90
+ json: () => Promise.resolve(DescriptiveQueryResponse)
91
+ }, async () => undefined))
92
+ }));
93
+ const cubeApi = new CubeApi('token', {
94
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
95
+ });
96
+ const res = await cubeApi.load([DescriptiveQueryRequest, DescriptiveQueryRequest]);
97
+ expect(res).toBeInstanceOf(ResultSet);
98
+ expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
99
+ });
100
+ test('2 queries + compact response format', async () => {
101
+ // Create a spy on the request method
102
+ jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
103
+ subscribe: (cb) => Promise.resolve(cb({
104
+ status: 200,
105
+ text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
106
+ json: () => Promise.resolve(DescriptiveQueryResponse)
107
+ }, async () => undefined))
108
+ }));
109
+ const cubeApi = new CubeApi('token', {
110
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
111
+ });
112
+ const res = await cubeApi.load([DescriptiveQueryRequestCompact, DescriptiveQueryRequestCompact], undefined, undefined, 'compact');
113
+ expect(res).toBeInstanceOf(ResultSet);
114
+ expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
115
+ });
116
+ });
117
+ describe('CubeApi with Abort Signal', () => {
118
+ afterEach(() => {
119
+ jest.clearAllMocks();
120
+ jest.restoreAllMocks();
121
+ });
122
+ test('should pass signal from constructor to request', async () => {
123
+ const controller = new AbortController();
124
+ const { signal } = controller;
125
+ // Create a spy on the request method
126
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
127
+ subscribe: (cb) => Promise.resolve(cb({
128
+ status: 200,
129
+ text: () => Promise.resolve('{"results":[]}'),
130
+ json: () => Promise.resolve({ results: [] })
131
+ }, async () => undefined))
132
+ }));
133
+ const cubeApi = new CubeApi('token', {
134
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
135
+ signal
136
+ });
137
+ // Create a second spy on the load method to verify signal is passed to HttpTransport
138
+ jest.spyOn(cubeApi, 'load');
139
+ await cubeApi.load({
140
+ measures: ['Orders.count']
141
+ });
142
+ // Check if the signal was passed to request method through load
143
+ expect(requestSpy).toHaveBeenCalled();
144
+ // The request method should receive the signal in the call
145
+ // Create a request in the same way as CubeApi.load does
146
+ cubeApi.makeRequest('load', {
147
+ query: { measures: ['Orders.count'] },
148
+ queryType: 'multi'
149
+ });
150
+ // Verify the transport is using the signal
151
+ expect(cubeApi.getTransport().signal).toBe(signal);
152
+ });
153
+ test('should pass signal from options to request', async () => {
154
+ const controller = new AbortController();
155
+ const { signal } = controller;
156
+ // Mock for this specific test
157
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
158
+ subscribe: (cb) => Promise.resolve(cb({
159
+ status: 200,
160
+ text: () => Promise.resolve('{"results":[]}'),
161
+ json: () => Promise.resolve({ results: [] })
162
+ }, async () => undefined))
163
+ }));
164
+ const cubeApi = new CubeApi('token', {
165
+ apiUrl: 'http://localhost:4000/cubejs-api/v1'
166
+ });
167
+ await cubeApi.load({ measures: ['Orders.count'] }, { signal });
168
+ expect(requestSpy).toHaveBeenCalled();
169
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).toBe(signal);
170
+ });
171
+ test('options signal should override constructor signal', async () => {
172
+ const constructorController = new AbortController();
173
+ const optionsController = new AbortController();
174
+ // Mock for this specific test
175
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
176
+ subscribe: (cb) => Promise.resolve(cb({
177
+ status: 200,
178
+ text: () => Promise.resolve('{"results":[]}'),
179
+ json: () => Promise.resolve({ results: [] })
180
+ }, async () => undefined))
181
+ }));
182
+ const cubeApi = new CubeApi('token', {
183
+ apiUrl: 'http://localhost:4000/cubejs-api/v1',
184
+ signal: constructorController.signal
185
+ });
186
+ await cubeApi.load({ measures: ['Orders.count'] }, { signal: optionsController.signal });
187
+ expect(requestSpy).toHaveBeenCalled();
188
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).toBe(optionsController.signal);
189
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).not.toBe(constructorController.signal);
190
+ });
191
+ test('should pass signal to meta request', async () => {
192
+ const controller = new AbortController();
193
+ const { signal } = controller;
194
+ // Mock for meta with proper format - include dimensions, segments, and measures with required properties
195
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
196
+ subscribe: (cb) => Promise.resolve(cb({
197
+ status: 200,
198
+ text: () => Promise.resolve(JSON.stringify({
199
+ cubes: [{
200
+ name: 'Orders',
201
+ title: 'Orders',
202
+ measures: [{
203
+ name: 'count',
204
+ title: 'Count',
205
+ shortTitle: 'Count',
206
+ type: 'number'
207
+ }],
208
+ dimensions: [{
209
+ name: 'status',
210
+ title: 'Status',
211
+ type: 'string'
212
+ }],
213
+ segments: []
214
+ }]
215
+ })),
216
+ json: () => Promise.resolve({
217
+ cubes: [{
218
+ name: 'Orders',
219
+ title: 'Orders',
220
+ measures: [{
221
+ name: 'count',
222
+ title: 'Count',
223
+ shortTitle: 'Count',
224
+ type: 'number'
225
+ }],
226
+ dimensions: [{
227
+ name: 'status',
228
+ title: 'Status',
229
+ type: 'string'
230
+ }],
231
+ segments: []
232
+ }]
233
+ })
234
+ }, async () => undefined))
235
+ }));
236
+ const cubeApi = new CubeApi('token', {
237
+ apiUrl: 'http://localhost:4000/cubejs-api/v1'
238
+ });
239
+ await cubeApi.meta({ signal });
240
+ expect(requestSpy).toHaveBeenCalled();
241
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).toBe(signal);
242
+ });
243
+ test('should pass signal to sql request', async () => {
244
+ const controller = new AbortController();
245
+ const { signal } = controller;
246
+ // Mock for SQL response
247
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
248
+ subscribe: (cb) => Promise.resolve(cb({
249
+ status: 200,
250
+ text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
251
+ json: () => Promise.resolve({ sql: { sql: 'SELECT * FROM orders' } })
252
+ }, async () => undefined))
253
+ }));
254
+ const cubeApi = new CubeApi('token', {
255
+ apiUrl: 'http://localhost:4000/cubejs-api/v1'
256
+ });
257
+ await cubeApi.sql({ measures: ['Orders.count'] }, { signal });
258
+ expect(requestSpy).toHaveBeenCalled();
259
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).toBe(signal);
260
+ });
261
+ test('should pass signal to dryRun request', async () => {
262
+ const controller = new AbortController();
263
+ const { signal } = controller;
264
+ // Mock for dryRun response
265
+ const requestSpy = jest.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
266
+ subscribe: (cb) => Promise.resolve(cb({
267
+ status: 200,
268
+ text: () => Promise.resolve('{"queryType":"regular"}'),
269
+ json: () => Promise.resolve({ queryType: 'regular' })
270
+ }, async () => undefined))
271
+ }));
272
+ const cubeApi = new CubeApi('token', {
273
+ apiUrl: 'http://localhost:4000/cubejs-api/v1'
274
+ });
275
+ await cubeApi.dryRun({ measures: ['Orders.count'] }, { signal });
276
+ expect(requestSpy).toHaveBeenCalled();
277
+ expect(requestSpy.mock.calls[0]?.[1]?.signal).toBe(signal);
278
+ });
279
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=HttpTransport.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpTransport.test.d.ts","sourceRoot":"","sources":["../../test/HttpTransport.test.ts"],"names":[],"mappings":""}