@sisense/sdk-query-client 1.7.2 → 1.9.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.
@@ -1,8 +1,10 @@
1
- import { DataSourceField, ExecutingCsvQueryResult, ExecutingPivotQueryResult, ExecutingQueryResult, PivotQueryDescription, QueryDescription, QueryExecutionConfig } from './types.js';
1
+ import { DataSourceField, DataSourceMetadata, DataSourceSchema, ExecutingCsvQueryResult, ExecutingPivotQueryResult, ExecutingQueryResult, PivotQueryDescription, QueryDescription, QueryExecutionConfig } from './types.js';
2
2
  import { DataSource } from '@sisense/sdk-data';
3
3
  export interface QueryClient {
4
4
  executeQuery(params: QueryDescription, config?: QueryExecutionConfig): ExecutingQueryResult;
5
5
  executeCsvQuery(params: QueryDescription, config?: QueryExecutionConfig): ExecutingCsvQueryResult;
6
6
  executePivotQuery(params: PivotQueryDescription, config?: QueryExecutionConfig): ExecutingPivotQueryResult;
7
7
  getDataSourceFields(dataSource: DataSource): Promise<DataSourceField[]>;
8
+ getDataSourceSchema(datasourceName: string): Promise<DataSourceSchema>;
9
+ getDataSourceList(): Promise<DataSourceMetadata[]>;
8
10
  }
@@ -1,9 +1,8 @@
1
- /* eslint-disable complexity */
2
- /* eslint-disable max-lines */
3
1
  import { v4 as uuid } from 'uuid';
4
2
  import merge from 'ts-deepmerge';
5
3
  import { isPivotAttribute, isPivotMeasure, DEFAULT_PIVOT_GRAND_TOTALS, isDataSourceInfo, } from '@sisense/sdk-data';
6
4
  import { applyHighlightFilters, matchHighlightsWithAttributes } from './metadata/highlights.js';
5
+ import { getPivotMetadataStats, normalizeLastRowSorting, preparePivotRowJaqlSortOptions, } from './pivot/pivot-query-utils.js';
7
6
  const JAQL_BY_CSDK = 'ComposeSDK';
8
7
  /**
9
8
  * @internal
@@ -62,8 +61,10 @@ export function getPivotJaqlQueryPayload(pivotQueryDescription, shouldSkipHighli
62
61
  }
63
62
  return queryPayload;
64
63
  }
65
- function jaqlPivotAttribute(a, panel, index) {
66
- return Object.assign(Object.assign(Object.assign({}, (isPivotAttribute(a) ? a.attribute.jaql() : a.jaql())), (isPivotAttribute(a) && a.includeSubTotals ? { format: { subtotal: true } } : {})), { panel, field: { index: index, id: `${panel}-${index}` } });
64
+ function jaqlPivotAttribute(a, panel, index, metadataStats) {
65
+ const isSortedRowAttribute = panel === 'rows' && isPivotAttribute(a) && a.sort && a.sort.direction !== 'sortNone';
66
+ const jaql = Object.assign(Object.assign({}, (isPivotAttribute(a) ? a.attribute.jaql(true) : a.jaql(true))), (isSortedRowAttribute && preparePivotRowJaqlSortOptions(a.sort, index, metadataStats)));
67
+ return Object.assign(Object.assign({ jaql }, (isPivotAttribute(a) && a.includeSubTotals ? { format: { subtotal: true } } : {})), { panel, field: { index: index, id: `${panel}-${index}` } });
67
68
  }
68
69
  function jaqlPivotMeasure(m, panel, index) {
69
70
  return Object.assign(Object.assign({}, (isPivotMeasure(m)
@@ -82,10 +83,11 @@ function jaqlPivotMeasure(m, panel, index) {
82
83
  */
83
84
  function preparePivotQueryMetadata(pivotMetadataDescription, shouldSkipHighlightsWithoutAttributes) {
84
85
  const { rowsAttributes, columnsAttributes, measures, filters, filterRelations, highlights } = pivotMetadataDescription;
86
+ const metadataStats = getPivotMetadataStats(rowsAttributes, columnsAttributes, measures);
85
87
  let fieldIndex = 0; // used as a global counter to build field.index in Jaql MetadataItem
86
- const rowsAttributesMetadata = rowsAttributes.map((a, index) => jaqlPivotAttribute(a, 'rows', index + fieldIndex));
88
+ const rowsAttributesMetadata = rowsAttributes.map((a, index) => jaqlPivotAttribute(a, 'rows', index + fieldIndex, metadataStats));
87
89
  fieldIndex = fieldIndex + rowsAttributes.length;
88
- const columnsAttributesMetadata = columnsAttributes.map((a, index) => jaqlPivotAttribute(a, 'columns', index + fieldIndex));
90
+ const columnsAttributesMetadata = columnsAttributes.map((a, index) => jaqlPivotAttribute(a, 'columns', index + fieldIndex, metadataStats));
89
91
  fieldIndex = fieldIndex + columnsAttributes.length;
90
92
  const attributesMetadata = [
91
93
  ...rowsAttributesMetadata,
@@ -93,7 +95,9 @@ function preparePivotQueryMetadata(pivotMetadataDescription, shouldSkipHighlight
93
95
  ];
94
96
  const measuresMetadata = measures.map((m, index) => jaqlPivotMeasure(m, 'measures', index + fieldIndex));
95
97
  const filtersMetadata = prepareFilterMetadata(attributesMetadata, filters, filterRelations, highlights, shouldSkipHighlightsWithoutAttributes);
96
- return [...attributesMetadata, ...measuresMetadata, ...filtersMetadata];
98
+ const metadata = [...attributesMetadata, ...measuresMetadata, ...filtersMetadata];
99
+ normalizeLastRowSorting(metadata, metadataStats);
100
+ return metadata;
97
101
  }
98
102
  /**
99
103
  * Prepares the options part of the JAQL payload for a pivot query.
@@ -0,0 +1,38 @@
1
+ import type { Attribute, Measure, PivotAttribute, PivotMeasure, PivotRowsSort, SortDirection } from '@sisense/sdk-data';
2
+ import { MetadataItem } from '../../types.js';
3
+ /**
4
+ * Represents statistics about a pivot table metadata.
5
+ */
6
+ export type PivotMetadataStats = {
7
+ rowsCount: number;
8
+ columnsCount: number;
9
+ measuresCount: number;
10
+ };
11
+ /**
12
+ * Calculates statistics about the pivot table metadata.
13
+ */
14
+ export declare function getPivotMetadataStats(rowsAttributes: (Attribute | PivotAttribute)[], columnsAttributes: (Attribute | PivotAttribute)[], measures: (Measure | PivotMeasure)[]): PivotMetadataStats;
15
+ /**
16
+ * Converts sort direction to JAQL sort direction.
17
+ */
18
+ export declare function convertSortDirectionToJaqlSort(direction: SortDirection): "asc" | "desc" | "none";
19
+ /**
20
+ * Prepares JAQL sort options for pivot table row.
21
+ */
22
+ export declare function preparePivotRowJaqlSortOptions(sort: PivotRowsSort, rowIndex: number, metadataStats: PivotMetadataStats): {
23
+ sort: string;
24
+ sortDetails: {
25
+ dir: string;
26
+ field?: number | undefined;
27
+ measurePath?: Record<number, string | number> | undefined;
28
+ sortingLastDimension?: boolean | undefined;
29
+ initialized?: boolean | undefined;
30
+ };
31
+ };
32
+ /**
33
+ * Normalizes sorting for the last row of the pivot table.
34
+ *
35
+ * According to the existing pivot JAQL structure,the sorting configuration of the last row
36
+ * should be located inside the target measure metadata
37
+ */
38
+ export declare function normalizeLastRowSorting(metadata: MetadataItem[], metadataStats: PivotMetadataStats): void;
@@ -0,0 +1,76 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ /**
13
+ * Calculates statistics about the pivot table metadata.
14
+ */
15
+ export function getPivotMetadataStats(rowsAttributes, columnsAttributes, measures) {
16
+ return {
17
+ rowsCount: rowsAttributes.length,
18
+ columnsCount: columnsAttributes.length,
19
+ measuresCount: measures.length,
20
+ };
21
+ }
22
+ /**
23
+ * Converts sort direction to JAQL sort direction.
24
+ */
25
+ export function convertSortDirectionToJaqlSort(direction) {
26
+ switch (direction) {
27
+ case 'sortAsc':
28
+ return 'asc';
29
+ case 'sortDesc':
30
+ return 'desc';
31
+ default:
32
+ return 'none';
33
+ }
34
+ }
35
+ /**
36
+ * Prepares JAQL sort options for pivot table row.
37
+ */
38
+ export function preparePivotRowJaqlSortOptions(sort, rowIndex, metadataStats) {
39
+ const sortDirection = convertSortDirectionToJaqlSort(sort.direction);
40
+ const isLastRow = rowIndex === metadataStats.rowsCount - 1;
41
+ const sortDetails = {
42
+ dir: sortDirection,
43
+ initialized: true,
44
+ field: sort.by && 'valuesIndex' in sort.by
45
+ ? metadataStats.rowsCount + metadataStats.columnsCount + sort.by.valuesIndex
46
+ : rowIndex,
47
+ };
48
+ if (isLastRow) {
49
+ sortDetails.sortingLastDimension = true;
50
+ }
51
+ if (sort.by) {
52
+ sortDetails.measurePath = (sort.by.columnsMembersPath || []).reduce((path, columnMember, columnIndex) => (Object.assign(Object.assign({}, path), { [metadataStats.rowsCount + columnIndex]: columnMember })), {});
53
+ }
54
+ return {
55
+ sort: sortDirection,
56
+ sortDetails,
57
+ };
58
+ }
59
+ /**
60
+ * Normalizes sorting for the last row of the pivot table.
61
+ *
62
+ * According to the existing pivot JAQL structure,the sorting configuration of the last row
63
+ * should be located inside the target measure metadata
64
+ */
65
+ export function normalizeLastRowSorting(metadata, metadataStats) {
66
+ const lastRowMetadata = metadata[metadataStats.rowsCount - 1];
67
+ const isSortedByMeasure = lastRowMetadata.jaql.sortDetails &&
68
+ lastRowMetadata.jaql.sortDetails.field !== metadataStats.rowsCount - 1;
69
+ if (isSortedByMeasure) {
70
+ const targetMeasureMetadata = metadata[lastRowMetadata.jaql.sortDetails.field];
71
+ const _a = lastRowMetadata.jaql, { sortDetails, sort } = _a, jaqlWithoutSortOptions = __rest(_a, ["sortDetails", "sort"]);
72
+ targetMeasureMetadata.jaql.sortDetails = sortDetails;
73
+ targetMeasureMetadata.jaql.sort = sort;
74
+ lastRowMetadata.jaql = jaqlWithoutSortOptions;
75
+ }
76
+ }
@@ -1,6 +1,6 @@
1
1
  import { DataSource } from '@sisense/sdk-data';
2
2
  import { HttpClient } from '@sisense/sdk-rest-client';
3
- import { AbortRequestFunction, DataSourceField, JaqlResponse, JaqlQueryPayload, QueryGuid, DataSourceSchema } from '../types.js';
3
+ import { AbortRequestFunction, DataSourceField, JaqlResponse, JaqlQueryPayload, QueryGuid, DataSourceSchema, DataSourceMetadata } from '../types.js';
4
4
  type RequestSendingResult<T> = {
5
5
  responsePromise: Promise<T>;
6
6
  abortHttpRequest: AbortRequestFunction;
@@ -9,6 +9,11 @@ export declare class QueryApiDispatcher {
9
9
  private httpClient;
10
10
  constructor(httpClient: HttpClient);
11
11
  getDataSourceFields(dataSource: DataSource, count?: number, offset?: number): Promise<DataSourceField[]>;
12
+ /**
13
+ * Returns a list of data sources.
14
+ * This method works with user of viewer role or above.
15
+ */
16
+ getDataSourceList(): Promise<DataSourceMetadata[]>;
12
17
  /**
13
18
  * Returns the schema of a data source by its name.
14
19
  */
@@ -28,6 +28,16 @@ export class QueryApiDispatcher {
28
28
  }
29
29
  });
30
30
  }
31
+ /**
32
+ * Returns a list of data sources.
33
+ * This method works with user of viewer role or above.
34
+ */
35
+ getDataSourceList() {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ const url = `${API_DATASOURCES_BASE_PATH}/?sharedWith=r,w`;
38
+ return this.httpClient.get(url);
39
+ });
40
+ }
31
41
  /**
32
42
  * Returns the schema of a data source by its name.
33
43
  */
@@ -41,7 +51,17 @@ export class QueryApiDispatcher {
41
51
  const url = getJaqlUrl(dataSource);
42
52
  const abortController = new AbortController();
43
53
  return {
44
- responsePromise: this.httpClient.post(url, jaqlPayload, undefined, abortController.signal),
54
+ responsePromise: this.httpClient
55
+ .post(url, jaqlPayload, undefined, abortController.signal)
56
+ .then((response) => {
57
+ if (Array.isArray(response)) {
58
+ return {
59
+ values: [],
60
+ metadata: [],
61
+ };
62
+ }
63
+ return response;
64
+ }),
45
65
  abortHttpRequest: (reason) => abortController.abort(reason),
46
66
  };
47
67
  }
@@ -80,7 +100,7 @@ export class QueryApiDispatcher {
80
100
  yield this.httpClient.post(regularUrl, payload);
81
101
  }
82
102
  catch (error) {
83
- if (error.status === 404) {
103
+ if (error.status === '404') {
84
104
  // probably this datasource is live and requires a different URL for canceling queries
85
105
  const liveUrl = getLiveCancelQueryUrl(dataSource);
86
106
  yield this.httpClient.post(liveUrl, payload);
@@ -1,6 +1,6 @@
1
- import { DataSourceField, ExecutingCsvQueryResult, ExecutingPivotQueryResult, ExecutingQueryResult, PivotQueryDescription, QueryDescription, QueryExecutionConfig } from './types.js';
1
+ import { DataSourceField, DataSourceMetadata, DataSourceSchema, ExecutingCsvQueryResult, ExecutingPivotQueryResult, ExecutingQueryResult, PivotQueryDescription, QueryDescription, QueryExecutionConfig } from './types.js';
2
2
  import { QueryClient } from './interfaces.js';
3
- import { DataSourceInfo, DataSource } from '@sisense/sdk-data';
3
+ import { DataSource } from '@sisense/sdk-data';
4
4
  import { HttpClient } from '@sisense/sdk-rest-client';
5
5
  import { PivotClient } from '@sisense/sdk-pivot-client';
6
6
  /** @internal */
@@ -31,9 +31,13 @@ export declare class DimensionalQueryClient implements QueryClient {
31
31
  executePivotQuery(pivotQueryDescription: PivotQueryDescription, config?: QueryExecutionConfig): ExecutingPivotQueryResult;
32
32
  getDataSourceFields(dataSource: DataSource, count?: number, offset?: number): Promise<DataSourceField[]>;
33
33
  /**
34
- * Get info about data source
34
+ * Returns the schema of a data source by its name.
35
35
  */
36
- getDataSourceInfo(datasourceName: string): Promise<DataSourceInfo>;
36
+ getDataSourceSchema(datasourceName: string): Promise<DataSourceSchema>;
37
+ /**
38
+ * Returns a list of data sources
39
+ */
40
+ getDataSourceList(): Promise<DataSourceMetadata[]>;
37
41
  }
38
42
  /**
39
43
  * Validates query description
@@ -97,15 +97,19 @@ export class DimensionalQueryClient {
97
97
  });
98
98
  }
99
99
  /**
100
- * Get info about data source
100
+ * Returns the schema of a data source by its name.
101
101
  */
102
- getDataSourceInfo(datasourceName) {
102
+ getDataSourceSchema(datasourceName) {
103
103
  return __awaiter(this, void 0, void 0, function* () {
104
- const completeDataSourceSchema = yield this.queryApi.getDataSourceSchema(datasourceName);
105
- return {
106
- title: completeDataSourceSchema.title,
107
- type: completeDataSourceSchema.type === 'extract' ? 'elasticube' : 'live',
108
- };
104
+ return this.queryApi.getDataSourceSchema(datasourceName);
105
+ });
106
+ }
107
+ /**
108
+ * Returns a list of data sources
109
+ */
110
+ getDataSourceList() {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ return this.queryApi.getDataSourceList();
109
113
  });
110
114
  }
111
115
  }
@@ -2,4 +2,5 @@ import { AbstractTranslatableError } from '@sisense/sdk-common';
2
2
  import { PACKAGE_NAMESPACE } from './resources/index.js';
3
3
  export declare class TranslatableError extends AbstractTranslatableError<typeof PACKAGE_NAMESPACE> {
4
4
  constructor(translationKey: string, interpolationOptions?: Record<string, string>);
5
+ get status(): string;
5
6
  }
@@ -8,4 +8,7 @@ export class TranslatableError extends AbstractTranslatableError {
8
8
  interpolationOptions: interpolationOptions,
9
9
  }, i18nextInstance.t);
10
10
  }
11
+ get status() {
12
+ return this.interpolationOptions.status;
13
+ }
11
14
  }
package/dist/types.d.ts CHANGED
@@ -72,6 +72,42 @@ export type ExecutingPivotQueryResult = {
72
72
  resultPromise: Promise<PivotQueryResultData>;
73
73
  cancel: (reason?: string) => Promise<void>;
74
74
  };
75
+ interface DecimalAbbreviations {
76
+ k: boolean;
77
+ m: boolean;
78
+ b: boolean;
79
+ t: boolean;
80
+ }
81
+ export declare enum CurrencyPosition {
82
+ PRE = "pre",
83
+ POST = "post"
84
+ }
85
+ export type NumericMask = {
86
+ isdefault?: boolean;
87
+ abbreviations?: DecimalAbbreviations;
88
+ decimals?: 'auto' | number | string;
89
+ currency?: {
90
+ symbol: string;
91
+ position: CurrencyPosition;
92
+ };
93
+ percent?: boolean;
94
+ number?: {
95
+ separated: boolean;
96
+ };
97
+ separated?: boolean;
98
+ type?: string;
99
+ };
100
+ export type DatetimeMask = {
101
+ isdefault?: boolean;
102
+ years: string;
103
+ quarters: string;
104
+ months: string;
105
+ weeks: string;
106
+ minutes: string;
107
+ days: string;
108
+ type: string;
109
+ dateAndTime?: string;
110
+ };
75
111
  export type MetadataItem = {
76
112
  instanceid?: string;
77
113
  measure?: MetadataItemJaql;
@@ -79,9 +115,7 @@ export type MetadataItem = {
79
115
  panel?: string;
80
116
  isScope?: boolean;
81
117
  format?: {
82
- mask?: {
83
- [level: string]: string | undefined;
84
- };
118
+ mask?: Partial<DatetimeMask> | Partial<NumericMask>;
85
119
  number?: string;
86
120
  subtotal?: boolean;
87
121
  width?: number;
@@ -124,11 +158,19 @@ export type MetadataItemJaql = {
124
158
  };
125
159
  };
126
160
  title?: string;
161
+ type?: string;
127
162
  formula?: string;
128
163
  context?: {
129
164
  [itemId: string]: MetadataItemJaql;
130
165
  };
131
166
  filter?: MetadataItem;
167
+ sortDetails?: {
168
+ dir: string;
169
+ field?: number;
170
+ measurePath?: Record<number, string | number>;
171
+ sortingLastDimension?: boolean;
172
+ initialized?: boolean;
173
+ };
132
174
  };
133
175
  export type JaqlQueryPayload = QueryOptions & {
134
176
  filterRelations?: FilterRelationsJaql;
@@ -159,5 +201,10 @@ export type DataSourceSchema = {
159
201
  title: string;
160
202
  type: 'extract' | 'live';
161
203
  } & AnyObject;
204
+ export type DataSourceMetadata = {
205
+ title: string;
206
+ live: boolean;
207
+ };
162
208
  export type AbortRequestFunction = (reason?: string) => void;
163
209
  export type QueryGuid = string;
210
+ export {};
package/dist/types.js CHANGED
@@ -1 +1,5 @@
1
- export {};
1
+ export var CurrencyPosition;
2
+ (function (CurrencyPosition) {
3
+ CurrencyPosition["PRE"] = "pre";
4
+ CurrencyPosition["POST"] = "post";
5
+ })(CurrencyPosition = CurrencyPosition || (CurrencyPosition = {}));
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "Sisense",
12
12
  "Compose SDK"
13
13
  ],
14
- "version": "1.7.2",
14
+ "version": "1.9.0",
15
15
  "type": "module",
16
16
  "exports": "./dist/index.js",
17
17
  "main": "./dist/index.js",
@@ -20,10 +20,10 @@
20
20
  "author": "Sisense",
21
21
  "license": "SEE LICENSE IN LICENSE.md",
22
22
  "dependencies": {
23
- "@sisense/sdk-common": "^1.7.2",
24
- "@sisense/sdk-data": "^1.7.2",
25
- "@sisense/sdk-pivot-client": "^1.7.2",
26
- "@sisense/sdk-rest-client": "^1.7.2",
23
+ "@sisense/sdk-common": "^1.9.0",
24
+ "@sisense/sdk-data": "^1.9.0",
25
+ "@sisense/sdk-pivot-client": "^1.9.0",
26
+ "@sisense/sdk-rest-client": "^1.9.0",
27
27
  "@sisense/task-manager": "^0.1.0",
28
28
  "numeral": "^2.0.6",
29
29
  "ts-deepmerge": "6.0.2",