@contrail/cli 1.0.66 → 1.0.68
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/apps/create-app/create.js +2 -2
- package/lib/cli.js +47 -4
- package/lib/types/option-set-merger.js +11 -8
- package/lib/types/option-set-parser.d.ts +2 -0
- package/lib/types/option-set-parser.js +98 -8
- package/lib/types/parse-types.js +4 -4
- package/lib/users/user-exporter.d.ts +1 -0
- package/lib/users/user-exporter.js +41 -0
- package/lib/users/user-uploader.d.ts +1 -0
- package/lib/users/user-uploader.js +45 -0
- package/package.json +1 -1
- package/src/apps/create-app/create.ts +2 -2
- package/src/cli.ts +48 -4
- package/src/types/option-set-merger.ts +10 -9
- package/src/types/option-set-parser.ts +114 -8
- package/src/types/parse-types.ts +4 -4
- package/src/users/user-exporter.ts +52 -0
- package/src/users/user-uploader.ts +58 -0
- package/templates/typescript/actions/handler.ts +1 -1
- package/templates/typescript/actions/mock-server.ts +24 -0
- package/templates/typescript/actions/utils/logger.ts +3 -3
- package/templates/typescript/package.json +6 -0
- package/templates/typescript/tsconfig.json +6 -10
|
@@ -17,7 +17,7 @@ function parseArgumentsIntoOptions(rawArgs) {
|
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
async function promptForMissingOptions(options) {
|
|
20
|
-
const defaultTemplate = '
|
|
20
|
+
const defaultTemplate = 'TypeScript';
|
|
21
21
|
const questions = [];
|
|
22
22
|
if (!options.appName) {
|
|
23
23
|
questions.push({
|
|
@@ -32,7 +32,7 @@ async function promptForMissingOptions(options) {
|
|
|
32
32
|
type: 'list',
|
|
33
33
|
name: 'template',
|
|
34
34
|
message: 'Which project template would you like to use?',
|
|
35
|
-
choices: ['
|
|
35
|
+
choices: ['TypeScript', 'JavaScript'],
|
|
36
36
|
default: defaultTemplate,
|
|
37
37
|
});
|
|
38
38
|
}
|
package/lib/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { deployApp, removeApp } from './apps/deploy-app/deploy';
|
|
|
3
3
|
import { getAll } from './types/types-extractor';
|
|
4
4
|
import { uploadTypes } from './types/types-uploader';
|
|
5
5
|
import { UploadOptionSets } from './types/option-set-uploader';
|
|
6
|
-
import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
6
|
+
import { ParseOptionSetsLocalFiles, ParseOptionSetsToFolderStructure } from './types/option-set-parser';
|
|
7
7
|
import { ParseOptionSetsHierarchyLocalFile, UploadOptionSetsHierarchyLocalFile } from './types/option-set-hierarchy-parser';
|
|
8
8
|
import { ExportOptionSetsHierarchies } from './types/option-set-hierarchy-exporter';
|
|
9
9
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
@@ -23,6 +23,8 @@ import { uploadRuleSets } from './types/rule-set-uploader';
|
|
|
23
23
|
import { UploadOptionSetHierarchies } from './types/option-set-hierarchy-uploader';
|
|
24
24
|
import { uploadTypePropertyPolicies } from './types/type-property-policy-uploader';
|
|
25
25
|
import { uploadAll } from './types/allUploader';
|
|
26
|
+
import { ExportUsers } from './users/user-exporter';
|
|
27
|
+
import { UploadUsers } from './users/user-uploader';
|
|
26
28
|
const cliUsage = require('command-line-usage');
|
|
27
29
|
/**
|
|
28
30
|
* Built using documentation here:
|
|
@@ -103,6 +105,10 @@ export async function cli(args) {
|
|
|
103
105
|
ParseOptionSetsLocalFiles(args);
|
|
104
106
|
break;
|
|
105
107
|
}
|
|
108
|
+
case 'parseOptionSetsToFolderStructure': {
|
|
109
|
+
ParseOptionSetsToFolderStructure(args);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
106
112
|
case 'parseOptionSetsHierarchyLocalFile': {
|
|
107
113
|
ParseOptionSetsHierarchyLocalFile(args);
|
|
108
114
|
break;
|
|
@@ -213,6 +219,22 @@ export async function cli(args) {
|
|
|
213
219
|
}
|
|
214
220
|
break;
|
|
215
221
|
}
|
|
222
|
+
case 'users': {
|
|
223
|
+
switch (command) {
|
|
224
|
+
case 'export': {
|
|
225
|
+
await ExportUsers();
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
case 'import': {
|
|
229
|
+
await UploadUsers();
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
default: {
|
|
233
|
+
printIllegalCommand();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
216
238
|
case 'workflow-templates': {
|
|
217
239
|
switch (command) {
|
|
218
240
|
case 'load': {
|
|
@@ -372,6 +394,19 @@ const helpSections = [
|
|
|
372
394
|
}
|
|
373
395
|
],
|
|
374
396
|
},
|
|
397
|
+
{
|
|
398
|
+
header: 'Users Commands - Domain: users',
|
|
399
|
+
content: [
|
|
400
|
+
{
|
|
401
|
+
name: 'export',
|
|
402
|
+
summary: 'Export all users in the org.'
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
name: 'import',
|
|
406
|
+
summary: 'Import all users in the users.yml file.'
|
|
407
|
+
}
|
|
408
|
+
],
|
|
409
|
+
},
|
|
375
410
|
{
|
|
376
411
|
header: 'Workflow Template Commands - Domain: workflow-templates',
|
|
377
412
|
content: [
|
|
@@ -414,11 +449,15 @@ const helpSections = [
|
|
|
414
449
|
},
|
|
415
450
|
{
|
|
416
451
|
name: 'uploadOptionSets',
|
|
417
|
-
summary: 'Upload OptionSets for your Org. OptionSets are loaded from
|
|
452
|
+
summary: 'Upload OptionSets for your Org. OptionSets are loaded from .yml files in the option-sets directory.\n'
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
name: 'parseOptionSetsLocalFiles <File Paths> <style>',
|
|
456
|
+
summary: 'Parse CSV files into OptionSets. Style denotes the format the csv is in. If the csv file has a column for name and label, use "NameAndLabel". If the file has one column for each option set with the rows being the label value use "LabelsInColumn"\n'
|
|
418
457
|
},
|
|
419
458
|
{
|
|
420
|
-
name: '
|
|
421
|
-
summary: 'Parse
|
|
459
|
+
name: 'parseOptionSetsToFolderStructure <File Path>',
|
|
460
|
+
summary: 'Parse single yml file into a folder with separate files per option set.\n'
|
|
422
461
|
},
|
|
423
462
|
{
|
|
424
463
|
name: 'parseOptionSetsHierarchyLocalFile <File Path>',
|
|
@@ -476,6 +515,10 @@ const helpSections = [
|
|
|
476
515
|
name: 'mergeTypeProperties <File Path> <TypePaths>',
|
|
477
516
|
summary: 'Merge the TypeProperties from an existing org and the TypeProperties passed in. Add to Types via TypePath File must be .yml\n'
|
|
478
517
|
},
|
|
518
|
+
{
|
|
519
|
+
name: 'mergeOptionSets <File Path>',
|
|
520
|
+
summary: 'Merge the OptionSets from an existing org and the OptionSets passed in. OptionSets File must be .yml.',
|
|
521
|
+
},
|
|
479
522
|
],
|
|
480
523
|
},
|
|
481
524
|
];
|
|
@@ -28,7 +28,7 @@ function loadOptionSets(fileLocation) {
|
|
|
28
28
|
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
29
29
|
console.log('Getting file from path: ', fullPath);
|
|
30
30
|
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
31
|
-
return doc
|
|
31
|
+
return doc;
|
|
32
32
|
}
|
|
33
33
|
catch (e) {
|
|
34
34
|
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
@@ -76,20 +76,23 @@ async function mergeOptionSets(fileLocation) {
|
|
|
76
76
|
mergedOptionSets.push(currentOptionSet);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
saveData(
|
|
79
|
+
saveData(mergedOptionSets);
|
|
80
80
|
}
|
|
81
81
|
function mergeOptionSet(existingOptionSet, uploadedOptionSet) {
|
|
82
|
+
var _a;
|
|
82
83
|
const merged = {
|
|
83
84
|
name: uploadedOptionSet.name,
|
|
84
85
|
optionSet: uploadedOptionSet.optionSet,
|
|
85
86
|
isArchived: uploadedOptionSet.isArchived,
|
|
86
87
|
};
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
if (((_a = existingOptionSet === null || existingOptionSet === void 0 ? void 0 : existingOptionSet.optionSet) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
89
|
+
for (const keyVal of existingOptionSet.optionSet) {
|
|
90
|
+
const value = keyVal.value;
|
|
91
|
+
const display = keyVal.display;
|
|
92
|
+
const found = merged.optionSet.find(keyVal => keyVal.value === value);
|
|
93
|
+
if (!found) {
|
|
94
|
+
merged.optionSet.push({ value, display });
|
|
95
|
+
}
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
return merged;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { getSeparatorByPlatform } from '../common';
|
|
3
3
|
import { parseOptionSets } from '@contrail/types';
|
|
4
|
+
import { StringUtil } from '@contrail/util';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
const csv = require('csvtojson');
|
|
6
7
|
const yaml = require('js-yaml');
|
|
8
|
+
import * as path from 'path';
|
|
7
9
|
export async function ParseOptionSetsLocalFiles(args) {
|
|
8
10
|
try {
|
|
9
11
|
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
@@ -11,8 +13,26 @@ export async function ParseOptionSetsLocalFiles(args) {
|
|
|
11
13
|
}
|
|
12
14
|
console.log('%s Importing local file', chalk.yellow.bold('OPTION SET PARSE'));
|
|
13
15
|
const fileLocation = args[3];
|
|
16
|
+
const csvStyle = args[4];
|
|
14
17
|
console.log('Using File: ', fileLocation);
|
|
15
|
-
await parseOptionSetsLocalFiles(fileLocation);
|
|
18
|
+
await parseOptionSetsLocalFiles(fileLocation, csvStyle);
|
|
19
|
+
console.log('%s Parsed', chalk.yellow.bold('OPTION SET PARSE'));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.log(`%s PARSE Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log('%s PARSE Complete.', chalk.green.bold('COMPLETE'));
|
|
26
|
+
}
|
|
27
|
+
export async function ParseOptionSetsToFolderStructure(args) {
|
|
28
|
+
try {
|
|
29
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
30
|
+
throw new Error('File name must be included.');
|
|
31
|
+
}
|
|
32
|
+
console.log('%s Importing local file', chalk.yellow.bold('OPTION SET PARSE'));
|
|
33
|
+
const fileLocation = args[3];
|
|
34
|
+
console.log('Using File: ', fileLocation);
|
|
35
|
+
await parseOptionSetsToFolderStructure(fileLocation);
|
|
16
36
|
console.log('%s Parsed', chalk.yellow.bold('OPTION SET PARSE'));
|
|
17
37
|
}
|
|
18
38
|
catch (e) {
|
|
@@ -33,14 +53,33 @@ async function loadOptionSetCSV(fileLocation) {
|
|
|
33
53
|
throw new Error(`ERROR PARSING CSV: ${e}`);
|
|
34
54
|
}
|
|
35
55
|
}
|
|
36
|
-
|
|
56
|
+
function loadOptionSets(fileLocation) {
|
|
57
|
+
const TARGET_DIR = process.cwd();
|
|
58
|
+
try {
|
|
59
|
+
const separator = getSeparatorByPlatform();
|
|
60
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
61
|
+
console.log('Getting file from path: ', fullPath);
|
|
62
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
63
|
+
return doc;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function parseOptionSetsLocalFiles(fileLocation, csvStyle) {
|
|
37
70
|
const uploadedOptionData = await loadOptionSetCSV(fileLocation);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
if (csvStyle === 'NameAndLabel') {
|
|
72
|
+
const parsedOptionSets = parseOptionSets(uploadedOptionData);
|
|
73
|
+
saveData(parsedOptionSets);
|
|
74
|
+
}
|
|
75
|
+
if (csvStyle === 'LabelsInColumn') {
|
|
76
|
+
const parsedOptionSets = parseLabelsInColumn(uploadedOptionData);
|
|
77
|
+
saveData(parsedOptionSets);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function parseOptionSetsToFolderStructure(fileLocation) {
|
|
81
|
+
const uploadedOptionData = await loadOptionSets(fileLocation);
|
|
82
|
+
saveDataInFolders(uploadedOptionData);
|
|
44
83
|
}
|
|
45
84
|
function saveData(data) {
|
|
46
85
|
const yamlStr = yaml.dump(data);
|
|
@@ -48,3 +87,54 @@ function saveData(data) {
|
|
|
48
87
|
const separator = getSeparatorByPlatform();
|
|
49
88
|
fs.writeFileSync(CURRENT_DIR + separator + 'parsed_local_optionSets.yml', yamlStr, 'utf8');
|
|
50
89
|
}
|
|
90
|
+
function saveDataInFolders(data) {
|
|
91
|
+
const folder = { filename: 'option-sets', split: true, fileLabel: 'name' };
|
|
92
|
+
const dir = 'merged_option_sets';
|
|
93
|
+
const CURRENT_DIR = process.cwd();
|
|
94
|
+
const subDir = path.join(CURRENT_DIR, dir, folder.filename);
|
|
95
|
+
if (!fs.existsSync(subDir)) {
|
|
96
|
+
fs.mkdirSync(subDir, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
for (const item of data) {
|
|
99
|
+
const yamlStr = yaml.dump(item);
|
|
100
|
+
const fileLabel = item[folder.fileLabel];
|
|
101
|
+
if (!fileLabel) {
|
|
102
|
+
console.warn('skipping bad data:', item);
|
|
103
|
+
}
|
|
104
|
+
fs.writeFileSync(path.join(subDir, `${removeSlash(fileLabel)}.yml`), yamlStr, 'utf8');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function removeSlash(string) {
|
|
108
|
+
const re = /\//gi;
|
|
109
|
+
return string.replace(re, '-');
|
|
110
|
+
}
|
|
111
|
+
export function parseLabelsInColumn(uploadedOptionData) {
|
|
112
|
+
const optionSets = [];
|
|
113
|
+
const optionSetNames = Object.keys(uploadedOptionData[0]);
|
|
114
|
+
for (const optionSetName of optionSetNames) {
|
|
115
|
+
const uniqueOptionSetValues = new Set();
|
|
116
|
+
for (const data of uploadedOptionData) {
|
|
117
|
+
const label = data[optionSetName];
|
|
118
|
+
uniqueOptionSetValues.add(label);
|
|
119
|
+
}
|
|
120
|
+
const optionSet = [];
|
|
121
|
+
if (uniqueOptionSetValues) {
|
|
122
|
+
for (const entry of uniqueOptionSetValues.values()) {
|
|
123
|
+
if (entry === '') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
optionSet.push({
|
|
127
|
+
value: StringUtil.convertToCamelCase(entry),
|
|
128
|
+
display: entry,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const reducedOptionSet = {
|
|
133
|
+
name: optionSetName,
|
|
134
|
+
isArchived: false,
|
|
135
|
+
optionSet,
|
|
136
|
+
};
|
|
137
|
+
optionSets.push(reducedOptionSet);
|
|
138
|
+
}
|
|
139
|
+
return optionSets;
|
|
140
|
+
}
|
package/lib/types/parse-types.js
CHANGED
|
@@ -110,7 +110,7 @@ async function parseTypesFromLocalFiles(fileLocations) {
|
|
|
110
110
|
}
|
|
111
111
|
console.log(`CSV imports were successful. ${csvJSONData === null || csvJSONData === void 0 ? void 0 : csvJSONData.length} total rows found.`);
|
|
112
112
|
const suggestions = GetSuggestedTypes(csvJSONData);
|
|
113
|
-
saveData(
|
|
113
|
+
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
114
114
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
115
115
|
}
|
|
116
116
|
async function parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation) {
|
|
@@ -129,7 +129,7 @@ async function parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFi
|
|
|
129
129
|
throw e;
|
|
130
130
|
}
|
|
131
131
|
const types = GetTypesFromTemplate(templateCSVData, dataCSVData);
|
|
132
|
-
saveData(
|
|
132
|
+
saveData(types.OptionSets, 'parsed_optionSets.yml');
|
|
133
133
|
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
134
134
|
}
|
|
135
135
|
async function parseTypesFromTemplateAndDataFromLocalFiles(templateFileLocation, dataFileLocations) {
|
|
@@ -157,7 +157,7 @@ async function parseTypesFromTemplateAndDataFromLocalFiles(templateFileLocation,
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
const types = GetTypesFromTemplateWithOptionSetsFromData(templateCSVData, dataCSVData);
|
|
160
|
-
saveData(
|
|
160
|
+
saveData(types.OptionSets, 'parsed_optionSets.yml');
|
|
161
161
|
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
162
162
|
}
|
|
163
163
|
async function parseTypesFromFiles(fileIds) {
|
|
@@ -178,7 +178,7 @@ async function parseTypesFromFiles(fileIds) {
|
|
|
178
178
|
}
|
|
179
179
|
console.log(`CSV downloads were successful. ${csvJSONData === null || csvJSONData === void 0 ? void 0 : csvJSONData.length} total rows found.`);
|
|
180
180
|
const suggestions = GetSuggestedTypes(csvJSONData);
|
|
181
|
-
saveData(
|
|
181
|
+
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
182
182
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
183
183
|
}
|
|
184
184
|
function saveData(data, name) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ExportUsers(): Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import { getSeparatorByPlatform } from '../common';
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
export async function ExportUsers() {
|
|
8
|
+
try {
|
|
9
|
+
await authUser();
|
|
10
|
+
console.log('%s Getting Users.', chalk.blue.bold('START'));
|
|
11
|
+
await exportUsers();
|
|
12
|
+
console.log('%s Done', chalk.yellow.bold('USERS'));
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.log(`%s Users download Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
console.log('%s Users download Complete.', chalk.green.bold('COMPLETE'));
|
|
19
|
+
}
|
|
20
|
+
async function exportUsers() {
|
|
21
|
+
const allUsersInOrg = await new Entities().get({
|
|
22
|
+
entityName: 'user-org',
|
|
23
|
+
});
|
|
24
|
+
const users = [];
|
|
25
|
+
for (const userInOrg of allUsersInOrg) {
|
|
26
|
+
delete userInOrg.user.id;
|
|
27
|
+
delete userInOrg.user.updatedBy;
|
|
28
|
+
delete userInOrg.user.createdBy;
|
|
29
|
+
if (userInOrg.user.email.includes('@vibeappuser.com')) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
users.push(Object.assign({ role: userInOrg.role }, userInOrg.user));
|
|
33
|
+
}
|
|
34
|
+
saveData({ users: users }, 'users');
|
|
35
|
+
}
|
|
36
|
+
function saveData(data, name) {
|
|
37
|
+
const yamlStr = yaml.dump(data);
|
|
38
|
+
const CURRENT_DIR = process.cwd();
|
|
39
|
+
const separator = getSeparatorByPlatform();
|
|
40
|
+
fs.writeFileSync(CURRENT_DIR + separator + name + '-export.yml', yamlStr, 'utf8');
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function UploadUsers(): Promise<void>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
export async function UploadUsers() {
|
|
8
|
+
try {
|
|
9
|
+
await authUser();
|
|
10
|
+
console.log('%s Uploading Users.', chalk.blue.bold('START'));
|
|
11
|
+
console.log('%s Uploading', chalk.yellow.bold('USER'));
|
|
12
|
+
await uploadUsers();
|
|
13
|
+
console.log('%s Uploaded', chalk.yellow.bold('USER'));
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log(`%s User Upload Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log('%s User Upload Complete.', chalk.green.bold('COMPLETE'));
|
|
20
|
+
}
|
|
21
|
+
function getUsersFile() {
|
|
22
|
+
const CURRENT_DIR = process.cwd();
|
|
23
|
+
try {
|
|
24
|
+
const fullPath = path.join(CURRENT_DIR, 'users.yml');
|
|
25
|
+
console.log('Getting file from path: ', fullPath);
|
|
26
|
+
const doc = yaml.load(fs.readFileSync(fullPath, 'utf8'));
|
|
27
|
+
return doc.users;
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function uploadUsers() {
|
|
34
|
+
const users = getUsersFile();
|
|
35
|
+
for (const user of users) {
|
|
36
|
+
const role = user.role;
|
|
37
|
+
const email = user.email;
|
|
38
|
+
delete user.role;
|
|
39
|
+
delete user.email;
|
|
40
|
+
await new Entities().create({
|
|
41
|
+
entityName: 'user-org',
|
|
42
|
+
object: Object.assign({ role: role, userEmail: email }, user)
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ function parseArgumentsIntoOptions(rawArgs) {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
async function promptForMissingOptions(options) {
|
|
24
|
-
const defaultTemplate = '
|
|
24
|
+
const defaultTemplate = 'TypeScript';
|
|
25
25
|
|
|
26
26
|
const questions = [];
|
|
27
27
|
if (!options.appName) {
|
|
@@ -38,7 +38,7 @@ async function promptForMissingOptions(options) {
|
|
|
38
38
|
type: 'list',
|
|
39
39
|
name: 'template',
|
|
40
40
|
message: 'Which project template would you like to use?',
|
|
41
|
-
choices: ['
|
|
41
|
+
choices: ['TypeScript', 'JavaScript'],
|
|
42
42
|
default: defaultTemplate,
|
|
43
43
|
});
|
|
44
44
|
}
|
package/src/cli.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { deployApp, removeApp } from './apps/deploy-app/deploy';
|
|
|
4
4
|
import { getAll } from './types/types-extractor';
|
|
5
5
|
import { uploadTypes } from './types/types-uploader';
|
|
6
6
|
import { UploadOptionSets } from './types/option-set-uploader';
|
|
7
|
-
import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
7
|
+
import { ParseOptionSetsLocalFiles, ParseOptionSetsToFolderStructure } from './types/option-set-parser';
|
|
8
8
|
import { ParseOptionSetsHierarchyLocalFile, UploadOptionSetsHierarchyLocalFile } from './types/option-set-hierarchy-parser';
|
|
9
9
|
import { ExportOptionSetsHierarchies } from './types/option-set-hierarchy-exporter';
|
|
10
10
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
@@ -24,6 +24,8 @@ import { uploadRuleSets } from './types/rule-set-uploader';
|
|
|
24
24
|
import { UploadOptionSetHierarchies } from './types/option-set-hierarchy-uploader';
|
|
25
25
|
import { uploadTypePropertyPolicies } from './types/type-property-policy-uploader';
|
|
26
26
|
import { uploadAll } from './types/allUploader';
|
|
27
|
+
import { ExportUsers } from './users/user-exporter';
|
|
28
|
+
import { UploadUsers } from './users/user-uploader';
|
|
27
29
|
|
|
28
30
|
const cliUsage = require('command-line-usage');
|
|
29
31
|
|
|
@@ -113,6 +115,10 @@ export async function cli(args) {
|
|
|
113
115
|
ParseOptionSetsLocalFiles(args);
|
|
114
116
|
break;
|
|
115
117
|
}
|
|
118
|
+
case 'parseOptionSetsToFolderStructure': {
|
|
119
|
+
ParseOptionSetsToFolderStructure(args);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
116
122
|
case 'parseOptionSetsHierarchyLocalFile': {
|
|
117
123
|
ParseOptionSetsHierarchyLocalFile(args);
|
|
118
124
|
break;
|
|
@@ -223,6 +229,23 @@ export async function cli(args) {
|
|
|
223
229
|
}
|
|
224
230
|
break;
|
|
225
231
|
}
|
|
232
|
+
case 'users': {
|
|
233
|
+
switch (command) {
|
|
234
|
+
case 'export': {
|
|
235
|
+
await ExportUsers();
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case 'import': {
|
|
239
|
+
await UploadUsers();
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
default: {
|
|
243
|
+
printIllegalCommand();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
|
|
226
249
|
case 'workflow-templates': {
|
|
227
250
|
switch (command) {
|
|
228
251
|
case 'load': {
|
|
@@ -387,6 +410,19 @@ const helpSections = [
|
|
|
387
410
|
}
|
|
388
411
|
],
|
|
389
412
|
},
|
|
413
|
+
{
|
|
414
|
+
header: 'Users Commands - Domain: users',
|
|
415
|
+
content: [
|
|
416
|
+
{
|
|
417
|
+
name: 'export',
|
|
418
|
+
summary: 'Export all users in the org.'
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
name: 'import',
|
|
422
|
+
summary: 'Import all users in the users.yml file.'
|
|
423
|
+
}
|
|
424
|
+
],
|
|
425
|
+
},
|
|
390
426
|
{
|
|
391
427
|
header: 'Workflow Template Commands - Domain: workflow-templates',
|
|
392
428
|
content: [
|
|
@@ -429,11 +465,15 @@ const helpSections = [
|
|
|
429
465
|
},
|
|
430
466
|
{
|
|
431
467
|
name: 'uploadOptionSets',
|
|
432
|
-
summary: 'Upload OptionSets for your Org. OptionSets are loaded from
|
|
468
|
+
summary: 'Upload OptionSets for your Org. OptionSets are loaded from .yml files in the option-sets directory.\n'
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: 'parseOptionSetsLocalFiles <File Paths> <style>',
|
|
472
|
+
summary: 'Parse CSV files into OptionSets. Style denotes the format the csv is in. If the csv file has a column for name and label, use "NameAndLabel". If the file has one column for each option set with the rows being the label value use "LabelsInColumn"\n'
|
|
433
473
|
},
|
|
434
474
|
{
|
|
435
|
-
name: '
|
|
436
|
-
summary: 'Parse
|
|
475
|
+
name: 'parseOptionSetsToFolderStructure <File Path>',
|
|
476
|
+
summary: 'Parse single yml file into a folder with separate files per option set.\n'
|
|
437
477
|
},
|
|
438
478
|
{
|
|
439
479
|
name: 'parseOptionSetsHierarchyLocalFile <File Path>',
|
|
@@ -491,6 +531,10 @@ const helpSections = [
|
|
|
491
531
|
name: 'mergeTypeProperties <File Path> <TypePaths>',
|
|
492
532
|
summary: 'Merge the TypeProperties from an existing org and the TypeProperties passed in. Add to Types via TypePath File must be .yml\n'
|
|
493
533
|
},
|
|
534
|
+
{
|
|
535
|
+
name: 'mergeOptionSets <File Path>',
|
|
536
|
+
summary: 'Merge the OptionSets from an existing org and the OptionSets passed in. OptionSets File must be .yml.',
|
|
537
|
+
},
|
|
494
538
|
],
|
|
495
539
|
},
|
|
496
540
|
];
|
|
@@ -35,7 +35,7 @@ function loadOptionSets(fileLocation) {
|
|
|
35
35
|
console.log('Getting file from path: ', fullPath);
|
|
36
36
|
|
|
37
37
|
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
38
|
-
return doc
|
|
38
|
+
return doc;
|
|
39
39
|
} catch (e) {
|
|
40
40
|
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
41
41
|
}
|
|
@@ -91,7 +91,7 @@ async function mergeOptionSets(fileLocation) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
saveData(
|
|
94
|
+
saveData(mergedOptionSets);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
function mergeOptionSet(existingOptionSet: ReducedOptionSet, uploadedOptionSet: ReducedOptionSet) {
|
|
@@ -101,15 +101,16 @@ function mergeOptionSet(existingOptionSet: ReducedOptionSet, uploadedOptionSet:
|
|
|
101
101
|
isArchived: uploadedOptionSet.isArchived,
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
104
|
+
if (existingOptionSet?.optionSet?.length > 0) {
|
|
105
|
+
for (const keyVal of existingOptionSet.optionSet) {
|
|
106
|
+
const value = keyVal.value;
|
|
107
|
+
const display = keyVal.display;
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
const found = merged.optionSet.find(keyVal => keyVal.value === value);
|
|
110
|
+
if (!found) {
|
|
111
|
+
merged.optionSet.push({value, display});
|
|
112
|
+
}
|
|
111
113
|
}
|
|
112
|
-
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
return merged;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { getSeparatorByPlatform } from '../common';
|
|
3
3
|
import { parseOptionSets } from '@contrail/types';
|
|
4
|
+
import { StringUtil } from '@contrail/util';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
const csv = require('csvtojson');
|
|
6
7
|
const yaml = require('js-yaml');
|
|
8
|
+
import * as path from 'path';
|
|
7
9
|
|
|
8
10
|
export async function ParseOptionSetsLocalFiles(args) {
|
|
9
11
|
try {
|
|
@@ -12,9 +14,31 @@ export async function ParseOptionSetsLocalFiles(args) {
|
|
|
12
14
|
}
|
|
13
15
|
console.log('%s Importing local file', chalk.yellow.bold('OPTION SET PARSE'));
|
|
14
16
|
const fileLocation = args[3];
|
|
17
|
+
const csvStyle = args[4];
|
|
15
18
|
console.log('Using File: ', fileLocation);
|
|
16
19
|
|
|
17
|
-
await parseOptionSetsLocalFiles(fileLocation);
|
|
20
|
+
await parseOptionSetsLocalFiles(fileLocation, csvStyle);
|
|
21
|
+
console.log('%s Parsed', chalk.yellow.bold('OPTION SET PARSE'));
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
console.log(`%s PARSE Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log('%s PARSE Complete.', chalk.green.bold('COMPLETE'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function ParseOptionSetsToFolderStructure(args) {
|
|
33
|
+
try {
|
|
34
|
+
if (args?.length < 4) {
|
|
35
|
+
throw new Error('File name must be included.');
|
|
36
|
+
}
|
|
37
|
+
console.log('%s Importing local file', chalk.yellow.bold('OPTION SET PARSE'));
|
|
38
|
+
const fileLocation = args[3];
|
|
39
|
+
console.log('Using File: ', fileLocation);
|
|
40
|
+
|
|
41
|
+
await parseOptionSetsToFolderStructure(fileLocation);
|
|
18
42
|
console.log('%s Parsed', chalk.yellow.bold('OPTION SET PARSE'));
|
|
19
43
|
|
|
20
44
|
}
|
|
@@ -40,16 +64,38 @@ async function loadOptionSetCSV(fileLocation) {
|
|
|
40
64
|
}
|
|
41
65
|
}
|
|
42
66
|
|
|
43
|
-
|
|
67
|
+
function loadOptionSets(fileLocation) {
|
|
68
|
+
const TARGET_DIR = process.cwd();
|
|
69
|
+
try {
|
|
70
|
+
const separator = getSeparatorByPlatform();
|
|
71
|
+
|
|
72
|
+
const fullPath = TARGET_DIR + separator + fileLocation;
|
|
73
|
+
console.log('Getting file from path: ', fullPath);
|
|
74
|
+
|
|
75
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + fileLocation, 'utf8'));
|
|
76
|
+
return doc;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function parseOptionSetsLocalFiles(fileLocation, csvStyle) {
|
|
44
83
|
const uploadedOptionData = await loadOptionSetCSV(fileLocation);
|
|
45
84
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
85
|
+
if (csvStyle === 'NameAndLabel') {
|
|
86
|
+
const parsedOptionSets = parseOptionSets(uploadedOptionData);
|
|
87
|
+
saveData(parsedOptionSets);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (csvStyle === 'LabelsInColumn') {
|
|
91
|
+
const parsedOptionSets = parseLabelsInColumn(uploadedOptionData);
|
|
92
|
+
saveData(parsedOptionSets);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
50
95
|
|
|
51
|
-
|
|
52
|
-
|
|
96
|
+
async function parseOptionSetsToFolderStructure(fileLocation) {
|
|
97
|
+
const uploadedOptionData = await loadOptionSets(fileLocation);
|
|
98
|
+
saveDataInFolders(uploadedOptionData);
|
|
53
99
|
}
|
|
54
100
|
|
|
55
101
|
function saveData(data) {
|
|
@@ -57,4 +103,64 @@ function saveData(data) {
|
|
|
57
103
|
const CURRENT_DIR = process.cwd();
|
|
58
104
|
const separator = getSeparatorByPlatform();
|
|
59
105
|
fs.writeFileSync(CURRENT_DIR + separator + 'parsed_local_optionSets.yml', yamlStr, 'utf8');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function saveDataInFolders(data) {
|
|
109
|
+
const folder = { filename: 'option-sets', split: true, fileLabel: 'name' };
|
|
110
|
+
const dir = 'merged_option_sets';
|
|
111
|
+
|
|
112
|
+
const CURRENT_DIR = process.cwd();
|
|
113
|
+
|
|
114
|
+
const subDir = path.join(CURRENT_DIR, dir, folder.filename);
|
|
115
|
+
if(!fs.existsSync(subDir)) {
|
|
116
|
+
fs.mkdirSync(subDir, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
for(const item of data) {
|
|
119
|
+
const yamlStr = yaml.dump(item);
|
|
120
|
+
const fileLabel = item[folder.fileLabel];
|
|
121
|
+
if(!fileLabel) {
|
|
122
|
+
console.warn('skipping bad data:', item);
|
|
123
|
+
}
|
|
124
|
+
fs.writeFileSync(path.join(subDir, `${removeSlash(fileLabel)}.yml`), yamlStr, 'utf8');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function removeSlash(string) {
|
|
129
|
+
const re = /\//gi;
|
|
130
|
+
return string.replace(re, '-');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function parseLabelsInColumn(uploadedOptionData) {
|
|
134
|
+
const optionSets = [];
|
|
135
|
+
const optionSetNames = Object.keys(uploadedOptionData[0]);
|
|
136
|
+
for (const optionSetName of optionSetNames) {
|
|
137
|
+
const uniqueOptionSetValues = new Set<string>();
|
|
138
|
+
for (const data of uploadedOptionData) {
|
|
139
|
+
const label = data[optionSetName];
|
|
140
|
+
uniqueOptionSetValues.add(label);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const optionSet: any[] = [];
|
|
144
|
+
if (uniqueOptionSetValues) {
|
|
145
|
+
for (const entry of uniqueOptionSetValues.values()) {
|
|
146
|
+
if (entry === '') {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
optionSet.push({
|
|
150
|
+
value: StringUtil.convertToCamelCase(entry),
|
|
151
|
+
display: entry,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const reducedOptionSet = {
|
|
157
|
+
name: optionSetName,
|
|
158
|
+
isArchived: false,
|
|
159
|
+
optionSet,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
optionSets.push(reducedOptionSet);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return optionSets;
|
|
60
166
|
}
|
package/src/types/parse-types.ts
CHANGED
|
@@ -134,7 +134,7 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
|
|
|
134
134
|
|
|
135
135
|
console.log(`CSV imports were successful. ${csvJSONData?.length} total rows found.`);
|
|
136
136
|
const suggestions = GetSuggestedTypes(csvJSONData);
|
|
137
|
-
saveData(
|
|
137
|
+
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
138
138
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -157,7 +157,7 @@ async function parseTypesFromTemplateFromLocalFiles(templateFileLocation: string
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
const types = GetTypesFromTemplate(templateCSVData, dataCSVData);
|
|
160
|
-
saveData(
|
|
160
|
+
saveData(types.OptionSets, 'parsed_optionSets.yml');
|
|
161
161
|
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -190,7 +190,7 @@ async function parseTypesFromTemplateAndDataFromLocalFiles(templateFileLocation:
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
const types = GetTypesFromTemplateWithOptionSetsFromData(templateCSVData, dataCSVData);
|
|
193
|
-
saveData(
|
|
193
|
+
saveData(types.OptionSets, 'parsed_optionSets.yml');
|
|
194
194
|
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -215,7 +215,7 @@ async function parseTypesFromFiles(fileIds: string[]) {
|
|
|
215
215
|
console.log(`CSV downloads were successful. ${csvJSONData?.length} total rows found.`);
|
|
216
216
|
const suggestions = GetSuggestedTypes(csvJSONData);
|
|
217
217
|
|
|
218
|
-
saveData(
|
|
218
|
+
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
219
219
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
220
220
|
}
|
|
221
221
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import { getSeparatorByPlatform } from '../common';
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
|
|
8
|
+
export async function ExportUsers() {
|
|
9
|
+
try {
|
|
10
|
+
await authUser();
|
|
11
|
+
console.log('%s Getting Users.', chalk.blue.bold('START'));
|
|
12
|
+
|
|
13
|
+
await exportUsers();
|
|
14
|
+
console.log('%s Done', chalk.yellow.bold('USERS'));
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
console.log(`%s Users download Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.log('%s Users download Complete.', chalk.green.bold('COMPLETE'));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function exportUsers() {
|
|
26
|
+
const allUsersInOrg = await new Entities().get({
|
|
27
|
+
entityName: 'user-org',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const users = [];
|
|
31
|
+
for (const userInOrg of allUsersInOrg) {
|
|
32
|
+
delete userInOrg.user.id;
|
|
33
|
+
delete userInOrg.user.updatedBy;
|
|
34
|
+
delete userInOrg.user.createdBy;
|
|
35
|
+
if (userInOrg.user.email.includes('@vibeappuser.com')) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
users.push({
|
|
39
|
+
role: userInOrg.role,
|
|
40
|
+
...userInOrg.user
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
saveData({users: users}, 'users');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function saveData(data, name) {
|
|
48
|
+
const yamlStr = yaml.dump(data);
|
|
49
|
+
const CURRENT_DIR = process.cwd();
|
|
50
|
+
const separator = getSeparatorByPlatform();
|
|
51
|
+
fs.writeFileSync(CURRENT_DIR + separator + name + '-export.yml', yamlStr, 'utf8');
|
|
52
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
|
|
9
|
+
export async function UploadUsers() {
|
|
10
|
+
try {
|
|
11
|
+
await authUser();
|
|
12
|
+
console.log('%s Uploading Users.', chalk.blue.bold('START'));
|
|
13
|
+
|
|
14
|
+
console.log('%s Uploading', chalk.yellow.bold('USER'));
|
|
15
|
+
await uploadUsers();
|
|
16
|
+
console.log('%s Uploaded', chalk.yellow.bold('USER'));
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.log(`%s User Upload Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log('%s User Upload Complete.', chalk.green.bold('COMPLETE'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getUsersFile(){
|
|
28
|
+
const CURRENT_DIR = process.cwd();
|
|
29
|
+
try {
|
|
30
|
+
const fullPath = path.join(CURRENT_DIR, 'users.yml');
|
|
31
|
+
console.log('Getting file from path: ', fullPath);
|
|
32
|
+
|
|
33
|
+
const doc = yaml.load(fs.readFileSync(fullPath, 'utf8'));
|
|
34
|
+
return doc.users;
|
|
35
|
+
} catch (e) {
|
|
36
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function uploadUsers() {
|
|
41
|
+
const users = getUsersFile();
|
|
42
|
+
|
|
43
|
+
for (const user of users) {
|
|
44
|
+
const role = user.role;
|
|
45
|
+
const email = user.email;
|
|
46
|
+
delete user.role;
|
|
47
|
+
delete user.email;
|
|
48
|
+
|
|
49
|
+
await new Entities().create({
|
|
50
|
+
entityName: 'user-org',
|
|
51
|
+
object: {
|
|
52
|
+
role: role,
|
|
53
|
+
userEmail: email,
|
|
54
|
+
...user
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { execute } from './handler';
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const bodyParser = require('body-parser');
|
|
4
|
+
const app = express();
|
|
5
|
+
const port = 5050;
|
|
6
|
+
|
|
7
|
+
// parse application/x-www-form-urlencoded
|
|
8
|
+
app.use(bodyParser.urlencoded({ extended: false }));
|
|
9
|
+
// parse application/json
|
|
10
|
+
app.use(bodyParser.json());
|
|
11
|
+
|
|
12
|
+
app.get('/health_check', (req, res) => {
|
|
13
|
+
res.send('Hello World!');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// DO NOT CHANGE THIS IMPLEMENTATION
|
|
17
|
+
app.post('/', async (req, res) => {
|
|
18
|
+
const result = await execute(req.body);
|
|
19
|
+
res.send(result);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
app.listen(port, () => {
|
|
23
|
+
console.log(`Mock server listening on port ${port}`);
|
|
24
|
+
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export class Logger {
|
|
2
2
|
allEntries = [];
|
|
3
3
|
public log(...args){
|
|
4
|
-
console.log(args);
|
|
4
|
+
console.log(...args);
|
|
5
5
|
this.allEntries.push(args);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
public getEntries(){
|
|
9
|
-
return this.allEntries;
|
|
9
|
+
return this.allEntries.join('\n');
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
public clearEntries(){
|
|
13
13
|
this.allEntries = [];
|
|
14
14
|
}
|
|
15
|
-
}
|
|
15
|
+
}
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsc",
|
|
18
|
+
"start": "nodemon --watch 'actions/**/*.ts' --exec ts-node actions/mock-server.ts",
|
|
19
|
+
"debug": "nodemon -r ts-node/register --inspect=127.0.0.1:60002 --watch 'actions/**/*.ts' --exec node actions/mock-server.ts",
|
|
18
20
|
"lint": "eslint . --fix",
|
|
19
21
|
"test": "jest",
|
|
20
22
|
"test-watch": "jest --watch",
|
|
@@ -39,8 +41,12 @@
|
|
|
39
41
|
"chalk": "^4.0.0"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
44
|
+
"body-parser": "^1.20.2",
|
|
45
|
+
"express": "^4.18.2",
|
|
46
|
+
"nodemon": "^1.19.4",
|
|
42
47
|
"jest": "^29.2.2",
|
|
43
48
|
"ts-jest": "^29.0.3",
|
|
49
|
+
"ts-node": "^7.0.1",
|
|
44
50
|
"typescript": "^4.7.4"
|
|
45
51
|
}
|
|
46
52
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
3
|
+
"target": "ES2020",
|
|
4
4
|
"module": "commonjs",
|
|
5
5
|
"declaration": true,
|
|
6
6
|
"esModuleInterop": true,
|
|
@@ -17,15 +17,11 @@
|
|
|
17
17
|
"ES2015",
|
|
18
18
|
"ES2016",
|
|
19
19
|
"ES2017",
|
|
20
|
+
"ES2020",
|
|
20
21
|
"dom",
|
|
21
22
|
"esnext.asynciterable"
|
|
22
|
-
]
|
|
23
|
+
]
|
|
23
24
|
},
|
|
24
|
-
"include": [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"exclude": [
|
|
28
|
-
"node_modules",
|
|
29
|
-
"**/__tests__/*"
|
|
30
|
-
]
|
|
31
|
-
}
|
|
25
|
+
"include": ["actions"],
|
|
26
|
+
"exclude": ["node_modules", "**/__tests__/*"]
|
|
27
|
+
}
|