@sisense/sdk-cli 1.8.0 → 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.
- package/dist/commands/helpers.d.ts +6 -0
- package/dist/commands/helpers.js +83 -15
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/types.d.ts +22 -0
- package/package.json +9 -7
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { HttpClient } from '@sisense/sdk-rest-client';
|
|
2
2
|
import { DataModel } from '@sisense/sdk-data';
|
|
3
|
+
import { DataSourceField } from '@sisense/sdk-query-client';
|
|
4
|
+
import { DataSourceSchemaDataset } from '../types.js';
|
|
3
5
|
declare function getHttpClient(url: string, username?: string, password?: string, token?: string, wat?: string): HttpClient;
|
|
4
6
|
export declare const handleHttpClientLogin: (httpClient: HttpClient) => Promise<void>;
|
|
5
7
|
/**
|
|
@@ -27,4 +29,8 @@ export declare type SupportedOutputFilePathInfo = FilePathInfo & {
|
|
|
27
29
|
extension: SupportedOutputFileExtension;
|
|
28
30
|
};
|
|
29
31
|
declare function isSupportedOutputFile(filePathInfo: FilePathInfo): filePathInfo is SupportedOutputFilePathInfo;
|
|
32
|
+
/**
|
|
33
|
+
* Add 'description' property from datasource schema columns to datasource fields
|
|
34
|
+
*/
|
|
35
|
+
export declare function addDescriptionToFields(fields: DataSourceField[], datasets: DataSourceSchemaDataset[]): DataSourceField[];
|
|
30
36
|
export { getHttpClient, createDataModel, rewriteDataModel, writeFile, getFilePathInfo, isSupportedOutputFile, };
|
package/dist/commands/helpers.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-lines */
|
|
2
|
-
/* eslint-disable max-lines-per-function */
|
|
3
1
|
/* eslint-disable max-params */
|
|
4
2
|
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
5
3
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
@@ -11,7 +9,8 @@ import { HttpClient, getAuthenticator, WatAuthenticator, BearerAuthenticator, }
|
|
|
11
9
|
import { MetadataTypes } from '@sisense/sdk-data';
|
|
12
10
|
import { writeTypescript, writeJavascript } from '@sisense/sdk-modeling';
|
|
13
11
|
import path from 'path';
|
|
14
|
-
import
|
|
12
|
+
import levenshtein from 'js-levenshtein';
|
|
13
|
+
import { DimensionalQueryClient, } from '@sisense/sdk-query-client';
|
|
15
14
|
import { PKG_VERSION } from '../package-version.js';
|
|
16
15
|
import { trackCliError } from '@sisense/sdk-tracking';
|
|
17
16
|
function getHttpClient(url, username, password, token, wat) {
|
|
@@ -39,24 +38,74 @@ export const handleHttpClientLogin = async (httpClient) => {
|
|
|
39
38
|
}
|
|
40
39
|
return Promise.resolve();
|
|
41
40
|
};
|
|
41
|
+
async function retrieveDataSource(queryClient, dataSourceTitle) {
|
|
42
|
+
console.log('Getting data source... ');
|
|
43
|
+
const dataSourceList = await queryClient.getDataSourceList();
|
|
44
|
+
let minDistance = Number.MAX_SAFE_INTEGER;
|
|
45
|
+
let minDistanceDataSource = { title: dataSourceTitle, live: false };
|
|
46
|
+
dataSourceList.forEach((dataSource) => {
|
|
47
|
+
const title = dataSource.title;
|
|
48
|
+
if (title === dataSourceTitle) {
|
|
49
|
+
minDistanceDataSource = dataSource;
|
|
50
|
+
minDistance = 0;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// get the most matching data source by comparing levenshtein distance on the title
|
|
54
|
+
const distance = levenshtein(dataSourceTitle, title);
|
|
55
|
+
if (distance < minDistance) {
|
|
56
|
+
minDistance = distance;
|
|
57
|
+
minDistanceDataSource = dataSource;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (minDistance === 0) {
|
|
62
|
+
console.log('OK!\r\n');
|
|
63
|
+
return minDistanceDataSource;
|
|
64
|
+
}
|
|
65
|
+
throw new Error(`Data source '${dataSourceTitle}' not found. ${minDistance <= 3 ? `Did you mean '${minDistanceDataSource.title}'?` : ''}`);
|
|
66
|
+
}
|
|
67
|
+
async function retrieveDataFields(queryClient, dataSourceTitle) {
|
|
68
|
+
console.log('Getting fields... ');
|
|
69
|
+
const fields = await queryClient.getDataSourceFields(dataSourceTitle);
|
|
70
|
+
try {
|
|
71
|
+
// get the schema of the data source to add descriptions to the fields
|
|
72
|
+
const dataSourceSchema = await queryClient.getDataSourceSchema(dataSourceTitle);
|
|
73
|
+
return addDescriptionToFields(fields, dataSourceSchema.datasets);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error.status === '403') {
|
|
77
|
+
// the caller may not have permission to access this data source
|
|
78
|
+
console.log(`Note: Field descriptions are omitted from the data model due to restricted role of your account`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
console.log('OK!\r\n');
|
|
86
|
+
}
|
|
87
|
+
return fields;
|
|
88
|
+
}
|
|
89
|
+
function combineDataSourceAndDataFields(dataSource, dataFields) {
|
|
90
|
+
return {
|
|
91
|
+
name: dataSource.title,
|
|
92
|
+
dataSource: {
|
|
93
|
+
title: dataSource.title,
|
|
94
|
+
type: dataSource.live ? 'live' : 'elasticube',
|
|
95
|
+
},
|
|
96
|
+
metadata: dataFields,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
42
99
|
/**
|
|
43
100
|
* Create a data model for a Sisense data source
|
|
44
101
|
*/
|
|
45
102
|
async function createDataModel(httpClient, dataSourceTitle) {
|
|
46
103
|
const queryClient = new DimensionalQueryClient(httpClient);
|
|
47
|
-
console.log('Getting fields... ');
|
|
48
104
|
try {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
console.log('OK!\r\n');
|
|
54
|
-
const dataModel = {
|
|
55
|
-
name: dataSourceTitle,
|
|
56
|
-
dataSource: dataSourceInfo,
|
|
57
|
-
metadata: fields,
|
|
58
|
-
};
|
|
59
|
-
return rewriteDataModel(dataModel);
|
|
105
|
+
const dataSource = await retrieveDataSource(queryClient, dataSourceTitle);
|
|
106
|
+
const dataFields = await retrieveDataFields(queryClient, dataSourceTitle);
|
|
107
|
+
const rawDataModel = combineDataSourceAndDataFields(dataSource, dataFields);
|
|
108
|
+
return rewriteDataModel(rawDataModel);
|
|
60
109
|
}
|
|
61
110
|
catch (err) {
|
|
62
111
|
trackCliError({
|
|
@@ -78,6 +127,7 @@ function rewriteDataModel(dataModel) {
|
|
|
78
127
|
expression: item.id,
|
|
79
128
|
type: MetadataTypes.Dimension,
|
|
80
129
|
group: undefined,
|
|
130
|
+
description: item.description,
|
|
81
131
|
};
|
|
82
132
|
result.group = item.table;
|
|
83
133
|
switch (item.dimtype) {
|
|
@@ -165,4 +215,22 @@ function getFullFilePath(filePathInfo) {
|
|
|
165
215
|
function isSupportedOutputFile(filePathInfo) {
|
|
166
216
|
return ['.ts', '.js'].includes(filePathInfo.extension);
|
|
167
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Add 'description' property from datasource schema columns to datasource fields
|
|
220
|
+
*/
|
|
221
|
+
export function addDescriptionToFields(fields, datasets) {
|
|
222
|
+
const schemaDataDescriptionsMap = datasets.reduce((map, dataset) => {
|
|
223
|
+
dataset.schema.tables.forEach((table) => {
|
|
224
|
+
map[table.name] = {};
|
|
225
|
+
table.columns.forEach((column) => {
|
|
226
|
+
map[table.name][column.name] = column.description;
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
return map;
|
|
230
|
+
}, {});
|
|
231
|
+
return fields.map((field) => ({
|
|
232
|
+
...field,
|
|
233
|
+
description: schemaDataDescriptionsMap[field.table]?.[field.column] || '',
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
168
236
|
export { getHttpClient, createDataModel, rewriteDataModel, writeFile, getFilePathInfo, isSupportedOutputFile, };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PKG_VERSION = "1.
|
|
1
|
+
export declare const PKG_VERSION = "1.9.0";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PKG_VERSION = "1.
|
|
1
|
+
export const PKG_VERSION = "1.9.0";
|
package/dist/types.d.ts
CHANGED
|
@@ -19,4 +19,26 @@ export declare type GetApiTokenOptions = {
|
|
|
19
19
|
username: string;
|
|
20
20
|
password: string | undefined;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Data source schema table
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare type DataSourceSchemaTable = {
|
|
28
|
+
name: string;
|
|
29
|
+
columns: {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string | null;
|
|
32
|
+
}[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Data source schema table
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare type DataSourceSchemaDataset = {
|
|
40
|
+
schema: {
|
|
41
|
+
tables: DataSourceSchemaTable[];
|
|
42
|
+
};
|
|
43
|
+
};
|
|
22
44
|
export {};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"Sisense",
|
|
12
12
|
"Compose SDK"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.9.0",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": "./dist/index.js",
|
|
17
17
|
"main": "./dist/index.js",
|
|
@@ -20,14 +20,15 @@
|
|
|
20
20
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
21
21
|
"bin": "./dist/index.js",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@sisense/sdk-common": "^1.
|
|
24
|
-
"@sisense/sdk-data": "^1.
|
|
25
|
-
"@sisense/sdk-modeling": "^1.
|
|
26
|
-
"@sisense/sdk-query-client": "^1.
|
|
27
|
-
"@sisense/sdk-rest-client": "^1.
|
|
28
|
-
"@sisense/sdk-tracking": "^1.
|
|
23
|
+
"@sisense/sdk-common": "^1.9.0",
|
|
24
|
+
"@sisense/sdk-data": "^1.9.0",
|
|
25
|
+
"@sisense/sdk-modeling": "^1.9.0",
|
|
26
|
+
"@sisense/sdk-query-client": "^1.9.0",
|
|
27
|
+
"@sisense/sdk-rest-client": "^1.9.0",
|
|
28
|
+
"@sisense/sdk-tracking": "^1.9.0",
|
|
29
29
|
"cross-fetch": "^4.0.0",
|
|
30
30
|
"inquirer": "^8.1.2",
|
|
31
|
+
"js-levenshtein": "^1.1.6",
|
|
31
32
|
"node-window-polyfill": "^1.0.2",
|
|
32
33
|
"yargs": "17.7.1"
|
|
33
34
|
},
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@babel/preset-env": "^7.20.2",
|
|
56
57
|
"@types/inquirer": "8.2.6",
|
|
58
|
+
"@types/js-levenshtein": "^1.1.3",
|
|
57
59
|
"@types/yargs": "^17.0.22",
|
|
58
60
|
"eslint": "^8.40.0",
|
|
59
61
|
"msw": "2.2.1",
|