@cubejs-client/react 1.7.37 → 1.7.38
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/README.md +4 -4
- package/dist/CubeProvider.d.ts +1 -1
- package/dist/QueryBuilder.d.ts +4 -2
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryRenderer.d.ts +2 -0
- package/dist/QueryRenderer.d.ts.map +1 -1
- package/dist/QueryRendererWithTotals.d.ts +2 -1
- package/dist/QueryRendererWithTotals.d.ts.map +1 -1
- package/dist/cubejs-client-react.cjs.js +88 -42
- package/dist/cubejs-client-react.cjs.js.map +1 -1
- package/dist/cubejs-client-react.esm.js +62 -34
- package/dist/cubejs-client-react.esm.js.map +1 -1
- package/dist/cubejs-client-react.umd.js +88 -42
- package/dist/cubejs-client-react.umd.js.map +1 -1
- package/dist/hooks/cube-query.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +5 -5
- package/package.json +17 -4
- package/src/CubeProvider.tsx +1 -1
- package/src/QueryBuilder.tsx +3 -5
- package/src/QueryRenderer.tsx +2 -4
- package/src/hooks/cube-query.ts +68 -25
- package/src/index.ts +1 -1
- package/src/types.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubejs-client/react",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.38",
|
|
4
4
|
"author": "Cube Dev, Inc.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {},
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsc --build",
|
|
18
|
+
"test": "yarn unit",
|
|
19
|
+
"test:types": "tsc --project tsconfig.test.json",
|
|
18
20
|
"tsc": "tsc --build",
|
|
21
|
+
"unit": "yarn test:types && jest --runInBand",
|
|
19
22
|
"watch": "tsc --build --watch"
|
|
20
23
|
},
|
|
21
24
|
"files": [
|
|
@@ -24,18 +27,28 @@
|
|
|
24
27
|
],
|
|
25
28
|
"dependencies": {
|
|
26
29
|
"@babel/runtime": "^7.13.9",
|
|
27
|
-
"@cubejs-client/core": "1.7.
|
|
30
|
+
"@cubejs-client/core": "1.7.38",
|
|
28
31
|
"core-js": "^3.34.0",
|
|
29
32
|
"ramda": "^0.27.2"
|
|
30
33
|
},
|
|
31
34
|
"devDependencies": {
|
|
32
35
|
"@babel/core": "^7.24.5",
|
|
36
|
+
"@babel/preset-env": "^7.24.5",
|
|
37
|
+
"@babel/preset-react": "^7.12.13",
|
|
38
|
+
"@babel/preset-typescript": "^7.13.0",
|
|
39
|
+
"@types/jest": "^29",
|
|
33
40
|
"@types/ramda": "^0.27.40",
|
|
34
|
-
"@types/react": "^
|
|
41
|
+
"@types/react": "^18.3.0",
|
|
42
|
+
"@types/react-dom": "^18.3.0",
|
|
43
|
+
"babel-jest": "^29",
|
|
44
|
+
"jest": "^29",
|
|
45
|
+
"jest-environment-jsdom": "^29",
|
|
46
|
+
"react": "^18.3.1",
|
|
47
|
+
"react-dom": "^18.3.1",
|
|
35
48
|
"typescript": "~6.0.3"
|
|
36
49
|
},
|
|
37
50
|
"peerDependencies": {
|
|
38
51
|
"react": ">=16.10.2"
|
|
39
52
|
},
|
|
40
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "9ea1fda5dade5b8a4256acd20bcf77318fe13a72"
|
|
41
54
|
}
|
package/src/CubeProvider.tsx
CHANGED
package/src/QueryBuilder.tsx
CHANGED
|
@@ -78,7 +78,7 @@ const granularities: GranularityOption[] = [
|
|
|
78
78
|
];
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* `<QueryBuilder />` is used to build interactive analytics query builders. It abstracts state management and API calls to Cube
|
|
81
|
+
* `<QueryBuilder />` is used to build interactive analytics query builders. It abstracts state management and API calls to Cube Backend. It uses render prop technique and doesn’t render anything itself, but calls the render function instead.
|
|
82
82
|
*
|
|
83
83
|
* **Example**
|
|
84
84
|
*
|
|
@@ -144,6 +144,8 @@ const granularities: GranularityOption[] = [
|
|
|
144
144
|
export default class QueryBuilder extends React.Component<QueryBuilderProps, QueryBuilderInternalState> {
|
|
145
145
|
static contextType = CubeContext;
|
|
146
146
|
|
|
147
|
+
context!: React.ContextType<typeof CubeContext>;
|
|
148
|
+
|
|
147
149
|
static defaultProps = {
|
|
148
150
|
cubeApi: null,
|
|
149
151
|
stateChangeHeuristics: null,
|
|
@@ -278,10 +280,6 @@ export default class QueryBuilder extends React.Component<QueryBuilderProps, Que
|
|
|
278
280
|
// TypeScript field declarations into `everything-else`, which the configured
|
|
279
281
|
// order puts after `lifecycle`. Runtime is unaffected: field initializers run
|
|
280
282
|
// right after `super()`, so the constructor's assignments still win.
|
|
281
|
-
//
|
|
282
|
-
// `this.context` is not re-declared: React types it as `any`, and a field
|
|
283
|
-
// declaration would be emitted at runtime and shadow the context React
|
|
284
|
-
// assigns.
|
|
285
283
|
private mutexObj: MutexObj;
|
|
286
284
|
|
|
287
285
|
private orderMembersOrderKeys: string[];
|
package/src/QueryRenderer.tsx
CHANGED
|
@@ -20,6 +20,8 @@ import type {
|
|
|
20
20
|
export default class QueryRenderer extends React.Component<QueryRendererProps, QueryRendererState> {
|
|
21
21
|
static contextType = CubeContext;
|
|
22
22
|
|
|
23
|
+
context!: React.ContextType<typeof CubeContext>;
|
|
24
|
+
|
|
23
25
|
static defaultProps = {
|
|
24
26
|
cubeApi: null,
|
|
25
27
|
query: null,
|
|
@@ -83,10 +85,6 @@ export default class QueryRenderer extends React.Component<QueryRendererProps, Q
|
|
|
83
85
|
// TypeScript field declarations into `everything-else`, which the configured
|
|
84
86
|
// order puts after `lifecycle`. Runtime is unaffected: field initializers run
|
|
85
87
|
// right after `super()`, so the constructor's assignments still win.
|
|
86
|
-
//
|
|
87
|
-
// `this.context` is not re-declared: React types it as `any`, and a field
|
|
88
|
-
// declaration would be emitted at runtime and shadow the context React
|
|
89
|
-
// assigns.
|
|
90
88
|
private mutexObj: MutexObj;
|
|
91
89
|
|
|
92
90
|
cubeApi(): CubeApi {
|
package/src/hooks/cube-query.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
} from '../types';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* A React hook for executing Cube
|
|
25
|
+
* A React hook for executing Cube queries
|
|
26
26
|
* ```js
|
|
27
27
|
* import React from 'react';
|
|
28
28
|
* import { Table } from 'antd';
|
|
@@ -75,15 +75,33 @@ export function useCubeQuery(
|
|
|
75
75
|
const [progress, setProgress] = useState<ProgressResponse | null>(null);
|
|
76
76
|
const [error, setError] = useState<Error | null>(null);
|
|
77
77
|
const context = useContext(CubeContext);
|
|
78
|
+
const requestIdRef = useRef(0);
|
|
79
|
+
const hasStartedRequestRef = useRef(false);
|
|
78
80
|
|
|
79
81
|
let subscribeRequest: UnsubscribeObj | null = null;
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
83
|
+
function isCurrentRequest(requestId: number) {
|
|
84
|
+
return requestId === requestIdRef.current;
|
|
85
|
+
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
function startRequest() {
|
|
88
|
+
hasStartedRequestRef.current = true;
|
|
89
|
+
|
|
90
|
+
return ++requestIdRef.current;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function createProgressCallback(requestId: number): ProgressCallback {
|
|
94
|
+
return (progressResult) => {
|
|
95
|
+
if (isCurrentRequest(requestId)) {
|
|
96
|
+
// `progressResponse` is not part of the public `ProgressResult` API
|
|
97
|
+
setProgress(
|
|
98
|
+
(progressResult as unknown as ProgressResultWithResponse).progressResponse
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function fetchQuery(requestId: number) {
|
|
87
105
|
const { resetResultSetOnChange } = options;
|
|
88
106
|
const cubeApi = options.cubeApi || context?.cubeApi;
|
|
89
107
|
|
|
@@ -97,25 +115,38 @@ export function useCubeQuery(
|
|
|
97
115
|
|
|
98
116
|
setError(null);
|
|
99
117
|
setLoading(true);
|
|
118
|
+
setProgress(null);
|
|
100
119
|
|
|
101
120
|
try {
|
|
102
121
|
const response = await cubeApi.load(query, {
|
|
103
122
|
mutexObj: mutexRef.current,
|
|
104
123
|
mutexKey: 'query',
|
|
105
|
-
progressCallback,
|
|
124
|
+
progressCallback: createProgressCallback(requestId),
|
|
106
125
|
castNumerics: Boolean(typeof options.castNumerics === 'boolean' ? options.castNumerics : context?.options?.castNumerics),
|
|
107
126
|
...(options.cache ? { cache: options.cache } : {}),
|
|
108
127
|
});
|
|
109
128
|
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
if (isCurrentRequest(requestId)) {
|
|
130
|
+
setResultSet(response);
|
|
131
|
+
setProgress(null);
|
|
132
|
+
}
|
|
112
133
|
} catch (loadError) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
134
|
+
if (isCurrentRequest(requestId)) {
|
|
135
|
+
setError(loadError as Error);
|
|
136
|
+
setResultSet(null);
|
|
137
|
+
setProgress(null);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (isCurrentRequest(requestId)) {
|
|
142
|
+
setLoading(false);
|
|
116
143
|
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function fetch() {
|
|
147
|
+
const requestId = startRequest();
|
|
117
148
|
|
|
118
|
-
|
|
149
|
+
await fetchQuery(requestId);
|
|
119
150
|
}
|
|
120
151
|
|
|
121
152
|
useEffect(() => {
|
|
@@ -129,6 +160,8 @@ export function useCubeQuery(
|
|
|
129
160
|
|
|
130
161
|
async function loadQuery() {
|
|
131
162
|
if (!skip && isQueryPresent(query)) {
|
|
163
|
+
const requestId = startRequest();
|
|
164
|
+
|
|
132
165
|
// `areQueriesEqual` is declared for a single query, and reads no more
|
|
133
166
|
// than `order` off one when given an array of queries
|
|
134
167
|
const previousQuery = currentQuery as DeeplyReadonly<Query> | null;
|
|
@@ -142,6 +175,7 @@ export function useCubeQuery(
|
|
|
142
175
|
|
|
143
176
|
setError(null);
|
|
144
177
|
setLoading(true);
|
|
178
|
+
setProgress(null);
|
|
145
179
|
|
|
146
180
|
try {
|
|
147
181
|
if (subscribeRequest) {
|
|
@@ -155,34 +189,43 @@ export function useCubeQuery(
|
|
|
155
189
|
{
|
|
156
190
|
mutexObj: mutexRef.current,
|
|
157
191
|
mutexKey: 'query',
|
|
158
|
-
progressCallback,
|
|
192
|
+
progressCallback: createProgressCallback(requestId),
|
|
159
193
|
...(options.cache ? { cache: options.cache } : {}),
|
|
160
194
|
},
|
|
161
195
|
(e, result) => {
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
196
|
+
if (isCurrentRequest(requestId)) {
|
|
197
|
+
if (e) {
|
|
198
|
+
setError(e);
|
|
199
|
+
} else {
|
|
200
|
+
setResultSet(result);
|
|
201
|
+
}
|
|
202
|
+
setLoading(false);
|
|
203
|
+
setProgress(null);
|
|
166
204
|
}
|
|
167
|
-
setLoading(false);
|
|
168
|
-
setProgress(null);
|
|
169
205
|
}
|
|
170
206
|
);
|
|
171
207
|
} else {
|
|
172
|
-
await
|
|
208
|
+
await fetchQuery(requestId);
|
|
173
209
|
}
|
|
174
210
|
} catch (e) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
211
|
+
if (isCurrentRequest(requestId)) {
|
|
212
|
+
setError(e as Error);
|
|
213
|
+
setResultSet(null);
|
|
214
|
+
setLoading(false);
|
|
215
|
+
setProgress(null);
|
|
216
|
+
}
|
|
179
217
|
}
|
|
218
|
+
} else if (hasStartedRequestRef.current) {
|
|
219
|
+
setLoading(false);
|
|
220
|
+
setProgress(null);
|
|
180
221
|
}
|
|
181
222
|
}
|
|
182
223
|
|
|
183
224
|
loadQuery();
|
|
184
225
|
|
|
185
226
|
return () => {
|
|
227
|
+
requestIdRef.current += 1;
|
|
228
|
+
|
|
186
229
|
if (subscribeRequest) {
|
|
187
230
|
subscribeRequest.unsubscribe();
|
|
188
231
|
subscribeRequest = null;
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @menuCategory Reference
|
|
5
5
|
* @subcategory Frontend
|
|
6
6
|
* @menuOrder 3
|
|
7
|
-
* @description `@cubejs-client/react` provides React Components for easy Cube
|
|
7
|
+
* @description `@cubejs-client/react` provides React Components for easy Cube integration in a React app.
|
|
8
8
|
*/
|
|
9
9
|
import QueryRenderer from './QueryRenderer';
|
|
10
10
|
import QueryRendererWithTotals from './QueryRendererWithTotals';
|
package/src/types.ts
CHANGED
|
@@ -86,7 +86,7 @@ export type QueryRendererProps = {
|
|
|
86
86
|
query: Query | Query[];
|
|
87
87
|
queries?: { [key: string]: Query };
|
|
88
88
|
/**
|
|
89
|
-
* Indicates whether the generated by `Cube
|
|
89
|
+
* Indicates whether the generated by `Cube` SQL Code should be requested. See [rest-api#sql](/reference/rest-api#v1sql). When set to `only` then only the request to [/v1/sql](/reference/rest-api#v1sql) will be performed. When set to `true` the sql request will be performed along with the query request. Will not be performed if set to `false`
|
|
90
90
|
*/
|
|
91
91
|
loadSql?: 'only' | boolean;
|
|
92
92
|
/**
|
|
@@ -245,19 +245,19 @@ export type QueryBuilderRenderProps = {
|
|
|
245
245
|
|
|
246
246
|
availableFilterMembers: Array<AvailableCube<TCubeMeasure> | AvailableCube<TCubeDimension>>;
|
|
247
247
|
/**
|
|
248
|
-
* An array of available measures to select. They are loaded via the API from Cube
|
|
248
|
+
* An array of available measures to select. They are loaded via the API from Cube Backend.
|
|
249
249
|
*/
|
|
250
250
|
availableMeasures: TCubeMeasure[];
|
|
251
251
|
/**
|
|
252
|
-
* An array of available dimensions to select. They are loaded via the API from Cube
|
|
252
|
+
* An array of available dimensions to select. They are loaded via the API from Cube Backend.
|
|
253
253
|
*/
|
|
254
254
|
availableDimensions: TCubeDimension[];
|
|
255
255
|
/**
|
|
256
|
-
* An array of available time dimensions to select. They are loaded via the API from Cube
|
|
256
|
+
* An array of available time dimensions to select. They are loaded via the API from Cube Backend.
|
|
257
257
|
*/
|
|
258
258
|
availableTimeDimensions: TCubeDimension[];
|
|
259
259
|
/**
|
|
260
|
-
* An array of available segments to select. They are loaded via the API from Cube
|
|
260
|
+
* An array of available segments to select. They are loaded via the API from Cube Backend.
|
|
261
261
|
*/
|
|
262
262
|
availableSegments: TCubeSegment[];
|
|
263
263
|
|