@cubejs-client/core 0.29.51 → 0.30.0

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/index.d.ts CHANGED
@@ -724,11 +724,11 @@ declare module '@cubejs-client/core' {
724
724
 
725
725
  export type Filter = BinaryFilter | UnaryFilter | LogicalOrFilter | LogicalAndFilter;
726
726
  export type LogicalAndFilter = {
727
- and: (BinaryFilter | UnaryFilter | LogicalOrFilter)[];
727
+ and: Filter[];
728
728
  };
729
729
 
730
730
  export type LogicalOrFilter = {
731
- or: (BinaryFilter | UnaryFilter | LogicalAndFilter)[];
731
+ or: Filter[];
732
732
  };
733
733
 
734
734
  export interface BinaryFilter {
@@ -788,6 +788,10 @@ declare module '@cubejs-client/core' {
788
788
 
789
789
  export type TimeDimension = TimeDimensionComparison | TimeDimensionRanged;
790
790
 
791
+ type DeeplyReadonly<T> = {
792
+ readonly [K in keyof T]: DeeplyReadonly<T[K]>;
793
+ };
794
+
791
795
  export interface Query {
792
796
  measures?: string[];
793
797
  dimensions?: string[];
@@ -804,6 +808,36 @@ declare module '@cubejs-client/core' {
804
808
  total?: boolean;
805
809
  }
806
810
 
811
+ export type QueryRecordType<T extends DeeplyReadonly<Query | Query[]>> =
812
+ T extends DeeplyReadonly<Query[]> ? QueryArrayRecordType<T> :
813
+ T extends DeeplyReadonly<Query> ? SingleQueryRecordType<T> :
814
+ never;
815
+
816
+ type QueryArrayRecordType<T extends DeeplyReadonly<Query[]>> =
817
+ T extends readonly [infer First, ...infer Rest]
818
+ ? SingleQueryRecordType<First> | QueryArrayRecordType<Rest>
819
+ : never;
820
+
821
+ // If we can't infer any members at all, then return any.
822
+ type SingleQueryRecordType<T extends DeeplyReadonly<Query>> = ExtractMembers<T> extends never
823
+ ? any
824
+ : { [K in string & ExtractMembers<T>]: string | number | boolean | null };
825
+
826
+ type ExtractMembers<T extends DeeplyReadonly<Query>> =
827
+ | ( T extends { dimensions: readonly (infer Names)[]; } ? Names : never )
828
+ | ( T extends { measures: readonly (infer Names)[]; } ? Names : never )
829
+ | ( T extends { timeDimensions: (infer U); } ? ExtractTimeMembers<U> : never );
830
+
831
+ type ExtractTimeMembers<T> =
832
+ T extends readonly [infer First, ...infer Rest]
833
+ ? ExtractTimeMember<First> | ExtractTimeMembers<Rest>
834
+ : never;
835
+
836
+ type ExtractTimeMember<T> =
837
+ T extends { dimension: infer Dimension, granularity: infer Granularity }
838
+ ? Dimension | `${Dimension & string}.${Granularity & string}`
839
+ : never;
840
+
807
841
  export class ProgressResult {
808
842
  stage(): string;
809
843
  timeElapsed(): string;
@@ -944,7 +978,7 @@ declare module '@cubejs-client/core' {
944
978
  * If empty query is provided no filtering is done based on query context and all available members are retrieved.
945
979
  * @param query - context query to provide filtering of members available to add to this query
946
980
  */
947
- membersForQuery(query: Query | null, memberType: MemberType): TCubeMeasure[] | TCubeDimension[] | TCubeMember[];
981
+ membersForQuery(query: DeeplyReadonly<Query> | null, memberType: MemberType): TCubeMeasure[] | TCubeDimension[] | TCubeMember[];
948
982
 
949
983
  /**
950
984
  * Get meta information for a cube member
@@ -979,7 +1013,10 @@ declare module '@cubejs-client/core' {
979
1013
  * @order 2
980
1014
  */
981
1015
  export class CubejsApi {
982
- load(query: Query | Query[], options?: LoadMethodOptions): Promise<ResultSet>;
1016
+ load<QueryType extends DeeplyReadonly<Query | Query[]>>(
1017
+ query: QueryType,
1018
+ options?: LoadMethodOptions,
1019
+ ): Promise<ResultSet<QueryRecordType<QueryType>>>;
983
1020
  /**
984
1021
  * Fetch data for the passed `query`.
985
1022
  *
@@ -1004,13 +1041,18 @@ declare module '@cubejs-client/core' {
1004
1041
  * ```
1005
1042
  * @param query - [Query object](query-format)
1006
1043
  */
1007
- load(query: Query | Query[], options?: LoadMethodOptions, callback?: LoadMethodCallback<ResultSet>): void;
1008
- load(
1009
- query: Query | Query[],
1044
+ load<QueryType extends DeeplyReadonly<Query | Query[]>>(
1045
+ query: QueryType,
1046
+ options?: LoadMethodOptions,
1047
+ callback?: LoadMethodCallback<ResultSet<QueryRecordType<QueryType>>>,
1048
+ ): void;
1049
+
1050
+ load<QueryType extends DeeplyReadonly<Query | Query[]>>(
1051
+ query: QueryType,
1010
1052
  options?: LoadMethodOptions,
1011
1053
  callback?: LoadMethodCallback<ResultSet>,
1012
1054
  responseFormat?: string
1013
- ): Promise<ResultSet>;
1055
+ ): Promise<ResultSet<QueryRecordType<QueryType>>>;
1014
1056
 
1015
1057
  /**
1016
1058
  * Allows you to fetch data and receive updates over time. See [Real-Time Data Fetch](real-time-data-fetch)
@@ -1036,14 +1078,18 @@ declare module '@cubejs-client/core' {
1036
1078
  * );
1037
1079
  * ```
1038
1080
  */
1039
- subscribe(query: Query | Query[], options: LoadMethodOptions | null, callback: LoadMethodCallback<ResultSet>): void;
1081
+ subscribe<QueryType extends DeeplyReadonly<Query | Query[]>>(
1082
+ query: QueryType,
1083
+ options: LoadMethodOptions | null,
1084
+ callback: LoadMethodCallback<ResultSet<QueryRecordType<QueryType>>>,
1085
+ ): void;
1040
1086
 
1041
- sql(query: Query | Query[], options?: LoadMethodOptions): Promise<SqlQuery>;
1087
+ sql(query: DeeplyReadonly<Query | Query[]>, options?: LoadMethodOptions): Promise<SqlQuery>;
1042
1088
  /**
1043
1089
  * Get generated SQL string for the given `query`.
1044
1090
  * @param query - [Query object](query-format)
1045
1091
  */
1046
- sql(query: Query | Query[], options?: LoadMethodOptions, callback?: LoadMethodCallback<SqlQuery>): void;
1092
+ sql(query: DeeplyReadonly<Query | Query[]>, options?: LoadMethodOptions, callback?: LoadMethodCallback<SqlQuery>): void;
1047
1093
 
1048
1094
  meta(options?: LoadMethodOptions): Promise<Meta>;
1049
1095
  /**
@@ -1051,11 +1097,11 @@ declare module '@cubejs-client/core' {
1051
1097
  */
1052
1098
  meta(options?: LoadMethodOptions, callback?: LoadMethodCallback<Meta>): void;
1053
1099
 
1054
- dryRun(query: Query | Query[], options?: LoadMethodOptions): Promise<DryRunResponse>;
1100
+ dryRun(query: DeeplyReadonly<Query | Query[]>, options?: LoadMethodOptions): Promise<DryRunResponse>;
1055
1101
  /**
1056
1102
  * Get query related meta without query execution
1057
1103
  */
1058
- dryRun(query: Query | Query[], options: LoadMethodOptions, callback?: LoadMethodCallback<DryRunResponse>): void;
1104
+ dryRun(query: DeeplyReadonly<Query | Query[]>, options: LoadMethodOptions, callback?: LoadMethodCallback<DryRunResponse>): void;
1059
1105
  }
1060
1106
 
1061
1107
  /**
@@ -1117,7 +1163,7 @@ declare module '@cubejs-client/core' {
1117
1163
  /**
1118
1164
  * @hidden
1119
1165
  */
1120
- export function isQueryPresent(query: Query | Query[] | null | undefined): boolean;
1166
+ export function isQueryPresent(query: DeeplyReadonly<Query | Query[]> | null | undefined): boolean;
1121
1167
  export function movePivotItem(
1122
1168
  pivotConfig: PivotConfig,
1123
1169
  sourceIndex: number,
@@ -1130,7 +1176,7 @@ declare module '@cubejs-client/core' {
1130
1176
  */
1131
1177
  export function moveItemInArray<T = any>(list: T[], sourceIndex: number, destinationIndex: number): T[];
1132
1178
 
1133
- export function defaultOrder(query: Query): { [key: string]: QueryOrder };
1179
+ export function defaultOrder(query: DeeplyReadonly<Query>): { [key: string]: QueryOrder };
1134
1180
 
1135
1181
  export interface TFlatFilter {
1136
1182
  /**
@@ -1164,9 +1210,9 @@ declare module '@cubejs-client/core' {
1164
1210
  /**
1165
1211
  * @hidden
1166
1212
  */
1167
- export function getQueryMembers(query: Query): string[];
1213
+ export function getQueryMembers(query: DeeplyReadonly<Query>): string[];
1168
1214
 
1169
- export function areQueriesEqual(query1: Query | null, query2: Query | null): boolean;
1215
+ export function areQueriesEqual(query1: DeeplyReadonly<Query> | null, query2: DeeplyReadonly<Query> | null): boolean;
1170
1216
 
1171
1217
  export type ProgressResponse = {
1172
1218
  stage: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubejs-client/core",
3
- "version": "0.29.51",
3
+ "version": "0.30.0",
4
4
  "engines": {},
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,5 +46,5 @@
46
46
  "eslint-plugin-node": "^5.2.1",
47
47
  "jest": "^26.0.1"
48
48
  },
49
- "gitHead": "44469b8ce956df50c2288194b550407bdb70c22d"
49
+ "gitHead": "bc4774e0945cdf0141e344657406115e8a4597f7"
50
50
  }
@@ -40,9 +40,16 @@ class HttpTransport {
40
40
  });
41
41
 
42
42
  return {
43
+ /* eslint no-unsafe-finally: off */
43
44
  async subscribe(callback) {
44
- const result = await runRequest();
45
- return callback(result, () => this.subscribe(callback));
45
+ let result = {
46
+ error: 'network Error' // add default error message
47
+ };
48
+ try {
49
+ result = await runRequest();
50
+ } finally {
51
+ return callback(result, () => this.subscribe(callback));
52
+ }
46
53
  }
47
54
  };
48
55
  }
@@ -1,6 +1,7 @@
1
1
  export default class RequestError extends Error {
2
- constructor(message, response) {
2
+ constructor(message, response, status) {
3
3
  super(message);
4
4
  this.response = response;
5
+ this.status = status;
5
6
  }
6
7
  }
package/src/index.js CHANGED
@@ -56,7 +56,7 @@ class CubejsApi {
56
56
  });
57
57
  this.pollInterval = options.pollInterval || 5;
58
58
  this.parseDateMeasures = options.parseDateMeasures;
59
-
59
+
60
60
  this.updateAuthorizationPromise = null;
61
61
  }
62
62
 
@@ -73,7 +73,7 @@ class CubejsApi {
73
73
  callback = options;
74
74
  options = undefined;
75
75
  }
76
-
76
+
77
77
  options = options || {};
78
78
 
79
79
  const mutexKey = options.mutexKey || 'default';
@@ -127,11 +127,11 @@ class CubejsApi {
127
127
  }
128
128
  return null;
129
129
  };
130
-
130
+
131
131
  if (options.subscribe && !skipAuthorizationUpdate) {
132
132
  await this.updateTransportAuthorization();
133
133
  }
134
-
134
+
135
135
  skipAuthorizationUpdate = false;
136
136
 
137
137
  if (response.status === 502) {
@@ -162,7 +162,7 @@ class CubejsApi {
162
162
  await requestInstance.unsubscribe();
163
163
  }
164
164
 
165
- const error = new RequestError(body.error, body); // TODO error class
165
+ const error = new RequestError(body.error, body, response.status); // TODO error class
166
166
  if (callback) {
167
167
  callback(error);
168
168
  } else {
@@ -209,7 +209,7 @@ class CubejsApi {
209
209
  await this.updateAuthorizationPromise;
210
210
  return;
211
211
  }
212
-
212
+
213
213
  if (typeof this.apiToken === 'function') {
214
214
  this.updateAuthorizationPromise = new Promise(async (resolve, reject) => {
215
215
  try {
@@ -224,7 +224,7 @@ class CubejsApi {
224
224
  this.updateAuthorizationPromise = null;
225
225
  }
226
226
  });
227
-
227
+
228
228
  await this.updateAuthorizationPromise;
229
229
  }
230
230
  }
@@ -241,7 +241,12 @@ class CubejsApi {
241
241
  responseFormat === ResultType.COMPACT &&
242
242
  query.responseFormat !== ResultType.COMPACT
243
243
  ) {
244
- query.responseFormat = ResultType.COMPACT;
244
+ return {
245
+ ...query,
246
+ responseFormat: ResultType.COMPACT,
247
+ };
248
+ } else {
249
+ return query;
245
250
  }
246
251
  }
247
252
 
@@ -287,11 +292,9 @@ class CubejsApi {
287
292
  load(query, options, callback, responseFormat = ResultType.DEFAULT) {
288
293
  if (responseFormat === ResultType.COMPACT) {
289
294
  if (Array.isArray(query)) {
290
- query.forEach((q) => {
291
- this.patchQueryInternal(q, ResultType.COMPACT);
292
- });
295
+ query = query.map((q) => this.patchQueryInternal(q, ResultType.COMPACT));
293
296
  } else {
294
- this.patchQueryInternal(query, ResultType.COMPACT);
297
+ query = this.patchQueryInternal(query, ResultType.COMPACT);
295
298
  }
296
299
  }
297
300
  return this.loadMethod(
@@ -318,11 +321,9 @@ class CubejsApi {
318
321
  subscribe(query, options, callback, responseFormat = ResultType.DEFAULT) {
319
322
  if (responseFormat === ResultType.COMPACT) {
320
323
  if (Array.isArray(query)) {
321
- query.forEach((q) => {
322
- this.patchQueryInternal(q, ResultType.COMPACT);
323
- });
324
+ query = query.map((q) => this.patchQueryInternal(q, ResultType.COMPACT));
324
325
  } else {
325
- this.patchQueryInternal(query, ResultType.COMPACT);
326
+ query = this.patchQueryInternal(query, ResultType.COMPACT);
326
327
  }
327
328
  }
328
329
  return this.loadMethod(