@contrail/cli 1.0.14 → 1.0.15
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/lib/cli.js +39 -6
- package/lib/types/interfaces.d.ts +2 -2
- package/lib/types/option-set-merger.d.ts +1 -0
- package/lib/types/option-set-merger.js +102 -0
- package/lib/types/option-set-uploader.d.ts +1 -1
- package/lib/types/option-set-uploader.js +17 -1
- package/lib/types/parse-types.d.ts +2 -0
- package/lib/types/parse-types.js +85 -0
- package/lib/types/types-extractor.d.ts +1 -0
- package/lib/types/types-extractor.js +10 -6
- package/lib/types/types-properties-merger.d.ts +1 -0
- package/lib/types/types-properties-merger.js +69 -0
- package/lib/types/types-uploader.js +0 -4
- package/package.json +2 -2
- package/src/cli.ts +40 -6
- package/src/types/interfaces.ts +2 -2
- package/src/types/option-set-merger.ts +123 -0
- package/src/types/option-set-uploader.ts +21 -1
- package/src/types/parse-types.ts +104 -0
- package/src/types/types-extractor.ts +12 -10
- package/src/types/types-properties-merger.ts +85 -0
- package/src/types/types-uploader.ts +1 -6
- package/.eslint.js +0 -54
- package/.eslintrc.js +0 -20
- package/lib/types/parse-optionSet.d.ts +0 -2
- package/lib/types/parse-optionSet.js +0 -79
- package/option_sets.yml +0 -15
- package/src/types/parse-optionSet.ts +0 -96
- package/test/actions/exampleAction.d.ts +0 -1
- package/test/actions/exampleAction.js +0 -40
- package/test/actions/exampleAction.ts +0 -39
- package/test/app.yml +0 -46
- package/test/option_sets.yml +0 -15
- package/test/package-lock.json +0 -57
- package/test/package.json +0 -26
- package/test/tsconfig.json +0 -31
- package/test/types.yml +0 -1621
- package/types.yml +0 -1621
package/lib/cli.js
CHANGED
|
@@ -2,7 +2,10 @@ import { create } from './apps/create-app/create';
|
|
|
2
2
|
import { deployApp, removeApp } from './apps/deploy-app/deploy';
|
|
3
3
|
import { getTypes } from './types/types-extractor';
|
|
4
4
|
import { uploadTypes } from './types/types-uploader';
|
|
5
|
-
import {
|
|
5
|
+
import { UploadOptionSets } from './types/option-set-uploader';
|
|
6
|
+
import { MergeOptionSets } from './types/option-set-merger';
|
|
7
|
+
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
8
|
+
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
6
9
|
const cliUsage = require('command-line-usage');
|
|
7
10
|
/**
|
|
8
11
|
* Built using documentation here:
|
|
@@ -54,12 +57,28 @@ export async function cli(args) {
|
|
|
54
57
|
getTypes(args);
|
|
55
58
|
break;
|
|
56
59
|
}
|
|
57
|
-
case '
|
|
60
|
+
case 'uploadTypes': {
|
|
58
61
|
uploadTypes(args);
|
|
59
62
|
break;
|
|
60
63
|
}
|
|
61
|
-
case '
|
|
62
|
-
|
|
64
|
+
case 'uploadOptionSets': {
|
|
65
|
+
UploadOptionSets(args);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case 'parseTypesFromLocalFiles': {
|
|
69
|
+
ParseTypesFromLocalFiles(args);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case 'parseTypesFromFiles': {
|
|
73
|
+
ParseTypesFromFiles(args);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case 'mergeOptionSets': {
|
|
77
|
+
MergeOptionSets(args);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'mergeTypeProperties': {
|
|
81
|
+
MergeTypeProperties(args);
|
|
63
82
|
break;
|
|
64
83
|
}
|
|
65
84
|
default: {
|
|
@@ -117,8 +136,22 @@ const helpSections = [
|
|
|
117
136
|
header: 'Type Commands - Domain: types',
|
|
118
137
|
content: [
|
|
119
138
|
'getAll Get all OptionSets and Types for your Org.',
|
|
120
|
-
'
|
|
121
|
-
'
|
|
139
|
+
'uploadTypes Upload Types for your Org.',
|
|
140
|
+
'. Types are uploaded from types.yml\n',
|
|
141
|
+
'uploadOptionSets Upload OptionSets for your Org.',
|
|
142
|
+
'. OptionSets are loaded from option_sets.yml\n',
|
|
143
|
+
'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
|
|
144
|
+
'. OptionSets from local files.\n',
|
|
145
|
+
'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
|
|
146
|
+
'. OptionSets from VibeIQ Files.\n',
|
|
147
|
+
'mergeOptionSets <File Path> Merge the OptionSets from an existing',
|
|
148
|
+
'. org and the OptionSets passed in.',
|
|
149
|
+
'. File must be .yml\n',
|
|
150
|
+
'mergeTypeProperties <File Path> <TypePaths> ',
|
|
151
|
+
'. Merge the TypeProperties from an existing',
|
|
152
|
+
'. org and the TypeProperties passed in.',
|
|
153
|
+
'. Add to Types via TypePath',
|
|
154
|
+
'. File must be .yml\n',
|
|
122
155
|
],
|
|
123
156
|
},
|
|
124
157
|
];
|
|
@@ -3,9 +3,9 @@ export interface ReducedType {
|
|
|
3
3
|
label: string;
|
|
4
4
|
typePath: string;
|
|
5
5
|
isArchived: boolean;
|
|
6
|
-
typeProperties:
|
|
6
|
+
typeProperties: ReducedTypeProperty[];
|
|
7
7
|
}
|
|
8
|
-
export interface
|
|
8
|
+
export interface ReducedTypeProperty {
|
|
9
9
|
id: string;
|
|
10
10
|
isArchived: boolean;
|
|
11
11
|
propertyType: PropertyType;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function MergeOptionSets(args: any): Promise<void>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { getSeparatorByPlatform } from '../common';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
const yaml = require('js-yaml');
|
|
7
|
+
export async function MergeOptionSets(args) {
|
|
8
|
+
try {
|
|
9
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
10
|
+
throw new Error('File name must be included.');
|
|
11
|
+
}
|
|
12
|
+
console.log(`%s Importing local file`, chalk.yellow.bold('OPTION SET MERGE'));
|
|
13
|
+
const fileLocation = args[3];
|
|
14
|
+
console.log('Using File: ', fileLocation);
|
|
15
|
+
await mergeOptionSets(fileLocation);
|
|
16
|
+
console.log(`%s Merged`, chalk.yellow.bold('OPTION SET MERGE'));
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.log(`%s Merge Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log('%s Merge Complete.', chalk.green.bold('COMPLETE'));
|
|
23
|
+
}
|
|
24
|
+
function loadOptionSets(fileLocation) {
|
|
25
|
+
const TARGET_DIR = process.cwd();
|
|
26
|
+
try {
|
|
27
|
+
const separator = getSeparatorByPlatform();
|
|
28
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
29
|
+
console.log('Getting file from path: ', fullPath);
|
|
30
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
31
|
+
return doc.optionSets;
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function mergeOptionSets(fileLocation) {
|
|
38
|
+
const uploadedOptionSets = loadOptionSets(fileLocation);
|
|
39
|
+
await authUser();
|
|
40
|
+
const currentOptionSetsFull = await new Entities().get({
|
|
41
|
+
entityName: 'type-property-option-set',
|
|
42
|
+
});
|
|
43
|
+
const currentOptionSets = currentOptionSetsFull.map(os => Object.assign({}, {
|
|
44
|
+
name: os.name,
|
|
45
|
+
isArchived: os.isArchived,
|
|
46
|
+
optionSet: os.optionSet,
|
|
47
|
+
}));
|
|
48
|
+
const currentOptionSetsByName = {};
|
|
49
|
+
for (const currentOptionSet of currentOptionSets) {
|
|
50
|
+
currentOptionSetsByName[currentOptionSet.name] = currentOptionSet;
|
|
51
|
+
}
|
|
52
|
+
const uploadedOptionSetsByName = {};
|
|
53
|
+
for (const optionSet of uploadedOptionSets) {
|
|
54
|
+
uploadedOptionSetsByName[optionSet.name] = optionSet;
|
|
55
|
+
}
|
|
56
|
+
const mergedOptionSets = [];
|
|
57
|
+
for (const uploadedOptionSet of uploadedOptionSets) {
|
|
58
|
+
const existing = currentOptionSetsByName[uploadedOptionSet.name];
|
|
59
|
+
if (!existing) {
|
|
60
|
+
if (!uploadedOptionSet.optionSet) {
|
|
61
|
+
console.log('No OptionSet for: ', uploadedOptionSet.name);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
console.log('Adding New: ', uploadedOptionSet.name);
|
|
65
|
+
mergedOptionSets.push(uploadedOptionSet);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.log('Merging: ', uploadedOptionSet.name);
|
|
69
|
+
mergedOptionSets.push(mergeOptionSet(existing, uploadedOptionSet));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const currentOptionSet of currentOptionSets) {
|
|
73
|
+
const found = uploadedOptionSetsByName[currentOptionSet.name];
|
|
74
|
+
if (!found) {
|
|
75
|
+
console.log('Adding Existing: ', currentOptionSet.name);
|
|
76
|
+
mergedOptionSets.push(currentOptionSet);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
saveData({ optionSets: mergedOptionSets });
|
|
80
|
+
}
|
|
81
|
+
function mergeOptionSet(existingOptionSet, uploadedOptionSet) {
|
|
82
|
+
const merged = {
|
|
83
|
+
name: uploadedOptionSet.name,
|
|
84
|
+
optionSet: uploadedOptionSet.optionSet,
|
|
85
|
+
isArchived: uploadedOptionSet.isArchived,
|
|
86
|
+
};
|
|
87
|
+
for (const keyVal of existingOptionSet.optionSet) {
|
|
88
|
+
const value = keyVal.value;
|
|
89
|
+
const display = keyVal.display;
|
|
90
|
+
const found = merged.optionSet.find(keyVal => keyVal.value === value);
|
|
91
|
+
if (!found) {
|
|
92
|
+
merged.optionSet.push({ value, display });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return merged;
|
|
96
|
+
}
|
|
97
|
+
function saveData(data) {
|
|
98
|
+
const yamlStr = yaml.dump(data);
|
|
99
|
+
const CURRENT_DIR = process.cwd();
|
|
100
|
+
const separator = getSeparatorByPlatform();
|
|
101
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'merged_optionSets.yml', yamlStr, 'utf8');
|
|
102
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function UploadOptionSets(args: any): Promise<void>;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { Entities } from '@contrail/sdk';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import { getSeparatorByPlatform } from '../common';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import chalk from 'chalk';
|
|
4
6
|
const yaml = require('js-yaml');
|
|
7
|
+
export async function UploadOptionSets(args) {
|
|
8
|
+
try {
|
|
9
|
+
const userConfig = await authUser();
|
|
10
|
+
console.log(`%s Getting all types for orgId: ${userConfig.orgId}`, chalk.blue.bold('START'));
|
|
11
|
+
console.log(`%s Uploading`, chalk.yellow.bold('OPTION SETS'));
|
|
12
|
+
await uploadOptionSets();
|
|
13
|
+
console.log(`%s Uploaded`, chalk.yellow.bold('OPTION SETS'));
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log(`%s Types Upload Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log('%s Types Upload Complete.', chalk.green.bold('COMPLETE'));
|
|
20
|
+
}
|
|
5
21
|
function loadOptionSets() {
|
|
6
22
|
const TARGET_DIR = process.cwd();
|
|
7
23
|
try {
|
|
@@ -13,7 +29,7 @@ function loadOptionSets() {
|
|
|
13
29
|
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
14
30
|
}
|
|
15
31
|
}
|
|
16
|
-
|
|
32
|
+
async function uploadOptionSets() {
|
|
17
33
|
const optionSets = loadOptionSets();
|
|
18
34
|
const currentOptionSets = await new Entities().get({
|
|
19
35
|
entityName: 'type-property-option-set',
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { TypeProcessor } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { getSeparatorByPlatform } from '../common';
|
|
5
|
+
import * as csvToJson from 'csvtojson';
|
|
6
|
+
import { authUser } from '../auth/login';
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
export async function ParseTypesFromLocalFiles(args) {
|
|
9
|
+
try {
|
|
10
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
11
|
+
throw new Error('File names must be included.');
|
|
12
|
+
}
|
|
13
|
+
console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
14
|
+
const fileLocations = args.slice(3);
|
|
15
|
+
console.log('Using File Location(s): ', fileLocations);
|
|
16
|
+
await parseTypesFromLocalFiles(fileLocations);
|
|
17
|
+
console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
24
|
+
}
|
|
25
|
+
export async function ParseTypesFromFiles(args) {
|
|
26
|
+
try {
|
|
27
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
28
|
+
throw new Error('File ids must be included.');
|
|
29
|
+
}
|
|
30
|
+
console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
31
|
+
const fileIds = args.slice(3);
|
|
32
|
+
console.log('Using FileId(s): ', fileIds);
|
|
33
|
+
await parseTypesFromFiles(fileIds);
|
|
34
|
+
console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
41
|
+
}
|
|
42
|
+
async function loadDataFromCSV(fileName) {
|
|
43
|
+
const CURRENT_DIR = process.cwd();
|
|
44
|
+
try {
|
|
45
|
+
const separator = getSeparatorByPlatform();
|
|
46
|
+
const fullPath = CURRENT_DIR + separator + fileName;
|
|
47
|
+
console.log('Getting file from path: ', fullPath);
|
|
48
|
+
const csvData = await csvToJson.default().fromFile(fullPath);
|
|
49
|
+
return csvData;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
throw new Error(`ERROR PARSING CSV: ${e}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function parseTypesFromLocalFiles(fileLocations) {
|
|
56
|
+
const csvJSONData = [];
|
|
57
|
+
for (const fileLocation of fileLocations) {
|
|
58
|
+
try {
|
|
59
|
+
console.log('Getting data for fileLocation: ', fileLocation);
|
|
60
|
+
const csvData = await loadDataFromCSV(fileLocation);
|
|
61
|
+
console.log(`CSV import was successful. ${csvData === null || csvData === void 0 ? void 0 : csvData.length} rows found. Adding to total rows.`);
|
|
62
|
+
csvJSONData.push(...csvData);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
console.log('Error importing csv data.', e);
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
console.log(`CSV imports were successful. ${csvJSONData === null || csvJSONData === void 0 ? void 0 : csvJSONData.length} total rows found.`);
|
|
70
|
+
const suggestions = await new TypeProcessor().GetSuggestedTypes(csvJSONData);
|
|
71
|
+
saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
|
|
72
|
+
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
73
|
+
}
|
|
74
|
+
async function parseTypesFromFiles(fileIds) {
|
|
75
|
+
await authUser();
|
|
76
|
+
const suggestions = await new TypeProcessor().GetSuggestedTypesFromFiles({ loadFileIds: fileIds });
|
|
77
|
+
saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
|
|
78
|
+
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
79
|
+
}
|
|
80
|
+
function saveData(data, name) {
|
|
81
|
+
const yamlStr = yaml.dump(data);
|
|
82
|
+
const CURRENT_DIR = process.cwd();
|
|
83
|
+
const separator = getSeparatorByPlatform();
|
|
84
|
+
fs.writeFileSync(CURRENT_DIR + separator + name, yamlStr, 'utf8');
|
|
85
|
+
}
|
|
@@ -15,7 +15,11 @@ export async function getTypes(args) {
|
|
|
15
15
|
await getOptionSets(optionSets);
|
|
16
16
|
console.log(`%s Retrieved`, chalk.yellow.bold('OPTION SETS'));
|
|
17
17
|
console.log(`%s Retrieving`, chalk.yellow.bold('TYPES'));
|
|
18
|
-
await getReducedTypes(optionSets);
|
|
18
|
+
const reducedTypes = await getReducedTypes(optionSets);
|
|
19
|
+
const typesHolder = {
|
|
20
|
+
types: reducedTypes,
|
|
21
|
+
};
|
|
22
|
+
saveData(typesHolder);
|
|
19
23
|
console.log(`%s Retrieved`, chalk.yellow.bold('TYPES'));
|
|
20
24
|
}
|
|
21
25
|
catch (e) {
|
|
@@ -43,7 +47,7 @@ async function getOptionSets(optionSets) {
|
|
|
43
47
|
const yamlStr = yaml.dump(optionSetsHolder);
|
|
44
48
|
fs.writeFileSync(CURRENT_DIR + separator + 'option_sets.yml', yamlStr, 'utf8');
|
|
45
49
|
}
|
|
46
|
-
async function getReducedTypes(optionSets) {
|
|
50
|
+
export async function getReducedTypes(optionSets) {
|
|
47
51
|
const types = await new Entities().get({
|
|
48
52
|
entityName: 'type',
|
|
49
53
|
});
|
|
@@ -90,11 +94,11 @@ async function getReducedTypes(optionSets) {
|
|
|
90
94
|
reducedTypes.push(reducedType);
|
|
91
95
|
}
|
|
92
96
|
reducedTypes = reducedTypes.sort((one, two) => (one.typePath < two.typePath ? -1 : 1));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
return reducedTypes;
|
|
98
|
+
}
|
|
99
|
+
function saveData(data) {
|
|
100
|
+
const yamlStr = yaml.dump(data);
|
|
96
101
|
const CURRENT_DIR = process.cwd();
|
|
97
102
|
const separator = getSeparatorByPlatform();
|
|
98
|
-
const yamlStr = yaml.dump(typesHolder);
|
|
99
103
|
fs.writeFileSync(CURRENT_DIR + separator + 'types.yml', yamlStr, 'utf8');
|
|
100
104
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function MergeTypeProperties(args: any): Promise<void>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import { getReducedTypes } from './types-extractor';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { getSeparatorByPlatform } from '../common';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
export async function MergeTypeProperties(args) {
|
|
9
|
+
try {
|
|
10
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 5) {
|
|
11
|
+
throw new Error('File name must be included along with a type path.');
|
|
12
|
+
}
|
|
13
|
+
console.log(`%s Importing local file`, chalk.yellow.bold('TYPE PROPERTIES MERGE'));
|
|
14
|
+
const fileLocation = args[3];
|
|
15
|
+
console.log('Using File: ', fileLocation);
|
|
16
|
+
const typePaths = args.slice(4);
|
|
17
|
+
console.log('Using TypePaths: ', typePaths);
|
|
18
|
+
await mergeTypeProperties(fileLocation, typePaths);
|
|
19
|
+
console.log(`%s Merged`, chalk.yellow.bold('TYPE PROPERTIES MERGE'));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.log(`%s Merge Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log('%s Merge Complete.', chalk.green.bold('COMPLETE'));
|
|
26
|
+
}
|
|
27
|
+
function loadTypeProperties(fileLocation) {
|
|
28
|
+
const TARGET_DIR = process.cwd();
|
|
29
|
+
try {
|
|
30
|
+
const separator = getSeparatorByPlatform();
|
|
31
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
32
|
+
console.log('Getting file from path: ', fullPath);
|
|
33
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
34
|
+
return doc.typeProperties;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function mergeTypeProperties(fileLocation, typePaths) {
|
|
41
|
+
const uploadedTypeProperties = loadTypeProperties(fileLocation);
|
|
42
|
+
await authUser();
|
|
43
|
+
const optionSets = await new Entities().get({
|
|
44
|
+
entityName: 'type-property-option-set',
|
|
45
|
+
});
|
|
46
|
+
const reducedTypes = await getReducedTypes(optionSets);
|
|
47
|
+
for (const typePath of typePaths) {
|
|
48
|
+
const foundType = reducedTypes.find(reducedTypes => reducedTypes.typePath === typePath);
|
|
49
|
+
if (!foundType) {
|
|
50
|
+
console.log(`%s No Type found for: ${typePath}`, chalk.red.bold('WARNING'));
|
|
51
|
+
}
|
|
52
|
+
mergeType(foundType, uploadedTypeProperties);
|
|
53
|
+
}
|
|
54
|
+
saveData({ types: reducedTypes });
|
|
55
|
+
}
|
|
56
|
+
function mergeType(reducedType, typePropertiesToAdd) {
|
|
57
|
+
for (const typeProperty of typePropertiesToAdd) {
|
|
58
|
+
const found = reducedType.typeProperties.find(tp => tp.slug === typeProperty.slug);
|
|
59
|
+
if (!found) {
|
|
60
|
+
reducedType.typeProperties.push(typeProperty);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function saveData(data) {
|
|
65
|
+
const yamlStr = yaml.dump(data);
|
|
66
|
+
const CURRENT_DIR = process.cwd();
|
|
67
|
+
const separator = getSeparatorByPlatform();
|
|
68
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'merged_types.yml', yamlStr, 'utf8');
|
|
69
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Entities, Request } from '@contrail/sdk';
|
|
2
|
-
import { uploadOptionSets } from './option-set-uploader';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
3
|
import fs from 'fs';
|
|
5
4
|
import { authUser } from '../auth/login';
|
|
@@ -10,9 +9,6 @@ export async function uploadTypes(args) {
|
|
|
10
9
|
try {
|
|
11
10
|
const userConfig = await authUser();
|
|
12
11
|
console.log(`%s Getting all types for orgId: ${userConfig.orgId}`, chalk.blue.bold('START'));
|
|
13
|
-
console.log(`%s Uploading`, chalk.yellow.bold('OPTION SETS'));
|
|
14
|
-
await uploadOptionSets();
|
|
15
|
-
console.log(`%s Uploaded`, chalk.yellow.bold('OPTION SETS'));
|
|
16
12
|
console.log(`%s Uploading`, chalk.yellow.bold('TYPES'));
|
|
17
13
|
await uploadReducedTypes();
|
|
18
14
|
console.log(`%s Uploaded`, chalk.yellow.bold('TYPES'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "VibeIQ's Contrail Platform CLI.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "",
|
|
24
24
|
"license": "ISC",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@contrail/sdk": "^1.0.
|
|
26
|
+
"@contrail/sdk": "^1.0.152",
|
|
27
27
|
"@contrail/util": "^1.0.17",
|
|
28
28
|
"amazon-cognito-identity-js": "^5.2.3",
|
|
29
29
|
"arg": "^4.0.1",
|
package/src/cli.ts
CHANGED
|
@@ -3,7 +3,11 @@ import { create } from './apps/create-app/create';
|
|
|
3
3
|
import { deployApp, removeApp } from './apps/deploy-app/deploy';
|
|
4
4
|
import { getTypes } from './types/types-extractor';
|
|
5
5
|
import { uploadTypes } from './types/types-uploader';
|
|
6
|
-
import {
|
|
6
|
+
import { UploadOptionSets } from './types/option-set-uploader';
|
|
7
|
+
import { MergeOptionSets } from './types/option-set-merger';
|
|
8
|
+
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
9
|
+
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
10
|
+
|
|
7
11
|
const cliUsage = require('command-line-usage');
|
|
8
12
|
|
|
9
13
|
/**
|
|
@@ -61,12 +65,28 @@ export async function cli(args) {
|
|
|
61
65
|
getTypes(args);
|
|
62
66
|
break;
|
|
63
67
|
}
|
|
64
|
-
case '
|
|
68
|
+
case 'uploadTypes': {
|
|
65
69
|
uploadTypes(args);
|
|
66
70
|
break;
|
|
67
71
|
}
|
|
68
|
-
case '
|
|
69
|
-
|
|
72
|
+
case 'uploadOptionSets': {
|
|
73
|
+
UploadOptionSets(args);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case 'parseTypesFromLocalFiles': {
|
|
77
|
+
ParseTypesFromLocalFiles(args);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'parseTypesFromFiles': {
|
|
81
|
+
ParseTypesFromFiles(args);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'mergeOptionSets': {
|
|
85
|
+
MergeOptionSets(args);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'mergeTypeProperties': {
|
|
89
|
+
MergeTypeProperties(args);
|
|
70
90
|
break;
|
|
71
91
|
}
|
|
72
92
|
default: {
|
|
@@ -129,8 +149,22 @@ const helpSections = [
|
|
|
129
149
|
header: 'Type Commands - Domain: types',
|
|
130
150
|
content: [
|
|
131
151
|
'getAll Get all OptionSets and Types for your Org.',
|
|
132
|
-
'
|
|
133
|
-
'
|
|
152
|
+
'uploadTypes Upload Types for your Org.',
|
|
153
|
+
'. Types are uploaded from types.yml\n',
|
|
154
|
+
'uploadOptionSets Upload OptionSets for your Org.',
|
|
155
|
+
'. OptionSets are loaded from option_sets.yml\n',
|
|
156
|
+
'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
|
|
157
|
+
'. OptionSets from local files.\n',
|
|
158
|
+
'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
|
|
159
|
+
'. OptionSets from VibeIQ Files.\n',
|
|
160
|
+
'mergeOptionSets <File Path> Merge the OptionSets from an existing',
|
|
161
|
+
'. org and the OptionSets passed in.',
|
|
162
|
+
'. File must be .yml\n',
|
|
163
|
+
'mergeTypeProperties <File Path> <TypePaths> ',
|
|
164
|
+
'. Merge the TypeProperties from an existing',
|
|
165
|
+
'. org and the TypeProperties passed in.',
|
|
166
|
+
'. Add to Types via TypePath',
|
|
167
|
+
'. File must be .yml\n',
|
|
134
168
|
],
|
|
135
169
|
},
|
|
136
170
|
];
|
package/src/types/interfaces.ts
CHANGED
|
@@ -3,10 +3,10 @@ export interface ReducedType {
|
|
|
3
3
|
label: string;
|
|
4
4
|
typePath: string;
|
|
5
5
|
isArchived: boolean;
|
|
6
|
-
typeProperties:
|
|
6
|
+
typeProperties: ReducedTypeProperty[];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface ReducedTypeProperty {
|
|
10
10
|
id: string;
|
|
11
11
|
isArchived: boolean;
|
|
12
12
|
propertyType: PropertyType;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import { ReducedOptionSet } from './interfaces';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { getSeparatorByPlatform } from '../common';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
|
|
9
|
+
export async function MergeOptionSets(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 MERGE'));
|
|
15
|
+
const fileLocation = args[3];
|
|
16
|
+
console.log('Using File: ', fileLocation);
|
|
17
|
+
|
|
18
|
+
await mergeOptionSets(fileLocation);
|
|
19
|
+
console.log(`%s Merged`, chalk.yellow.bold('OPTION SET MERGE'));
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.log(`%s Merge Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log('%s Merge Complete.', chalk.green.bold('COMPLETE'));
|
|
28
|
+
}
|
|
29
|
+
function loadOptionSets(fileLocation) {
|
|
30
|
+
const TARGET_DIR = process.cwd();
|
|
31
|
+
try {
|
|
32
|
+
const separator = getSeparatorByPlatform();
|
|
33
|
+
|
|
34
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
35
|
+
console.log('Getting file from path: ', fullPath);
|
|
36
|
+
|
|
37
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
38
|
+
return doc.optionSets;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function mergeOptionSets(fileLocation) {
|
|
45
|
+
const uploadedOptionSets: ReducedOptionSet[] = loadOptionSets(fileLocation);
|
|
46
|
+
|
|
47
|
+
await authUser();
|
|
48
|
+
|
|
49
|
+
const currentOptionSetsFull: any[] = await new Entities().get({
|
|
50
|
+
entityName: 'type-property-option-set',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const currentOptionSets = currentOptionSetsFull.map(os => Object.assign({}, {
|
|
54
|
+
name: os.name,
|
|
55
|
+
isArchived: os.isArchived,
|
|
56
|
+
optionSet: os.optionSet,
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
const currentOptionSetsByName = {};
|
|
60
|
+
for (const currentOptionSet of currentOptionSets) {
|
|
61
|
+
currentOptionSetsByName[currentOptionSet.name] = currentOptionSet;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const uploadedOptionSetsByName = {};
|
|
65
|
+
for (const optionSet of uploadedOptionSets) {
|
|
66
|
+
uploadedOptionSetsByName[optionSet.name] = optionSet;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const mergedOptionSets: any[] = []
|
|
70
|
+
for (const uploadedOptionSet of uploadedOptionSets) {
|
|
71
|
+
const existing = currentOptionSetsByName[uploadedOptionSet.name];
|
|
72
|
+
if (!existing) {
|
|
73
|
+
if (!uploadedOptionSet.optionSet) {
|
|
74
|
+
console.log('No OptionSet for: ', uploadedOptionSet.name);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
console.log('Adding New: ', uploadedOptionSet.name);
|
|
78
|
+
mergedOptionSets.push(uploadedOptionSet);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log('Merging: ', uploadedOptionSet.name);
|
|
82
|
+
mergedOptionSets.push(mergeOptionSet(existing, uploadedOptionSet));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const currentOptionSet of currentOptionSets) {
|
|
87
|
+
const found = uploadedOptionSetsByName[currentOptionSet.name];
|
|
88
|
+
if (!found) {
|
|
89
|
+
console.log('Adding Existing: ', currentOptionSet.name);
|
|
90
|
+
mergedOptionSets.push(currentOptionSet);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
saveData({optionSets: mergedOptionSets})
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function mergeOptionSet(existingOptionSet: ReducedOptionSet, uploadedOptionSet: ReducedOptionSet) {
|
|
98
|
+
const merged = {
|
|
99
|
+
name: uploadedOptionSet.name,
|
|
100
|
+
optionSet: uploadedOptionSet.optionSet,
|
|
101
|
+
isArchived: uploadedOptionSet.isArchived,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
for (const keyVal of existingOptionSet.optionSet) {
|
|
105
|
+
const value = keyVal.value
|
|
106
|
+
const display = keyVal.display
|
|
107
|
+
|
|
108
|
+
const found = merged.optionSet.find(keyVal => keyVal.value === value)
|
|
109
|
+
if (!found) {
|
|
110
|
+
merged.optionSet.push({value, display})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return merged;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function saveData(data) {
|
|
119
|
+
const yamlStr = yaml.dump(data);
|
|
120
|
+
const CURRENT_DIR = process.cwd();
|
|
121
|
+
const separator = getSeparatorByPlatform();
|
|
122
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'merged_optionSets.yml', yamlStr, 'utf8');
|
|
123
|
+
}
|