@contrail/cli 1.0.15 → 1.0.17
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 +5 -0
- package/lib/cli.js +51 -0
- package/lib/colors/color-loader.d.ts +2 -0
- package/lib/colors/color-loader.js +94 -0
- package/lib/config/config.d.ts +2 -1
- package/lib/config/config.js +17 -6
- package/lib/config/configCommands.d.ts +2 -0
- package/lib/config/configCommands.js +10 -0
- package/lib/types/csv-parser.d.ts +1 -0
- package/lib/types/csv-parser.js +51 -0
- package/lib/types/option-set-parser.d.ts +1 -0
- package/lib/types/option-set-parser.js +46 -0
- package/lib/types/parse-types.js +21 -5
- package/package.json +3 -2
- package/src/cli.ts +53 -0
- package/src/colors/color-example.csv +866 -0
- package/src/colors/color-loader.ts +110 -0
- package/src/config/config.ts +20 -9
- package/src/config/configCommands.ts +13 -0
- package/src/types/csv-parser.ts +59 -0
- package/src/types/option-set-parser.ts +55 -0
- package/src/types/parse-types.ts +22 -5
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { authUser } from '../auth/login';
|
|
4
|
+
import { getSeparatorByPlatform } from '../common';
|
|
5
|
+
|
|
6
|
+
const csv = require('csvtojson')
|
|
7
|
+
|
|
8
|
+
interface Color {
|
|
9
|
+
name: string;
|
|
10
|
+
hex: string;
|
|
11
|
+
red?: number;
|
|
12
|
+
green?: number;
|
|
13
|
+
blue?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function deleteColors() {
|
|
17
|
+
try {
|
|
18
|
+
await authUser();
|
|
19
|
+
const colors = await getExistingColors();
|
|
20
|
+
console.log("Deleting %s colors", colors.length)
|
|
21
|
+
for (const color of colors) {
|
|
22
|
+
await deleteColor(color);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.log(`%s Loading Colors Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log('%s Deleting Colors Complete.', chalk.green.bold('COMPLETE'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function loadColors() {
|
|
33
|
+
try {
|
|
34
|
+
await authUser();
|
|
35
|
+
console.log(`%s Getting Existing Colors`, chalk.yellow.bold('COLORS'));
|
|
36
|
+
console.log(`%s Uploading`, chalk.yellow.bold('COLORS'));
|
|
37
|
+
await uploadColors();
|
|
38
|
+
console.log(`%s Uploaded`, chalk.yellow.bold('COLORS'));
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
console.log(`%s Loading Colors Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('%s Loading Colors Complete.', chalk.green.bold('COMPLETE'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function getLocalColors() {
|
|
50
|
+
console.log("loading colors from local file")
|
|
51
|
+
const TARGET_DIR = process.cwd();
|
|
52
|
+
try {
|
|
53
|
+
const separator = getSeparatorByPlatform();
|
|
54
|
+
|
|
55
|
+
const csvFilePath = TARGET_DIR + separator + 'colors.csv'
|
|
56
|
+
return await csv().fromFile(csvFilePath)
|
|
57
|
+
} catch (e) {
|
|
58
|
+
throw new Error(`ERROR PARSING COLORS CSV: ${e}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function getExistingColors() {
|
|
63
|
+
console.log(`%s Getting Existing Colors`, chalk.yellow.bold('COLORS'));
|
|
64
|
+
try {
|
|
65
|
+
return new Entities().get({ entityName: 'color'}); //, useSearch: false }); Not in EntitiesClientGetOptions yet
|
|
66
|
+
} catch (e) {
|
|
67
|
+
throw new Error(`ERROR DOWNLOADING COLORS: ${e}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function deleteColor(color) {
|
|
72
|
+
try {
|
|
73
|
+
await new Entities().delete({ entityName: 'color', id: color.id });
|
|
74
|
+
} catch (e) {
|
|
75
|
+
throw new Error(`ERROR DOWNLOADING COLORS: ${e}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function uploadColors() {
|
|
80
|
+
const colors: Color[] = await getLocalColors();
|
|
81
|
+
const existingColors = await getExistingColors();
|
|
82
|
+
const existingNamesValues = existingColors.filter(x => x.name).map(x => x.name)
|
|
83
|
+
for (const color of colors) {
|
|
84
|
+
if (existingNamesValues.includes(color.name)) {
|
|
85
|
+
console.log(`%s SKIPPING %s (%s)`, chalk.yellow.bold('COLORS'), color.hex, color.name);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (color.hex.length > 1 && color.hex[0] === '#') {
|
|
89
|
+
color.hex = color.hex.substring(1);
|
|
90
|
+
}
|
|
91
|
+
const o: any = {
|
|
92
|
+
hex: color.hex,
|
|
93
|
+
name: color.name
|
|
94
|
+
}
|
|
95
|
+
if (color.red) {
|
|
96
|
+
o.red = color.red
|
|
97
|
+
}
|
|
98
|
+
if (color.green) {
|
|
99
|
+
o.green = color.green
|
|
100
|
+
}
|
|
101
|
+
if (color.blue) {
|
|
102
|
+
o.blue = color.blue
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
await new Entities().create({
|
|
106
|
+
entityName: 'color',
|
|
107
|
+
object: o
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
package/src/config/config.ts
CHANGED
|
@@ -28,8 +28,7 @@ export async function readVibeIQConfig() {
|
|
|
28
28
|
console.debug(`failed to open config file (${configFileLocation}) for reading.`);
|
|
29
29
|
console.debug('trying to initialize config file');
|
|
30
30
|
await initializeVibeIQConfig();
|
|
31
|
-
|
|
32
|
-
throw e
|
|
31
|
+
fileContent = await fsPromises.readFile(configFileLocation);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
try {
|
|
@@ -54,12 +53,24 @@ export async function getConfig() {
|
|
|
54
53
|
return await readVibeIQConfig();
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
export async function
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
export async function deleteConfigs(configNames: string[]) {
|
|
57
|
+
const currentConfig = await readVibeIQConfig();
|
|
58
|
+
for(const configName of configNames) {
|
|
59
|
+
delete currentConfig[configName];
|
|
60
|
+
}
|
|
61
|
+
await storeConfig(currentConfig, false);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function storeConfig(incomingConfig: Object, merge=true) {
|
|
65
|
+
let config;
|
|
66
|
+
if (merge) {
|
|
67
|
+
config = {
|
|
68
|
+
... await readVibeIQConfig(),
|
|
69
|
+
... incomingConfig
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
config = incomingConfig
|
|
73
|
+
}
|
|
74
|
+
await writeVibeIQConfig(config);
|
|
64
75
|
}
|
|
65
76
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {deleteConfigs, readVibeIQConfig} from './config';
|
|
2
|
+
export async function listConfig() {
|
|
3
|
+
console.log(await readVibeIQConfig())
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export async function removeConfig(args) {
|
|
7
|
+
if (args?.length < 4) {
|
|
8
|
+
throw new Error('At least one configuration must be included to be removed.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
await deleteConfigs(args.slice(3));
|
|
12
|
+
|
|
13
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import csvToJson from 'csvtojson';
|
|
2
|
+
import * as client from 'https'
|
|
3
|
+
import { Entities } from '@contrail/sdk';
|
|
4
|
+
|
|
5
|
+
export async function getCSVFromFile(loadFileId: string): Promise<any[]> {
|
|
6
|
+
|
|
7
|
+
let file;
|
|
8
|
+
try {
|
|
9
|
+
file = await new Entities().get({ entityName: 'file', id: loadFileId });
|
|
10
|
+
console.log('Got file: ', file);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
console.log(`Failed to get file: ${loadFileId}`, JSON.stringify(e));
|
|
13
|
+
throw new Error(`Failed to get file: ${loadFileId} - ` + JSON.stringify(e));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!file || !file.downloadUrl) {
|
|
17
|
+
console.log(`File: ${loadFileId} does not have a downloadUrl`);
|
|
18
|
+
throw new Error(`File: ${loadFileId} does not have a downloadUrl`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// get csv
|
|
22
|
+
let response;
|
|
23
|
+
try {
|
|
24
|
+
response = await new Promise((resolve, reject) => {
|
|
25
|
+
client.get(file.downloadUrl, function(res) {
|
|
26
|
+
console.log('Status code:', res.statusCode);
|
|
27
|
+
console.log('Status text:', res.statusMessage);
|
|
28
|
+
|
|
29
|
+
let body = '';
|
|
30
|
+
|
|
31
|
+
res.on('data', (data) => {
|
|
32
|
+
body += data.toString();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
res.on('end', () => {
|
|
36
|
+
console.log('Response body:');
|
|
37
|
+
//console.log(body);
|
|
38
|
+
resolve(body);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
}).on('error', function(e) {
|
|
42
|
+
console.error(e);
|
|
43
|
+
reject(e);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
} catch (e) {
|
|
47
|
+
console.log(`Failed to get data from downloadUrl: ${file.downloadUrl}`, e);
|
|
48
|
+
throw e;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!response) {
|
|
52
|
+
console.log('Response is empty');
|
|
53
|
+
throw new Error('Response is empty');
|
|
54
|
+
}
|
|
55
|
+
const csvJson = await csvToJson({flatKeys: true}).fromString(response);
|
|
56
|
+
// console.log('csvJson', csvJson);
|
|
57
|
+
|
|
58
|
+
return csvJson;
|
|
59
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReducedOptionSet } from './interfaces';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { getSeparatorByPlatform } from '../common';
|
|
4
|
+
import { parseOptionSets } from '@contrail/types';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
const csv = require('csvtojson')
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
|
|
9
|
+
export async function ParseOptionSetsLocalFiles(args) {
|
|
10
|
+
try {
|
|
11
|
+
if (args?.length < 4) {
|
|
12
|
+
throw new Error('File name must be included.');
|
|
13
|
+
}
|
|
14
|
+
console.log(`%s Importing local file`, chalk.yellow.bold('OPTION SET PARSE'));
|
|
15
|
+
const fileLocation = args[3];
|
|
16
|
+
console.log('Using File: ', fileLocation);
|
|
17
|
+
|
|
18
|
+
await parseOptionSetsLocalFiles(fileLocation);
|
|
19
|
+
console.log(`%s Parsed`, chalk.yellow.bold('OPTION SET PARSE'));
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.log(`%s PARSE Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log('%s PARSE Complete.', chalk.green.bold('COMPLETE'));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function loadOptionSetCSV(fileLocation) {
|
|
31
|
+
const TARGET_DIR = process.cwd();
|
|
32
|
+
try {
|
|
33
|
+
const separator = getSeparatorByPlatform();
|
|
34
|
+
|
|
35
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
36
|
+
console.log('Getting file from path: ', fullPath);
|
|
37
|
+
|
|
38
|
+
return await csv().fromFile(fullPath)
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw new Error(`ERROR PARSING CSV: ${e}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function parseOptionSetsLocalFiles(fileLocation) {
|
|
45
|
+
const uploadedOptionData = await loadOptionSetCSV(fileLocation);
|
|
46
|
+
const parsedOptionSets = parseOptionSets(uploadedOptionData);
|
|
47
|
+
saveData({optionSets: parsedOptionSets})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function saveData(data) {
|
|
51
|
+
const yamlStr = yaml.dump(data);
|
|
52
|
+
const CURRENT_DIR = process.cwd();
|
|
53
|
+
const separator = getSeparatorByPlatform();
|
|
54
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'parsed_local_optionSets.yml', yamlStr, 'utf8');
|
|
55
|
+
}
|
package/src/types/parse-types.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GetSuggestedTypes } from '@contrail/types';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { getSeparatorByPlatform } from '../common';
|
|
5
5
|
import * as csvToJson from 'csvtojson';
|
|
6
6
|
import { authUser } from '../auth/login';
|
|
7
|
+
import { getCSVFromFile } from './csv-parser';
|
|
7
8
|
|
|
8
9
|
const yaml = require('js-yaml');
|
|
9
10
|
|
|
@@ -49,7 +50,7 @@ export async function ParseTypesFromFiles(args) {
|
|
|
49
50
|
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
async function
|
|
53
|
+
async function loadDataFromLocalCSV(fileName) {
|
|
53
54
|
const CURRENT_DIR = process.cwd();
|
|
54
55
|
try {
|
|
55
56
|
const separator = getSeparatorByPlatform();
|
|
@@ -70,7 +71,7 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
|
|
|
70
71
|
for (const fileLocation of fileLocations) {
|
|
71
72
|
try {
|
|
72
73
|
console.log('Getting data for fileLocation: ', fileLocation);
|
|
73
|
-
const csvData = await
|
|
74
|
+
const csvData = await loadDataFromLocalCSV(fileLocation);
|
|
74
75
|
|
|
75
76
|
console.log(`CSV import was successful. ${csvData?.length} rows found. Adding to total rows.`);
|
|
76
77
|
csvJSONData.push(...csvData);
|
|
@@ -82,7 +83,7 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
console.log(`CSV imports were successful. ${csvJSONData?.length} total rows found.`);
|
|
85
|
-
const suggestions =
|
|
86
|
+
const suggestions = GetSuggestedTypes(csvJSONData)
|
|
86
87
|
saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
|
|
87
88
|
saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
|
|
88
89
|
}
|
|
@@ -90,7 +91,23 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
|
|
|
90
91
|
async function parseTypesFromFiles(fileIds: string[]) {
|
|
91
92
|
await authUser();
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
// get csv data
|
|
95
|
+
const csvJSONData: any[] = [];
|
|
96
|
+
for (const loadFileId of fileIds) {
|
|
97
|
+
try {
|
|
98
|
+
console.log('Getting data for fileId: ', loadFileId);
|
|
99
|
+
const csvJSON = await getCSVFromFile(loadFileId);
|
|
100
|
+
console.log(`CSV download was successful. ${csvJSON?.length} rows found. Adding to total rows`);
|
|
101
|
+
csvJSONData.push(...csvJSON);
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
console.log('Error retrieving csv data', e);
|
|
105
|
+
throw e;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(`CSV downloads were successful. ${csvJSONData?.length} total rows found.`);
|
|
110
|
+
const suggestions = GetSuggestedTypes(csvJSONData)
|
|
94
111
|
|
|
95
112
|
saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
|
|
96
113
|
saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
|