@contrail/cli 1.0.51 → 1.0.54
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 +38 -12
- package/lib/projects/project-exporter.d.ts +2 -0
- package/lib/projects/project-exporter.js +163 -0
- package/lib/types/option-set-hierarchy-exporter.d.ts +1 -0
- package/lib/types/option-set-hierarchy-exporter.js +113 -0
- package/lib/types/option-set-hierarchy-parser.d.ts +2 -2
- package/lib/types/option-set-hierarchy-parser.js +9 -9
- package/package.json +3 -2
- package/src/cli.ts +38 -12
- package/src/projects/project-exporter.ts +194 -0
- package/src/types/option-set-hierarchy-exporter.ts +125 -0
- package/src/types/option-set-hierarchy-parser.ts +9 -9
package/lib/cli.js
CHANGED
|
@@ -4,7 +4,8 @@ import { getTypes } from './types/types-extractor';
|
|
|
4
4
|
import { uploadTypes } from './types/types-uploader';
|
|
5
5
|
import { UploadOptionSets } from './types/option-set-uploader';
|
|
6
6
|
import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
7
|
-
import {
|
|
7
|
+
import { ParseOptionSetsHierarchyLocalFile, UploadOptionSetsHierarchyLocalFile } from './types/option-set-hierarchy-parser';
|
|
8
|
+
import { ExportOptionSetsHierarchies } from './types/option-set-hierarchy-exporter';
|
|
8
9
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
9
10
|
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
10
11
|
import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles, ParseTypesFromTemplateAndDataFromLocalFiles } from './types/parse-types';
|
|
@@ -15,6 +16,7 @@ import { installApp, uninstallApp } from './apps/install-app/app-installer';
|
|
|
15
16
|
import { upgradeApp } from './apps/upgrade-app/app-upgrader';
|
|
16
17
|
import { cliInstallWorkflowTemplateDefinitions, listWorkflowTemplateDefinitions } from './workflow-template-definitions/workflow-template-definition-commands';
|
|
17
18
|
import { configureProject } from './projects/project-uploader';
|
|
19
|
+
import { ListProjects, ExportProject } from './projects/project-exporter';
|
|
18
20
|
import { Load, UploadAndLoad } from './loader-process/loader-process';
|
|
19
21
|
const cliUsage = require('command-line-usage');
|
|
20
22
|
/**
|
|
@@ -92,12 +94,16 @@ export async function cli(args) {
|
|
|
92
94
|
ParseOptionSetsLocalFiles(args);
|
|
93
95
|
break;
|
|
94
96
|
}
|
|
95
|
-
case '
|
|
96
|
-
|
|
97
|
+
case 'parseOptionSetsHierarchyLocalFile': {
|
|
98
|
+
ParseOptionSetsHierarchyLocalFile(args);
|
|
97
99
|
break;
|
|
98
100
|
}
|
|
99
|
-
case '
|
|
100
|
-
|
|
101
|
+
case 'uploadOptionSetsHierarchyLocalFile': {
|
|
102
|
+
UploadOptionSetsHierarchyLocalFile(args);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'exportOptionSetsHierarchies': {
|
|
106
|
+
ExportOptionSetsHierarchies();
|
|
101
107
|
break;
|
|
102
108
|
}
|
|
103
109
|
case 'parseTypesFromLocalFiles': {
|
|
@@ -164,10 +170,18 @@ export async function cli(args) {
|
|
|
164
170
|
}
|
|
165
171
|
case 'projects': {
|
|
166
172
|
switch (command) {
|
|
167
|
-
case '
|
|
173
|
+
case 'load': {
|
|
168
174
|
await configureProject(args);
|
|
169
175
|
break;
|
|
170
176
|
}
|
|
177
|
+
case 'list': {
|
|
178
|
+
await ListProjects();
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case 'export': {
|
|
182
|
+
await ExportProject(args);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
171
185
|
default: {
|
|
172
186
|
printIllegalCommand();
|
|
173
187
|
}
|
|
@@ -316,8 +330,16 @@ const helpSections = [
|
|
|
316
330
|
{
|
|
317
331
|
header: 'Project Commands - Domain: projects',
|
|
318
332
|
content: [{
|
|
319
|
-
name: '
|
|
333
|
+
name: 'load <File Path>',
|
|
320
334
|
summary: 'Configure a project from a yml file.'
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: 'list',
|
|
338
|
+
summary: 'Get a list of all projects.'
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: 'export <Project Name>',
|
|
342
|
+
summary: 'Export a project.'
|
|
321
343
|
}
|
|
322
344
|
],
|
|
323
345
|
},
|
|
@@ -367,15 +389,19 @@ const helpSections = [
|
|
|
367
389
|
},
|
|
368
390
|
{
|
|
369
391
|
name: 'parseOptionSetsLocalFiles <File Paths>',
|
|
370
|
-
summary: 'Parse CSV files into OptionSets
|
|
392
|
+
summary: 'Parse CSV files into OptionSets.\n'
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: 'parseOptionSetsHierarchyLocalFile <File Path>',
|
|
396
|
+
summary: 'Parse CSV file into OptionSetHierarchy.'
|
|
371
397
|
},
|
|
372
398
|
{
|
|
373
|
-
name: '
|
|
374
|
-
summary: '
|
|
399
|
+
name: 'uploadOptionSetsHierarchyLocalFile <File Path> <name>',
|
|
400
|
+
summary: 'upload CSV file into OptionSetHierarchy.'
|
|
375
401
|
},
|
|
376
402
|
{
|
|
377
|
-
name: '
|
|
378
|
-
summary: '
|
|
403
|
+
name: 'exportOptionSetsHierarchies',
|
|
404
|
+
summary: 'export OptionSetHierarchies into CSVs.\n'
|
|
379
405
|
},
|
|
380
406
|
{
|
|
381
407
|
name: 'parseTypesFromLocalFiles <File Paths>',
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import { ObjectUtil } from '@contrail/util';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import { getSeparatorByPlatform } from '../common';
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
export async function ListProjects() {
|
|
9
|
+
try {
|
|
10
|
+
await authUser();
|
|
11
|
+
console.log('%s Getting Projects.', chalk.blue.bold('START'));
|
|
12
|
+
await listProjects();
|
|
13
|
+
console.log('%s Done', chalk.yellow.bold('PROJECTS'));
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log(`%s Project download Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log('%s Project download Complete.', chalk.green.bold('COMPLETE'));
|
|
20
|
+
}
|
|
21
|
+
export async function ExportProject(args) {
|
|
22
|
+
try {
|
|
23
|
+
await authUser();
|
|
24
|
+
console.log('%s Exporting Project.', chalk.blue.bold('START'));
|
|
25
|
+
console.log('%s Exporting', chalk.yellow.bold('PROJECT'));
|
|
26
|
+
const projectName = args[3];
|
|
27
|
+
await exportProject(projectName);
|
|
28
|
+
console.log('%s Exported', chalk.yellow.bold('PROJECT'));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.log(`%s Project Export Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log('%s Project Export Complete.', chalk.green.bold('COMPLETE'));
|
|
35
|
+
}
|
|
36
|
+
async function listProjects() {
|
|
37
|
+
const allWorkspaces = await new Entities().get({
|
|
38
|
+
entityName: 'workspace',
|
|
39
|
+
criteria: { isArchived: false }
|
|
40
|
+
});
|
|
41
|
+
console.log('%s', chalk.green.bold('PROJECTS:'));
|
|
42
|
+
//console.log(allWorkspaces.map(w => Object.assign({}, {name: w.name, id: w.id}))); // if we want ids
|
|
43
|
+
console.log(allWorkspaces.map(w => w.name));
|
|
44
|
+
}
|
|
45
|
+
async function exportProject(name) {
|
|
46
|
+
const allWorkspaces = await new Entities().get({
|
|
47
|
+
entityName: 'workspace',
|
|
48
|
+
useSearch: false,
|
|
49
|
+
});
|
|
50
|
+
const workspace = allWorkspaces.find(w => w.name === name);
|
|
51
|
+
if (!workspace) {
|
|
52
|
+
throw new Error('Project was not found.');
|
|
53
|
+
}
|
|
54
|
+
const projectConfiguration = {
|
|
55
|
+
projectName: workspace.name,
|
|
56
|
+
identifier: workspace.identifier,
|
|
57
|
+
commonConfig: {},
|
|
58
|
+
assortments: [],
|
|
59
|
+
subFolders: []
|
|
60
|
+
};
|
|
61
|
+
const allAssortments = [];
|
|
62
|
+
await getAssortmentsAndSubFolders(workspace.id, projectConfiguration.assortments, projectConfiguration.subFolders, allAssortments);
|
|
63
|
+
await convertRelationshipsInFolders(projectConfiguration, allAssortments);
|
|
64
|
+
saveData({ projectConfiguration: projectConfiguration }, name);
|
|
65
|
+
}
|
|
66
|
+
async function getAssortmentsAndSubFolders(parentId, assortments, subFolders, allAssortments) {
|
|
67
|
+
const workspaceAssortments = await new Entities().get({
|
|
68
|
+
entityName: 'assortment',
|
|
69
|
+
criteria: {
|
|
70
|
+
workspaceId: parentId,
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const integrationAssortments = workspaceAssortments === null || workspaceAssortments === void 0 ? void 0 : workspaceAssortments.filter(a => a.assortmentType === 'INTEGRATION');
|
|
74
|
+
if ((integrationAssortments === null || integrationAssortments === void 0 ? void 0 : integrationAssortments.length) > 0) {
|
|
75
|
+
allAssortments.push(...integrationAssortments);
|
|
76
|
+
for (const a of integrationAssortments) {
|
|
77
|
+
const integrationAssortmentsCopy = ObjectUtil.cloneDeep(a);
|
|
78
|
+
deleteNonUserKeys(integrationAssortmentsCopy);
|
|
79
|
+
const converted = {
|
|
80
|
+
identifier: a.identifier,
|
|
81
|
+
name: a.name,
|
|
82
|
+
type: 'ASSORTMENT',
|
|
83
|
+
sourceAssortmentIdentifier: [],
|
|
84
|
+
sourceAssortmentIds: a.sourceAssortmentIds,
|
|
85
|
+
composedFromAssortmentIdentifiers: [],
|
|
86
|
+
composedFromAssortmentIds: a.composedFromAssortmentIds,
|
|
87
|
+
assortmentAtts: Object.assign({}, integrationAssortmentsCopy),
|
|
88
|
+
};
|
|
89
|
+
assortments.push(converted);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
console.log('workspaceFolderLinks call');
|
|
93
|
+
const workspaceFolderLinks = await new Entities().get({
|
|
94
|
+
entityName: 'workspace-entity',
|
|
95
|
+
criteria: {
|
|
96
|
+
workspaceId: parentId,
|
|
97
|
+
entityType: 'workspace'
|
|
98
|
+
},
|
|
99
|
+
relations: ['entity']
|
|
100
|
+
});
|
|
101
|
+
const workspaceFolders = workspaceFolderLinks === null || workspaceFolderLinks === void 0 ? void 0 : workspaceFolderLinks.map(wfl => wfl.entity);
|
|
102
|
+
if ((workspaceFolders === null || workspaceFolders === void 0 ? void 0 : workspaceFolders.length) > 0) {
|
|
103
|
+
for (const folder of workspaceFolders) {
|
|
104
|
+
const converted = {
|
|
105
|
+
identifier: folder.identifier,
|
|
106
|
+
name: folder.name,
|
|
107
|
+
assortments: [],
|
|
108
|
+
subFolders: [],
|
|
109
|
+
};
|
|
110
|
+
await getAssortmentsAndSubFolders(folder.id, converted.assortments, converted.subFolders, allAssortments);
|
|
111
|
+
subFolders.push(converted);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function convertRelationshipsInFolders(folder, allAssortments) {
|
|
116
|
+
if (!(allAssortments.length > 0)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
convertRelationshipsToIdentifiers(folder.assortments, allAssortments);
|
|
120
|
+
for (const f of folder.subFolders) {
|
|
121
|
+
convertRelationshipsInFolders(f, allAssortments);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function convertRelationshipsToIdentifiers(assortments, allAssortments) {
|
|
125
|
+
if (!(allAssortments.length > 0)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
for (const assortment of assortments) {
|
|
129
|
+
if (assortment.sourceAssortmentIds) {
|
|
130
|
+
assortment.sourceAssortmentIdentifier = assortment.sourceAssortmentIds.map(id => { var _a; return (_a = allAssortments.find(a => a.id === id)) === null || _a === void 0 ? void 0 : _a.identifier; });
|
|
131
|
+
}
|
|
132
|
+
delete assortment.sourceAssortmentIds;
|
|
133
|
+
if (assortment.composedFromAssortmentIds) {
|
|
134
|
+
assortment.composedFromAssortmentIdentifiers = assortment.composedFromAssortmentIds.map(id => { var _a; return (_a = allAssortments.find(a => a.id === id)) === null || _a === void 0 ? void 0 : _a.identifier; });
|
|
135
|
+
}
|
|
136
|
+
delete assortment.composedFromAssortmentIds;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function deleteNonUserKeys(assortment) {
|
|
140
|
+
delete assortment.name;
|
|
141
|
+
delete assortment.identifier;
|
|
142
|
+
delete assortment.assortmentType;
|
|
143
|
+
delete assortment.createdById;
|
|
144
|
+
delete assortment.createdForReference;
|
|
145
|
+
delete assortment.createdOn;
|
|
146
|
+
delete assortment.entityType;
|
|
147
|
+
delete assortment.id;
|
|
148
|
+
delete assortment.orgId;
|
|
149
|
+
delete assortment.rootWorkspaceId;
|
|
150
|
+
delete assortment.composedFromAssortmentIds;
|
|
151
|
+
delete assortment.sourceAssortmentIds;
|
|
152
|
+
delete assortment.typeId;
|
|
153
|
+
delete assortment.typePath;
|
|
154
|
+
delete assortment.updatedById;
|
|
155
|
+
delete assortment.updatedOn;
|
|
156
|
+
delete assortment.workspaceId;
|
|
157
|
+
}
|
|
158
|
+
function saveData(data, name) {
|
|
159
|
+
const yamlStr = yaml.dump(data);
|
|
160
|
+
const CURRENT_DIR = process.cwd();
|
|
161
|
+
const separator = getSeparatorByPlatform();
|
|
162
|
+
fs.writeFileSync(CURRENT_DIR + separator + name + '-export.yml', yamlStr, 'utf8');
|
|
163
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ExportOptionSetsHierarchies(): Promise<void>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { getSeparatorByPlatform } from '../common';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Entities } from '@contrail/sdk';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import { ObjectUtil, StringUtil } from '@contrail/util';
|
|
7
|
+
const { Parser } = require('json2csv');
|
|
8
|
+
export async function ExportOptionSetsHierarchies() {
|
|
9
|
+
try {
|
|
10
|
+
await authUser();
|
|
11
|
+
console.log('%s Exporting local file', chalk.yellow.bold('OPTION SET HIERARCHY EXPORT'));
|
|
12
|
+
await exportOptionSetHierarchies();
|
|
13
|
+
console.log('%s Exported', chalk.yellow.bold('OPTION SET HIERARCHY EXPORT'));
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log(`%s EXPORT Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log('%s EXPORT Complete.', chalk.green.bold('COMPLETE'));
|
|
20
|
+
}
|
|
21
|
+
async function exportOptionSetHierarchies() {
|
|
22
|
+
const allOptionSetHierarchies = await new Entities().get({
|
|
23
|
+
entityName: 'option-set-hierarchy',
|
|
24
|
+
});
|
|
25
|
+
const currentOptionSets = await new Entities().get({
|
|
26
|
+
entityName: 'type-property-option-set',
|
|
27
|
+
});
|
|
28
|
+
for (const optionSetHierarchy of allOptionSetHierarchies) {
|
|
29
|
+
const levelNameInOrder = [];
|
|
30
|
+
for (const optionSetId of optionSetHierarchy.hierarchy) {
|
|
31
|
+
const os = currentOptionSets.find(os => os.id === optionSetId);
|
|
32
|
+
levelNameInOrder.push(StringUtil.convertToCamelCase(os.name));
|
|
33
|
+
}
|
|
34
|
+
transformAndSave(optionSetHierarchy, levelNameInOrder);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function transformAndSave(optionSetHierarchy, levelNameInOrder) {
|
|
38
|
+
const finalObjects = [];
|
|
39
|
+
transform(optionSetHierarchy.options, levelNameInOrder, [], finalObjects);
|
|
40
|
+
saveData(optionSetHierarchy.name, finalObjects, levelNameInOrder);
|
|
41
|
+
}
|
|
42
|
+
/*
|
|
43
|
+
Transform will take in a set if options, the names left to process, the partly completed objects, and the list to place the final objects.
|
|
44
|
+
On the first pass the list of names will be full and the list of partial objects will be empty. On this pass we create objects
|
|
45
|
+
with one field, the name of the field is the first name in levelNameInOrder. These objects are added to the workingObjects list
|
|
46
|
+
for the next run. On the following (recursive) runs there will be one less name in the levelNameInOrder (we remove the name we just processed)
|
|
47
|
+
and there will be objects to clone and add to in the workingObjects list. When all the objects have been created (There are no names
|
|
48
|
+
left in the levelNameInOrder list), all the objects are added to the finalObjects list.
|
|
49
|
+
|
|
50
|
+
Initial Input:
|
|
51
|
+
options: {value: "BTP", options: [{value: "The Great"}, {value: "The Best"}]}
|
|
52
|
+
levelNameInOrder: ["name", "title"]
|
|
53
|
+
workingObjects: []
|
|
54
|
+
finalObjects: []
|
|
55
|
+
|
|
56
|
+
Level 2 Input 1:
|
|
57
|
+
options: [{value: "The Great"}]
|
|
58
|
+
levelNameInOrder: ["title"]
|
|
59
|
+
workingObjects: [{name: "BTP"}]
|
|
60
|
+
finalObjects: []
|
|
61
|
+
|
|
62
|
+
Level 2 Input 2:
|
|
63
|
+
options: [{value: "The Best"}]
|
|
64
|
+
levelNameInOrder: ["title"]
|
|
65
|
+
workingObjects: [{name: "BTP"}]
|
|
66
|
+
finalObjects: []
|
|
67
|
+
|
|
68
|
+
Final Objects:
|
|
69
|
+
[{name: "BTP", title: "The Great"}, {name: "BTP", title: "The Best"}]
|
|
70
|
+
*/
|
|
71
|
+
function transform(options, levelNameInOrder, workingObjects, finalObjects) {
|
|
72
|
+
for (const option of options) {
|
|
73
|
+
const localObjects = [];
|
|
74
|
+
if (workingObjects.length === 0) {
|
|
75
|
+
localObjects.push({ [levelNameInOrder[0]]: option.value });
|
|
76
|
+
if (levelNameInOrder.length <= 1) {
|
|
77
|
+
finalObjects.push(...localObjects);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
transform(option.options, levelNameInOrder.slice(1), localObjects, finalObjects);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
for (const workingObject of workingObjects) {
|
|
85
|
+
const clone = ObjectUtil.cloneDeep(workingObject);
|
|
86
|
+
clone[levelNameInOrder[0]] = option.value;
|
|
87
|
+
localObjects.push(clone);
|
|
88
|
+
}
|
|
89
|
+
if (levelNameInOrder.length <= 1) {
|
|
90
|
+
finalObjects.push(...localObjects);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
transform(option.options, levelNameInOrder.slice(1), localObjects, finalObjects);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function saveData(name, data, fieldNames) {
|
|
99
|
+
const CURRENT_DIR = process.cwd();
|
|
100
|
+
const separator = getSeparatorByPlatform();
|
|
101
|
+
const opts = { fieldNames };
|
|
102
|
+
try {
|
|
103
|
+
const parser = new Parser(opts);
|
|
104
|
+
const csv = parser.parse(data);
|
|
105
|
+
fs.mkdirSync(CURRENT_DIR + separator + 'option-set-hierarchies', { recursive: true });
|
|
106
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'option-set-hierarchies' + separator + name + '.csv', csv, {
|
|
107
|
+
flag: 'w',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error(err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function
|
|
2
|
-
export declare function
|
|
1
|
+
export declare function ParseOptionSetsHierarchyLocalFile(args: any): Promise<void>;
|
|
2
|
+
export declare function UploadOptionSetsHierarchyLocalFile(args: any): Promise<void>;
|
|
@@ -5,7 +5,7 @@ const csv = require('csvtojson');
|
|
|
5
5
|
import { Entities } from '@contrail/sdk';
|
|
6
6
|
import { StringUtil } from '@contrail/util';
|
|
7
7
|
import { authUser } from '../auth/login';
|
|
8
|
-
export async function
|
|
8
|
+
export async function ParseOptionSetsHierarchyLocalFile(args) {
|
|
9
9
|
try {
|
|
10
10
|
await authUser();
|
|
11
11
|
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
@@ -14,7 +14,7 @@ export async function ParseOptionSetsHierarchyLocalFiles(args) {
|
|
|
14
14
|
console.log('%s Importing local file', chalk.yellow.bold('OPTION SET HIERARCHY PARSE'));
|
|
15
15
|
const fileLocation = args[3];
|
|
16
16
|
console.log('Using File: ', fileLocation);
|
|
17
|
-
await
|
|
17
|
+
await parseAndSaveOptionSetHierarchiesLocalFile(fileLocation);
|
|
18
18
|
console.log('%s Parsed', chalk.yellow.bold('OPTION SET HIERARCHY PARSE'));
|
|
19
19
|
}
|
|
20
20
|
catch (e) {
|
|
@@ -23,7 +23,7 @@ export async function ParseOptionSetsHierarchyLocalFiles(args) {
|
|
|
23
23
|
}
|
|
24
24
|
console.log('%s PARSE Complete.', chalk.green.bold('COMPLETE'));
|
|
25
25
|
}
|
|
26
|
-
export async function
|
|
26
|
+
export async function UploadOptionSetsHierarchyLocalFile(args) {
|
|
27
27
|
try {
|
|
28
28
|
await authUser();
|
|
29
29
|
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
@@ -34,7 +34,7 @@ export async function UploadOptionSetsHierarchyLocalFiles(args) {
|
|
|
34
34
|
const name = args[4];
|
|
35
35
|
console.log('Using File: ', fileLocation);
|
|
36
36
|
console.log('Using Name: ', name);
|
|
37
|
-
await
|
|
37
|
+
await uploadOptionSetHierarchiesLocalFile(fileLocation, name);
|
|
38
38
|
console.log('%s Uploaded', chalk.yellow.bold('OPTION SET HIERARCHY UPLOAD'));
|
|
39
39
|
}
|
|
40
40
|
catch (e) {
|
|
@@ -55,7 +55,7 @@ async function loadOptionSetHierarchyCSV(fileLocation) {
|
|
|
55
55
|
throw new Error(`ERROR PARSING CSV: ${e}`);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
async function
|
|
58
|
+
async function parseOptionSetHierarchiesLocalFile(fileLocation) {
|
|
59
59
|
const uploadedOptionHierarchyData = await loadOptionSetHierarchyCSV(fileLocation);
|
|
60
60
|
const optionSetHierarchy = {
|
|
61
61
|
hierarchy: [],
|
|
@@ -90,12 +90,12 @@ async function parseOptionSetHierarchiesLocalFiles(fileLocation) {
|
|
|
90
90
|
}
|
|
91
91
|
return optionSetHierarchy;
|
|
92
92
|
}
|
|
93
|
-
async function
|
|
94
|
-
const optionSetHierarchy = await
|
|
93
|
+
async function parseAndSaveOptionSetHierarchiesLocalFile(fileLocation) {
|
|
94
|
+
const optionSetHierarchy = await parseOptionSetHierarchiesLocalFile(fileLocation);
|
|
95
95
|
saveData(optionSetHierarchy.options);
|
|
96
96
|
}
|
|
97
|
-
async function
|
|
98
|
-
const optionSetHierarchy = await
|
|
97
|
+
async function uploadOptionSetHierarchiesLocalFile(fileLocation, name) {
|
|
98
|
+
const optionSetHierarchy = await parseOptionSetHierarchiesLocalFile(fileLocation);
|
|
99
99
|
optionSetHierarchy.name = name;
|
|
100
100
|
const currentOptionSetHierarchies = await new Entities().get({
|
|
101
101
|
entityName: 'option-set-hierarchy',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
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.1.
|
|
26
|
+
"@contrail/sdk": "^1.1.52",
|
|
27
27
|
"@contrail/types": "^3.0.20",
|
|
28
28
|
"@contrail/util": "^1.0.17",
|
|
29
29
|
"amazon-cognito-identity-js": "^5.2.3",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"execa": "^5.0.0",
|
|
38
38
|
"inquirer": "^8.2.0",
|
|
39
39
|
"js-yaml": "^4.1.0",
|
|
40
|
+
"json2csv": "^5.0.7",
|
|
40
41
|
"listr": "^0.14.3",
|
|
41
42
|
"lodash": "^4.17.21",
|
|
42
43
|
"ncp": "^2.0.0",
|
package/src/cli.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { getTypes } from './types/types-extractor';
|
|
|
5
5
|
import { uploadTypes } from './types/types-uploader';
|
|
6
6
|
import { UploadOptionSets } from './types/option-set-uploader';
|
|
7
7
|
import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
8
|
-
import {
|
|
8
|
+
import { ParseOptionSetsHierarchyLocalFile, UploadOptionSetsHierarchyLocalFile } from './types/option-set-hierarchy-parser';
|
|
9
|
+
import { ExportOptionSetsHierarchies } from './types/option-set-hierarchy-exporter';
|
|
9
10
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
10
11
|
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
11
12
|
import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles, ParseTypesFromTemplateAndDataFromLocalFiles } from './types/parse-types';
|
|
@@ -16,6 +17,7 @@ import { installApp, uninstallApp } from './apps/install-app/app-installer';
|
|
|
16
17
|
import { upgradeApp } from './apps/upgrade-app/app-upgrader';
|
|
17
18
|
import { cliInstallWorkflowTemplateDefinitions, listWorkflowTemplateDefinitions } from './workflow-template-definitions/workflow-template-definition-commands';
|
|
18
19
|
import { configureProject } from './projects/project-uploader';
|
|
20
|
+
import { ListProjects, ExportProject } from './projects/project-exporter';
|
|
19
21
|
import { Load, UploadAndLoad } from './loader-process/loader-process';
|
|
20
22
|
|
|
21
23
|
const cliUsage = require('command-line-usage');
|
|
@@ -102,12 +104,16 @@ export async function cli(args) {
|
|
|
102
104
|
ParseOptionSetsLocalFiles(args);
|
|
103
105
|
break;
|
|
104
106
|
}
|
|
105
|
-
case '
|
|
106
|
-
|
|
107
|
+
case 'parseOptionSetsHierarchyLocalFile': {
|
|
108
|
+
ParseOptionSetsHierarchyLocalFile(args);
|
|
107
109
|
break;
|
|
108
110
|
}
|
|
109
|
-
case '
|
|
110
|
-
|
|
111
|
+
case 'uploadOptionSetsHierarchyLocalFile': {
|
|
112
|
+
UploadOptionSetsHierarchyLocalFile(args);
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case 'exportOptionSetsHierarchies': {
|
|
116
|
+
ExportOptionSetsHierarchies();
|
|
111
117
|
break;
|
|
112
118
|
}
|
|
113
119
|
case 'parseTypesFromLocalFiles': {
|
|
@@ -174,10 +180,18 @@ export async function cli(args) {
|
|
|
174
180
|
}
|
|
175
181
|
case 'projects': {
|
|
176
182
|
switch (command) {
|
|
177
|
-
case '
|
|
183
|
+
case 'load': {
|
|
178
184
|
await configureProject(args);
|
|
179
185
|
break;
|
|
180
186
|
}
|
|
187
|
+
case 'list': {
|
|
188
|
+
await ListProjects();
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case 'export': {
|
|
192
|
+
await ExportProject(args);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
181
195
|
default: {
|
|
182
196
|
printIllegalCommand();
|
|
183
197
|
}
|
|
@@ -331,8 +345,16 @@ const helpSections = [
|
|
|
331
345
|
{
|
|
332
346
|
header: 'Project Commands - Domain: projects',
|
|
333
347
|
content: [{
|
|
334
|
-
name: '
|
|
348
|
+
name: 'load <File Path>',
|
|
335
349
|
summary: 'Configure a project from a yml file.'
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
name: 'list',
|
|
353
|
+
summary: 'Get a list of all projects.'
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: 'export <Project Name>',
|
|
357
|
+
summary: 'Export a project.'
|
|
336
358
|
}
|
|
337
359
|
],
|
|
338
360
|
},
|
|
@@ -382,15 +404,19 @@ const helpSections = [
|
|
|
382
404
|
},
|
|
383
405
|
{
|
|
384
406
|
name: 'parseOptionSetsLocalFiles <File Paths>',
|
|
385
|
-
summary: 'Parse CSV files into OptionSets
|
|
407
|
+
summary: 'Parse CSV files into OptionSets.\n'
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'parseOptionSetsHierarchyLocalFile <File Path>',
|
|
411
|
+
summary: 'Parse CSV file into OptionSetHierarchy.'
|
|
386
412
|
},
|
|
387
413
|
{
|
|
388
|
-
name: '
|
|
389
|
-
summary: '
|
|
414
|
+
name: 'uploadOptionSetsHierarchyLocalFile <File Path> <name>',
|
|
415
|
+
summary: 'upload CSV file into OptionSetHierarchy.'
|
|
390
416
|
},
|
|
391
417
|
{
|
|
392
|
-
name: '
|
|
393
|
-
summary: '
|
|
418
|
+
name: 'exportOptionSetsHierarchies',
|
|
419
|
+
summary: 'export OptionSetHierarchies into CSVs.\n'
|
|
394
420
|
},
|
|
395
421
|
{
|
|
396
422
|
name: 'parseTypesFromLocalFiles <File Paths>',
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import { ObjectUtil } from '@contrail/util';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import { getSeparatorByPlatform } from '../common';
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
|
|
9
|
+
export async function ListProjects() {
|
|
10
|
+
try {
|
|
11
|
+
await authUser();
|
|
12
|
+
console.log('%s Getting Projects.', chalk.blue.bold('START'));
|
|
13
|
+
|
|
14
|
+
await listProjects();
|
|
15
|
+
console.log('%s Done', chalk.yellow.bold('PROJECTS'));
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.log(`%s Project download Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log('%s Project download Complete.', chalk.green.bold('COMPLETE'));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function ExportProject(args) {
|
|
27
|
+
try {
|
|
28
|
+
await authUser();
|
|
29
|
+
console.log('%s Exporting Project.', chalk.blue.bold('START'));
|
|
30
|
+
|
|
31
|
+
console.log('%s Exporting', chalk.yellow.bold('PROJECT'));
|
|
32
|
+
const projectName = args[3];
|
|
33
|
+
await exportProject(projectName);
|
|
34
|
+
console.log('%s Exported', chalk.yellow.bold('PROJECT'));
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.log(`%s Project Export Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log('%s Project Export Complete.', chalk.green.bold('COMPLETE'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function listProjects() {
|
|
46
|
+
const allWorkspaces = await new Entities().get({
|
|
47
|
+
entityName: 'workspace',
|
|
48
|
+
criteria: {isArchived: false}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('%s', chalk.green.bold('PROJECTS:'));
|
|
52
|
+
//console.log(allWorkspaces.map(w => Object.assign({}, {name: w.name, id: w.id}))); // if we want ids
|
|
53
|
+
console.log(allWorkspaces.map(w => w.name));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function exportProject(name) {
|
|
57
|
+
const allWorkspaces = await new Entities().get({
|
|
58
|
+
entityName: 'workspace',
|
|
59
|
+
useSearch: false,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const workspace = allWorkspaces.find(w => w.name === name);
|
|
63
|
+
if (!workspace) {
|
|
64
|
+
throw new Error('Project was not found.');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const projectConfiguration = {
|
|
68
|
+
projectName: workspace.name,
|
|
69
|
+
identifier: workspace.identifier,
|
|
70
|
+
commonConfig: {},
|
|
71
|
+
assortments: [],
|
|
72
|
+
subFolders: []
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const allAssortments = [];
|
|
76
|
+
await getAssortmentsAndSubFolders(workspace.id, projectConfiguration.assortments, projectConfiguration.subFolders, allAssortments);
|
|
77
|
+
await convertRelationshipsInFolders(projectConfiguration, allAssortments);
|
|
78
|
+
saveData({projectConfiguration: projectConfiguration}, name);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function getAssortmentsAndSubFolders(parentId, assortments, subFolders, allAssortments) {
|
|
82
|
+
const workspaceAssortments = await new Entities().get({
|
|
83
|
+
entityName: 'assortment',
|
|
84
|
+
criteria: {
|
|
85
|
+
workspaceId: parentId,
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const integrationAssortments = workspaceAssortments?.filter(a => a.assortmentType === 'INTEGRATION');
|
|
90
|
+
|
|
91
|
+
if (integrationAssortments?.length > 0) {
|
|
92
|
+
allAssortments.push(...integrationAssortments);
|
|
93
|
+
for (const a of integrationAssortments) {
|
|
94
|
+
const integrationAssortmentsCopy = ObjectUtil.cloneDeep(a);
|
|
95
|
+
deleteNonUserKeys(integrationAssortmentsCopy);
|
|
96
|
+
const converted = {
|
|
97
|
+
identifier: a.identifier,
|
|
98
|
+
name: a.name,
|
|
99
|
+
type: 'ASSORTMENT',
|
|
100
|
+
sourceAssortmentIdentifier: [],
|
|
101
|
+
sourceAssortmentIds: a.sourceAssortmentIds,
|
|
102
|
+
composedFromAssortmentIdentifiers: [],
|
|
103
|
+
composedFromAssortmentIds: a.composedFromAssortmentIds,
|
|
104
|
+
assortmentAtts: Object.assign({}, integrationAssortmentsCopy),
|
|
105
|
+
};
|
|
106
|
+
assortments.push(converted);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log('workspaceFolderLinks call');
|
|
111
|
+
|
|
112
|
+
const workspaceFolderLinks = await new Entities().get({
|
|
113
|
+
entityName: 'workspace-entity',
|
|
114
|
+
criteria: {
|
|
115
|
+
workspaceId: parentId,
|
|
116
|
+
entityType: 'workspace'
|
|
117
|
+
},
|
|
118
|
+
relations: ['entity']
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const workspaceFolders = workspaceFolderLinks?.map(wfl => wfl.entity);
|
|
122
|
+
|
|
123
|
+
if (workspaceFolders?.length > 0) {
|
|
124
|
+
for (const folder of workspaceFolders) {
|
|
125
|
+
const converted = {
|
|
126
|
+
identifier: folder.identifier,
|
|
127
|
+
name: folder.name,
|
|
128
|
+
assortments: [],
|
|
129
|
+
subFolders: [],
|
|
130
|
+
};
|
|
131
|
+
await getAssortmentsAndSubFolders(folder.id, converted.assortments, converted.subFolders, allAssortments);
|
|
132
|
+
subFolders.push(converted);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function convertRelationshipsInFolders(folder, allAssortments) {
|
|
139
|
+
if (!(allAssortments.length > 0)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
convertRelationshipsToIdentifiers(folder.assortments, allAssortments);
|
|
144
|
+
|
|
145
|
+
for (const f of folder.subFolders) {
|
|
146
|
+
convertRelationshipsInFolders(f, allAssortments);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function convertRelationshipsToIdentifiers(assortments, allAssortments) {
|
|
152
|
+
if (!(allAssortments.length > 0)) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
for (const assortment of assortments) {
|
|
157
|
+
if (assortment.sourceAssortmentIds) {
|
|
158
|
+
assortment.sourceAssortmentIdentifier = assortment.sourceAssortmentIds.map(id => allAssortments.find(a => a.id === id)?.identifier);
|
|
159
|
+
}
|
|
160
|
+
delete assortment.sourceAssortmentIds;
|
|
161
|
+
|
|
162
|
+
if (assortment.composedFromAssortmentIds) {
|
|
163
|
+
assortment.composedFromAssortmentIdentifiers = assortment.composedFromAssortmentIds.map(id => allAssortments.find(a => a.id === id)?.identifier);
|
|
164
|
+
}
|
|
165
|
+
delete assortment.composedFromAssortmentIds;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function deleteNonUserKeys(assortment) {
|
|
170
|
+
delete assortment.name;
|
|
171
|
+
delete assortment.identifier;
|
|
172
|
+
delete assortment.assortmentType;
|
|
173
|
+
delete assortment.createdById;
|
|
174
|
+
delete assortment.createdForReference;
|
|
175
|
+
delete assortment.createdOn;
|
|
176
|
+
delete assortment.entityType;
|
|
177
|
+
delete assortment.id;
|
|
178
|
+
delete assortment.orgId;
|
|
179
|
+
delete assortment.rootWorkspaceId;
|
|
180
|
+
delete assortment.composedFromAssortmentIds;
|
|
181
|
+
delete assortment.sourceAssortmentIds;
|
|
182
|
+
delete assortment.typeId;
|
|
183
|
+
delete assortment.typePath;
|
|
184
|
+
delete assortment.updatedById;
|
|
185
|
+
delete assortment.updatedOn;
|
|
186
|
+
delete assortment.workspaceId;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function saveData(data, name) {
|
|
190
|
+
const yamlStr = yaml.dump(data);
|
|
191
|
+
const CURRENT_DIR = process.cwd();
|
|
192
|
+
const separator = getSeparatorByPlatform();
|
|
193
|
+
fs.writeFileSync(CURRENT_DIR + separator + name + '-export.yml', yamlStr, 'utf8');
|
|
194
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { getSeparatorByPlatform } from '../common';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Entities } from '@contrail/sdk';
|
|
5
|
+
import { authUser } from '../auth/login';
|
|
6
|
+
import { ObjectUtil, StringUtil } from '@contrail/util';
|
|
7
|
+
const { Parser } = require('json2csv');
|
|
8
|
+
|
|
9
|
+
export async function ExportOptionSetsHierarchies() {
|
|
10
|
+
try {
|
|
11
|
+
await authUser();
|
|
12
|
+
|
|
13
|
+
console.log('%s Exporting local file', chalk.yellow.bold('OPTION SET HIERARCHY EXPORT'));
|
|
14
|
+
await exportOptionSetHierarchies();
|
|
15
|
+
console.log('%s Exported', chalk.yellow.bold('OPTION SET HIERARCHY EXPORT'));
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.log(`%s EXPORT Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log('%s EXPORT Complete.', chalk.green.bold('COMPLETE'));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function exportOptionSetHierarchies() {
|
|
27
|
+
const allOptionSetHierarchies = await new Entities().get({
|
|
28
|
+
entityName: 'option-set-hierarchy',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const currentOptionSets = await new Entities().get({
|
|
32
|
+
entityName: 'type-property-option-set',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
for (const optionSetHierarchy of allOptionSetHierarchies) {
|
|
36
|
+
const levelNameInOrder = [];
|
|
37
|
+
for (const optionSetId of optionSetHierarchy.hierarchy) {
|
|
38
|
+
const os = currentOptionSets.find(os => os.id === optionSetId);
|
|
39
|
+
levelNameInOrder.push(StringUtil.convertToCamelCase(os.name));
|
|
40
|
+
}
|
|
41
|
+
transformAndSave(optionSetHierarchy, levelNameInOrder);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function transformAndSave(optionSetHierarchy, levelNameInOrder) {
|
|
46
|
+
const finalObjects = [];
|
|
47
|
+
transform(optionSetHierarchy.options, levelNameInOrder, [], finalObjects);
|
|
48
|
+
saveData(optionSetHierarchy.name, finalObjects, levelNameInOrder);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
Transform will take in a set if options, the names left to process, the partly completed objects, and the list to place the final objects.
|
|
53
|
+
On the first pass the list of names will be full and the list of partial objects will be empty. On this pass we create objects
|
|
54
|
+
with one field, the name of the field is the first name in levelNameInOrder. These objects are added to the workingObjects list
|
|
55
|
+
for the next run. On the following (recursive) runs there will be one less name in the levelNameInOrder (we remove the name we just processed)
|
|
56
|
+
and there will be objects to clone and add to in the workingObjects list. When all the objects have been created (There are no names
|
|
57
|
+
left in the levelNameInOrder list), all the objects are added to the finalObjects list.
|
|
58
|
+
|
|
59
|
+
Initial Input:
|
|
60
|
+
options: {value: "BTP", options: [{value: "The Great"}, {value: "The Best"}]}
|
|
61
|
+
levelNameInOrder: ["name", "title"]
|
|
62
|
+
workingObjects: []
|
|
63
|
+
finalObjects: []
|
|
64
|
+
|
|
65
|
+
Level 2 Input 1:
|
|
66
|
+
options: [{value: "The Great"}]
|
|
67
|
+
levelNameInOrder: ["title"]
|
|
68
|
+
workingObjects: [{name: "BTP"}]
|
|
69
|
+
finalObjects: []
|
|
70
|
+
|
|
71
|
+
Level 2 Input 2:
|
|
72
|
+
options: [{value: "The Best"}]
|
|
73
|
+
levelNameInOrder: ["title"]
|
|
74
|
+
workingObjects: [{name: "BTP"}]
|
|
75
|
+
finalObjects: []
|
|
76
|
+
|
|
77
|
+
Final Objects:
|
|
78
|
+
[{name: "BTP", title: "The Great"}, {name: "BTP", title: "The Best"}]
|
|
79
|
+
*/
|
|
80
|
+
function transform(options, levelNameInOrder, workingObjects, finalObjects) {
|
|
81
|
+
for (const option of options) {
|
|
82
|
+
const localObjects = [];
|
|
83
|
+
if (workingObjects.length === 0) {
|
|
84
|
+
localObjects.push({[levelNameInOrder[0]]: option.value});
|
|
85
|
+
if (levelNameInOrder.length <= 1) {
|
|
86
|
+
finalObjects.push(...localObjects);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
transform(option.options, levelNameInOrder.slice(1,), localObjects, finalObjects);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
for (const workingObject of workingObjects) {
|
|
94
|
+
const clone = ObjectUtil.cloneDeep(workingObject);
|
|
95
|
+
clone[levelNameInOrder[0]] = option.value;
|
|
96
|
+
localObjects.push(clone);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (levelNameInOrder.length <= 1) {
|
|
100
|
+
finalObjects.push(...localObjects);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
transform(option.options, levelNameInOrder.slice(1,), localObjects, finalObjects);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function saveData(name, data, fieldNames) {
|
|
111
|
+
const CURRENT_DIR = process.cwd();
|
|
112
|
+
const separator = getSeparatorByPlatform();
|
|
113
|
+
const opts = { fieldNames };
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const parser = new Parser(opts);
|
|
117
|
+
const csv = parser.parse(data);
|
|
118
|
+
fs.mkdirSync(CURRENT_DIR + separator + 'option-set-hierarchies', { recursive: true });
|
|
119
|
+
fs.writeFileSync(CURRENT_DIR + separator + 'option-set-hierarchies' + separator + name + '.csv', csv, {
|
|
120
|
+
flag: 'w',
|
|
121
|
+
});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(err);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -6,7 +6,7 @@ import { Entities } from '@contrail/sdk';
|
|
|
6
6
|
import { StringUtil } from '@contrail/util';
|
|
7
7
|
import { authUser } from '../auth/login';
|
|
8
8
|
|
|
9
|
-
export async function
|
|
9
|
+
export async function ParseOptionSetsHierarchyLocalFile(args) {
|
|
10
10
|
try {
|
|
11
11
|
await authUser();
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ export async function ParseOptionSetsHierarchyLocalFiles(args) {
|
|
|
17
17
|
const fileLocation = args[3];
|
|
18
18
|
console.log('Using File: ', fileLocation);
|
|
19
19
|
|
|
20
|
-
await
|
|
20
|
+
await parseAndSaveOptionSetHierarchiesLocalFile(fileLocation);
|
|
21
21
|
console.log('%s Parsed', chalk.yellow.bold('OPTION SET HIERARCHY PARSE'));
|
|
22
22
|
|
|
23
23
|
}
|
|
@@ -29,7 +29,7 @@ export async function ParseOptionSetsHierarchyLocalFiles(args) {
|
|
|
29
29
|
console.log('%s PARSE Complete.', chalk.green.bold('COMPLETE'));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export async function
|
|
32
|
+
export async function UploadOptionSetsHierarchyLocalFile(args) {
|
|
33
33
|
try {
|
|
34
34
|
await authUser();
|
|
35
35
|
|
|
@@ -42,7 +42,7 @@ export async function UploadOptionSetsHierarchyLocalFiles(args) {
|
|
|
42
42
|
console.log('Using File: ', fileLocation);
|
|
43
43
|
console.log('Using Name: ', name);
|
|
44
44
|
|
|
45
|
-
await
|
|
45
|
+
await uploadOptionSetHierarchiesLocalFile(fileLocation, name);
|
|
46
46
|
console.log('%s Uploaded', chalk.yellow.bold('OPTION SET HIERARCHY UPLOAD'));
|
|
47
47
|
|
|
48
48
|
}
|
|
@@ -68,7 +68,7 @@ async function loadOptionSetHierarchyCSV(fileLocation) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
async function
|
|
71
|
+
async function parseOptionSetHierarchiesLocalFile(fileLocation) {
|
|
72
72
|
const uploadedOptionHierarchyData = await loadOptionSetHierarchyCSV(fileLocation);
|
|
73
73
|
|
|
74
74
|
const optionSetHierarchy = {
|
|
@@ -112,13 +112,13 @@ async function parseOptionSetHierarchiesLocalFiles(fileLocation) {
|
|
|
112
112
|
return optionSetHierarchy;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
async function
|
|
116
|
-
const optionSetHierarchy = await
|
|
115
|
+
async function parseAndSaveOptionSetHierarchiesLocalFile(fileLocation) {
|
|
116
|
+
const optionSetHierarchy = await parseOptionSetHierarchiesLocalFile(fileLocation);
|
|
117
117
|
saveData(optionSetHierarchy.options);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
async function
|
|
121
|
-
const optionSetHierarchy = await
|
|
120
|
+
async function uploadOptionSetHierarchiesLocalFile(fileLocation, name) {
|
|
121
|
+
const optionSetHierarchy = await parseOptionSetHierarchiesLocalFile(fileLocation);
|
|
122
122
|
optionSetHierarchy.name = name;
|
|
123
123
|
|
|
124
124
|
const currentOptionSetHierarchies = await new Entities().get({
|