@contrail/cli 2.1.20 → 2.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -105
- package/dist/api/apps.js +15 -15
- package/dist/api/event-workflow-action-definition.d.ts +1 -1
- package/dist/api/event-workflow-action-definition.js +1 -1
- package/dist/api/event-workflow-template-definition.d.ts +4 -3
- package/dist/api/event-workflow-templates.d.ts +5 -4
- package/dist/api/event-workflow-templates.js +2 -2
- package/dist/api/types.d.ts +10 -10
- package/dist/api/users.js +4 -2
- package/dist/auth/login.js +12 -14
- package/dist/commands/app/create.d.ts +2 -2
- package/dist/commands/app/create.js +15 -10
- package/dist/commands/app/delete.d.ts +2 -2
- package/dist/commands/app/delete.js +4 -2
- package/dist/commands/app/getApiKey.d.ts +2 -2
- package/dist/commands/app/getApiKey.js +17 -11
- package/dist/commands/app/install.d.ts +2 -2
- package/dist/commands/app/install.js +42 -25
- package/dist/commands/app/publish.d.ts +2 -2
- package/dist/commands/app/publish.js +26 -11
- package/dist/commands/app/uninstall.d.ts +2 -2
- package/dist/commands/app/uninstall.js +20 -11
- package/dist/commands/app/upgrade.d.ts +2 -2
- package/dist/commands/app/upgrade.js +46 -23
- package/dist/commands/basecommand.d.ts +7 -0
- package/dist/commands/basecommand.js +29 -0
- package/dist/commands/colors/deleteAll.d.ts +2 -2
- package/dist/commands/colors/deleteAll.js +8 -5
- package/dist/commands/colors/load.d.ts +2 -2
- package/dist/commands/colors/load.js +10 -7
- package/dist/commands/config/list.d.ts +2 -2
- package/dist/commands/config/list.js +4 -2
- package/dist/commands/config/remove.d.ts +2 -2
- package/dist/commands/config/remove.js +4 -2
- package/dist/commands/config/set.d.ts +3 -2
- package/dist/commands/config/set.js +21 -7
- package/dist/commands/groups/export.d.ts +2 -2
- package/dist/commands/groups/export.js +20 -8
- package/dist/commands/groups/upload.d.ts +3 -3
- package/dist/commands/groups/upload.js +44 -32
- package/dist/commands/instance/export.d.ts +2 -2
- package/dist/commands/instance/export.js +15 -3
- package/dist/commands/instance/import.d.ts +2 -2
- package/dist/commands/instance/import.js +9 -2
- package/dist/commands/loader-process/load.d.ts +2 -2
- package/dist/commands/loader-process/load.js +13 -6
- package/dist/commands/loader-process/upload-and-load.d.ts +2 -2
- package/dist/commands/loader-process/upload-and-load.js +18 -7
- package/dist/commands/projects/export.d.ts +2 -2
- package/dist/commands/projects/export.js +4 -2
- package/dist/commands/projects/list.d.ts +2 -2
- package/dist/commands/projects/list.js +6 -4
- package/dist/commands/projects/load.d.ts +2 -2
- package/dist/commands/projects/load.js +16 -8
- package/dist/commands/types/exportOptionSetHierarchies.d.ts +2 -2
- package/dist/commands/types/exportOptionSetHierarchies.js +15 -12
- package/dist/commands/types/getAll.d.ts +2 -2
- package/dist/commands/types/getAll.js +107 -76
- package/dist/commands/types/loadAll.d.ts +2 -2
- package/dist/commands/types/loadAll.js +12 -4
- package/dist/commands/types/mergeOptionSets.d.ts +2 -2
- package/dist/commands/types/mergeOptionSets.js +13 -10
- package/dist/commands/types/mergeTypeProperties.d.ts +2 -2
- package/dist/commands/types/mergeTypeProperties.js +12 -9
- package/dist/commands/types/parseOptionSetsHierarchyLocalFile.d.ts +2 -2
- package/dist/commands/types/parseOptionSetsHierarchyLocalFile.js +19 -15
- package/dist/commands/types/parseOptionSetsHierarchyValuesToKeysLocalFile.d.ts +10 -0
- package/dist/commands/types/parseOptionSetsHierarchyValuesToKeysLocalFile.js +102 -0
- package/dist/commands/types/parseOptionSetsLocalFiles.d.ts +2 -2
- package/dist/commands/types/parseOptionSetsLocalFiles.js +21 -21
- package/dist/commands/types/parseOptionSetsToFolderStructure.d.ts +2 -2
- package/dist/commands/types/parseOptionSetsToFolderStructure.js +17 -18
- package/dist/commands/types/parseTypesFromFiles.d.ts +2 -2
- package/dist/commands/types/parseTypesFromFiles.js +14 -8
- package/dist/commands/types/parseTypesFromLocalFiles.d.ts +2 -2
- package/dist/commands/types/parseTypesFromLocalFiles.js +10 -7
- package/dist/commands/types/parseTypesFromTemplateAndDataFromLocalFiles.d.ts +2 -2
- package/dist/commands/types/parseTypesFromTemplateAndDataFromLocalFiles.js +11 -8
- package/dist/commands/types/parseTypesFromTemplateFromLocalFiles.d.ts +2 -2
- package/dist/commands/types/parseTypesFromTemplateFromLocalFiles.js +11 -8
- package/dist/commands/types/uploadOptionSetHierarchies.d.ts +2 -2
- package/dist/commands/types/uploadOptionSetHierarchies.js +44 -32
- package/dist/commands/types/uploadOptionSets.d.ts +2 -2
- package/dist/commands/types/uploadOptionSets.js +21 -13
- package/dist/commands/types/uploadOptionSetsHierarchyLocalFile.d.ts +2 -2
- package/dist/commands/types/uploadOptionSetsHierarchyLocalFile.js +26 -19
- package/dist/commands/types/uploadRuleSets.d.ts +2 -2
- package/dist/commands/types/uploadRuleSets.js +34 -26
- package/dist/commands/types/uploadTypePolicies.d.ts +2 -2
- package/dist/commands/types/uploadTypePolicies.js +37 -29
- package/dist/commands/types/uploadTypePropertyPolicies.d.ts +2 -2
- package/dist/commands/types/uploadTypePropertyPolicies.js +38 -30
- package/dist/commands/types/uploadTypes.d.ts +2 -2
- package/dist/commands/types/uploadTypes.js +10 -4
- package/dist/commands/types/uploadUsageInfo.d.ts +2 -2
- package/dist/commands/types/uploadUsageInfo.js +32 -24
- package/dist/commands/users/export.d.ts +2 -2
- package/dist/commands/users/export.js +15 -4
- package/dist/commands/users/upload.d.ts +2 -2
- package/dist/commands/users/upload.js +6 -4
- package/dist/commands/webhooks/create.d.ts +2 -2
- package/dist/commands/webhooks/create.js +8 -6
- package/dist/commands/webhooks/delete.d.ts +2 -2
- package/dist/commands/webhooks/delete.js +8 -5
- package/dist/commands/webhooks/getWebhookTrigger.d.ts +2 -2
- package/dist/commands/webhooks/getWebhookTrigger.js +10 -9
- package/dist/commands/webhooks/list.d.ts +2 -2
- package/dist/commands/webhooks/list.js +8 -6
- package/dist/commands/workflow-template-definitions/install.d.ts +2 -2
- package/dist/commands/workflow-template-definitions/install.js +4 -2
- package/dist/commands/workflow-template-definitions/list.d.ts +2 -2
- package/dist/commands/workflow-template-definitions/list.js +4 -2
- package/dist/commands/workflow-templates/delete.d.ts +2 -2
- package/dist/commands/workflow-templates/delete.js +4 -2
- package/dist/commands/workflow-templates/export.d.ts +2 -2
- package/dist/commands/workflow-templates/export.js +19 -17
- package/dist/commands/workflow-templates/list.d.ts +2 -2
- package/dist/commands/workflow-templates/list.js +4 -2
- package/dist/commands/workflow-templates/load.d.ts +2 -2
- package/dist/commands/workflow-templates/load.js +8 -3
- package/dist/common.d.ts +4 -1
- package/dist/common.js +10 -1
- package/dist/helpers/app/actions-deployer.d.ts +2 -2
- package/dist/helpers/app/actions-deployer.js +12 -7
- package/dist/helpers/app/app-deployer.d.ts +1 -1
- package/dist/helpers/app/app-deployer.js +70 -52
- package/dist/helpers/app/app-template-parsers.js +3 -1
- package/dist/helpers/app/load-app-config.d.ts +2 -1
- package/dist/helpers/app/load-app-config.js +2 -2
- package/dist/helpers/app/setup-template.js +4 -3
- package/dist/helpers/colors/helpers.d.ts +10 -2
- package/dist/helpers/colors/helpers.js +11 -10
- package/dist/helpers/config/config.js +15 -10
- package/dist/helpers/file-helpers.js +7 -4
- package/dist/helpers/loader-process/helpers.js +14 -13
- package/dist/helpers/projects/helpers.d.ts +2 -1
- package/dist/helpers/projects/helpers.js +16 -15
- package/dist/helpers/types/csv-parser.js +17 -14
- package/dist/helpers/types/type-extractor.d.ts +1 -1
- package/dist/helpers/types/type-extractor.js +3 -2
- package/dist/helpers/types/type-parser.js +22 -21
- package/dist/helpers/types/type-uploader.js +19 -15
- package/dist/helpers/workflow-template-definitions/workflow-template-definition-deployer.d.ts +1 -1
- package/dist/helpers/workflow-template-definitions/workflow-template-definition-deployer.js +47 -28
- package/dist/helpers/workflow-templates/helper.d.ts +3 -3
- package/dist/helpers/workflow-templates/helper.js +33 -23
- package/dist/interface-converters.spec.js +15 -15
- package/dist/interfaces.d.ts +6 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +32 -0
- package/dist/templates/typescript/src/actions/logItem.ts +9 -4
- package/dist/templates/typescript/src/main.ts +13 -8
- package/oclif.manifest.json +861 -31
- package/package.json +10 -7
|
@@ -10,10 +10,13 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
|
10
10
|
const core_1 = require("@oclif/core");
|
|
11
11
|
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
12
12
|
const users_1 = require("../../api/users");
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const basecommand_1 = require("../basecommand");
|
|
14
|
+
const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
15
|
+
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
16
|
+
class UploadTypePolicies extends basecommand_1.BaseCommand {
|
|
15
17
|
async run() {
|
|
16
18
|
const { flags } = await this.parse(UploadTypePolicies);
|
|
19
|
+
await super.setLogLevel(flags.logLevel);
|
|
17
20
|
return await uploadTypePolicies(flags.dir);
|
|
18
21
|
}
|
|
19
22
|
}
|
|
@@ -24,22 +27,27 @@ UploadTypePolicies.examples = [
|
|
|
24
27
|
`,
|
|
25
28
|
];
|
|
26
29
|
UploadTypePolicies.flags = {
|
|
27
|
-
dir: core_1.Flags.string({
|
|
30
|
+
dir: core_1.Flags.string({
|
|
31
|
+
char: 'd',
|
|
32
|
+
description: 'The directory from which to export the type policy data. Defaults to the current directory. The type policy data will be loaded from $dir/type-policies/*.yml',
|
|
33
|
+
required: false,
|
|
34
|
+
default: '.',
|
|
35
|
+
}),
|
|
28
36
|
};
|
|
29
37
|
async function uploadTypePolicies(dir) {
|
|
30
38
|
try {
|
|
31
39
|
await (0, login_1.authUser)();
|
|
32
|
-
|
|
40
|
+
logger_1.default.info('%s Uploading', chalk_1.default.yellow.bold('TYPE POLICY'));
|
|
33
41
|
const [reducedTypePolicies, reducedTypePolicyLinks] = await loadTypePolicies(dir);
|
|
34
42
|
await uploadTypePolicyObjects(reducedTypePolicies);
|
|
35
43
|
await uploadTypePolicyLinks(reducedTypePolicyLinks);
|
|
36
|
-
|
|
44
|
+
logger_1.default.info('%s Uploaded', chalk_1.default.yellow.bold('TYPE POLICY'));
|
|
37
45
|
}
|
|
38
46
|
catch (e) {
|
|
39
|
-
|
|
47
|
+
logger_1.default.info(`%s Type Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
40
48
|
return;
|
|
41
49
|
}
|
|
42
|
-
|
|
50
|
+
logger_1.default.info('%s Type Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
43
51
|
}
|
|
44
52
|
exports.uploadTypePolicies = uploadTypePolicies;
|
|
45
53
|
function loadTypePolicies(fromDir) {
|
|
@@ -49,9 +57,9 @@ function loadTypePolicies(fromDir) {
|
|
|
49
57
|
try {
|
|
50
58
|
const files = fs_1.default.readdirSync(dir);
|
|
51
59
|
for (const file of files) {
|
|
52
|
-
tps.push(
|
|
60
|
+
tps.push(js_yaml_1.default.load(fs_1.default.readFileSync(path.join(dir, file), 'utf8')));
|
|
53
61
|
}
|
|
54
|
-
tpLinks =
|
|
62
|
+
tpLinks = js_yaml_1.default.load(fs_1.default.readFileSync(path.join(fromDir, 'type-policy-links.yml'), 'utf8'));
|
|
55
63
|
return [tps, tpLinks];
|
|
56
64
|
}
|
|
57
65
|
catch (e) {
|
|
@@ -64,27 +72,27 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
|
|
|
64
72
|
function fillPrincipal(statement) {
|
|
65
73
|
const principal = statement === null || statement === void 0 ? void 0 : statement.principal;
|
|
66
74
|
if (!principal) {
|
|
67
|
-
|
|
75
|
+
logger_1.default.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
68
76
|
return statement;
|
|
69
77
|
}
|
|
70
78
|
const [type, identifier] = principal.split(':');
|
|
71
79
|
if (!type || !identifier) {
|
|
72
|
-
|
|
80
|
+
logger_1.default.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
73
81
|
return statement;
|
|
74
82
|
}
|
|
75
83
|
if (type === 'group') {
|
|
76
|
-
const group = groups.find(x => x.name === identifier);
|
|
84
|
+
const group = groups.find((x) => x.name === identifier);
|
|
77
85
|
if (!group) {
|
|
78
|
-
|
|
86
|
+
logger_1.default.info(`Could not find group ${identifier}`);
|
|
79
87
|
}
|
|
80
88
|
else {
|
|
81
89
|
statement.principal = `group:${group.id}`;
|
|
82
90
|
}
|
|
83
91
|
}
|
|
84
92
|
else if (type === 'user') {
|
|
85
|
-
const orgUser = orgUsers.find(x => x.user.email === identifier);
|
|
93
|
+
const orgUser = orgUsers.find((x) => x.user.email === identifier);
|
|
86
94
|
if (!orgUser) {
|
|
87
|
-
|
|
95
|
+
logger_1.default.info(`Could not find user ${identifier}`);
|
|
88
96
|
}
|
|
89
97
|
else {
|
|
90
98
|
statement.principal = `user:${orgUser.user.id}`;
|
|
@@ -92,8 +100,8 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
|
|
|
92
100
|
}
|
|
93
101
|
return statement;
|
|
94
102
|
}
|
|
95
|
-
reducedTypePolicies.forEach(policy => {
|
|
96
|
-
policy.policy.statements = policy.policy.statements.map(x => fillPrincipal(x));
|
|
103
|
+
reducedTypePolicies.forEach((policy) => {
|
|
104
|
+
policy.policy.statements = policy.policy.statements.map((x) => fillPrincipal(x));
|
|
97
105
|
});
|
|
98
106
|
const currentTypePolicies = await new sdk_1.Entities().get({
|
|
99
107
|
entityName: 'type-policy',
|
|
@@ -110,14 +118,14 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
|
|
|
110
118
|
try {
|
|
111
119
|
const found = currentTypePolicyByLabel[label];
|
|
112
120
|
if (!found) {
|
|
113
|
-
|
|
121
|
+
logger_1.default.info('Creating: ', label);
|
|
114
122
|
await new sdk_1.Entities().create({
|
|
115
123
|
entityName: 'type-policy',
|
|
116
|
-
object: loadedTPP
|
|
124
|
+
object: loadedTPP,
|
|
117
125
|
});
|
|
118
126
|
}
|
|
119
127
|
else {
|
|
120
|
-
|
|
128
|
+
logger_1.default.info('Updating: ', label);
|
|
121
129
|
await new sdk_1.Entities().update({
|
|
122
130
|
entityName: 'type-policy',
|
|
123
131
|
id: found.id,
|
|
@@ -133,7 +141,7 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
|
|
|
133
141
|
try {
|
|
134
142
|
const found = loadedTypePolicyByName[label];
|
|
135
143
|
if (!found) {
|
|
136
|
-
|
|
144
|
+
logger_1.default.info('Deleting: ', label);
|
|
137
145
|
await new sdk_1.Entities().delete({
|
|
138
146
|
entityName: 'type-policy',
|
|
139
147
|
id: currentTPP['id'],
|
|
@@ -155,10 +163,10 @@ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
|
|
|
155
163
|
});
|
|
156
164
|
const currentLinksHashes = {};
|
|
157
165
|
for (const currentLink of currentTypePolicyLinks) {
|
|
158
|
-
const foundType = types.find(type => type.id === currentLink.typeId);
|
|
159
|
-
const foundTypePolicy = currentTypePolicies.find(tp => tp.id === currentLink.typePolicyId);
|
|
166
|
+
const foundType = types.find((type) => type.id === currentLink.typeId);
|
|
167
|
+
const foundTypePolicy = currentTypePolicies.find((tp) => tp.id === currentLink.typePolicyId);
|
|
160
168
|
if (!foundType || !foundTypePolicy) {
|
|
161
|
-
|
|
169
|
+
logger_1.default.info('skipping unhashable, invalid policy link:', currentLink);
|
|
162
170
|
}
|
|
163
171
|
const hash = `${foundType.slug}|${foundTypePolicy.label}`;
|
|
164
172
|
currentLinksHashes[hash] = currentLink;
|
|
@@ -197,7 +205,7 @@ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
|
|
|
197
205
|
try {
|
|
198
206
|
const found = reducedLinksByHashes[currentLinkHash];
|
|
199
207
|
if (!found) {
|
|
200
|
-
|
|
208
|
+
logger_1.default.info('Deleting: ', currentLinkHash);
|
|
201
209
|
await new sdk_1.Entities().delete({
|
|
202
210
|
entityName: 'type-policy-link',
|
|
203
211
|
id: currentLink['id'],
|
|
@@ -210,15 +218,15 @@ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
|
|
|
210
218
|
}
|
|
211
219
|
}
|
|
212
220
|
function transformReducedLink(typePolicyLink, types, typePolicies) {
|
|
213
|
-
const foundType = types.find(type => type.slug === typePolicyLink.typeSlug);
|
|
221
|
+
const foundType = types.find((type) => type.slug === typePolicyLink.typeSlug);
|
|
214
222
|
if (!foundType) {
|
|
215
|
-
|
|
223
|
+
logger_1.default.error('Could not find type with slug', typePolicyLink.typeSlug);
|
|
216
224
|
return false;
|
|
217
225
|
}
|
|
218
226
|
typePolicyLink.typeId = foundType.id;
|
|
219
|
-
const foundTypePolicy = typePolicies.find(tpp => tpp.label === typePolicyLink.typePolicyLabel);
|
|
227
|
+
const foundTypePolicy = typePolicies.find((tpp) => tpp.label === typePolicyLink.typePolicyLabel);
|
|
220
228
|
if (!foundTypePolicy) {
|
|
221
|
-
|
|
229
|
+
logger_1.default.error('Could not find type policy with label', typePolicyLink.typePolicyLabel);
|
|
222
230
|
return false;
|
|
223
231
|
}
|
|
224
232
|
typePolicyLink.typePolicyId = foundTypePolicy.id;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class UploadTypePropertyPolicies extends
|
|
1
|
+
import { BaseCommand } from '../basecommand';
|
|
2
|
+
export default class UploadTypePropertyPolicies extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -10,10 +10,13 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
|
10
10
|
const core_1 = require("@oclif/core");
|
|
11
11
|
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
12
12
|
const users_1 = require("../../api/users");
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const basecommand_1 = require("../basecommand");
|
|
14
|
+
const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
15
|
+
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
16
|
+
class UploadTypePropertyPolicies extends basecommand_1.BaseCommand {
|
|
15
17
|
async run() {
|
|
16
18
|
const { flags } = await this.parse(UploadTypePropertyPolicies);
|
|
19
|
+
await super.setLogLevel(flags.logLevel);
|
|
17
20
|
return await uploadTypePropertyPolicies(flags.dir);
|
|
18
21
|
}
|
|
19
22
|
}
|
|
@@ -24,24 +27,29 @@ UploadTypePropertyPolicies.examples = [
|
|
|
24
27
|
`,
|
|
25
28
|
];
|
|
26
29
|
UploadTypePropertyPolicies.flags = {
|
|
27
|
-
dir: core_1.Flags.string({
|
|
30
|
+
dir: core_1.Flags.string({
|
|
31
|
+
char: 'd',
|
|
32
|
+
description: 'The directory from which to export the type property policy data. Defaults to the current directory. The type property policy data will be loaded from $dir/type-property-policies/*.yml',
|
|
33
|
+
required: false,
|
|
34
|
+
default: '.',
|
|
35
|
+
}),
|
|
28
36
|
};
|
|
29
37
|
async function uploadTypePropertyPolicies(dir) {
|
|
30
38
|
try {
|
|
31
39
|
await (0, login_1.authUser)();
|
|
32
|
-
|
|
40
|
+
logger_1.default.info('%s Uploading', chalk_1.default.yellow.bold('TYPE PROPERTY POLICY'));
|
|
33
41
|
const [reducedTypePropertyPolicies, reducedTypePropertyPolicyLinks] = await loadTPPolicies(dir);
|
|
34
42
|
await uploadTPPolicyObjects(reducedTypePropertyPolicies);
|
|
35
43
|
await uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks);
|
|
36
|
-
|
|
44
|
+
logger_1.default.info('%s Uploaded', chalk_1.default.yellow.bold('TYPE PROPERTY POLICY'));
|
|
37
45
|
}
|
|
38
46
|
catch (e) {
|
|
39
|
-
|
|
47
|
+
logger_1.default.info(`%s Type Property Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
40
48
|
//TODO make this only print if a debug flag is set
|
|
41
49
|
console.trace(e);
|
|
42
50
|
return;
|
|
43
51
|
}
|
|
44
|
-
|
|
52
|
+
logger_1.default.info('%s Type Property Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
45
53
|
}
|
|
46
54
|
exports.uploadTypePropertyPolicies = uploadTypePropertyPolicies;
|
|
47
55
|
function loadTPPolicies(fromDir) {
|
|
@@ -51,9 +59,9 @@ function loadTPPolicies(fromDir) {
|
|
|
51
59
|
try {
|
|
52
60
|
const files = fs_1.default.readdirSync(dir);
|
|
53
61
|
for (const file of files) {
|
|
54
|
-
tpps.push(
|
|
62
|
+
tpps.push(js_yaml_1.default.load(fs_1.default.readFileSync(path.join(dir, file), 'utf8')));
|
|
55
63
|
}
|
|
56
|
-
tppLinks =
|
|
64
|
+
tppLinks = js_yaml_1.default.load(fs_1.default.readFileSync(path.join(fromDir, 'type-property-policy-links.yml'), 'utf8'));
|
|
57
65
|
return [tpps, tppLinks];
|
|
58
66
|
}
|
|
59
67
|
catch (e) {
|
|
@@ -66,27 +74,27 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
66
74
|
function fillPrincipal(statement) {
|
|
67
75
|
const principal = statement === null || statement === void 0 ? void 0 : statement.principal;
|
|
68
76
|
if (!principal) {
|
|
69
|
-
|
|
77
|
+
logger_1.default.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
70
78
|
return statement;
|
|
71
79
|
}
|
|
72
80
|
const [type, identifier] = principal.split(':');
|
|
73
81
|
if (!type || !identifier) {
|
|
74
|
-
|
|
82
|
+
logger_1.default.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
75
83
|
return statement;
|
|
76
84
|
}
|
|
77
85
|
if (type === 'group') {
|
|
78
|
-
const group = groups.find(x => x.name === identifier);
|
|
86
|
+
const group = groups.find((x) => x.name === identifier);
|
|
79
87
|
if (!group) {
|
|
80
|
-
|
|
88
|
+
logger_1.default.info(`Could not find group ${identifier}`);
|
|
81
89
|
}
|
|
82
90
|
else {
|
|
83
91
|
statement.principal = `group:${group.id}`;
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
else if (type === 'user') {
|
|
87
|
-
const orgUser = orgUsers.find(x => x.user.email === identifier);
|
|
95
|
+
const orgUser = orgUsers.find((x) => x.user.email === identifier);
|
|
88
96
|
if (!orgUser) {
|
|
89
|
-
|
|
97
|
+
logger_1.default.info(`Could not find user ${identifier}`);
|
|
90
98
|
}
|
|
91
99
|
else {
|
|
92
100
|
statement.principal = `user:${orgUser.user.id}`;
|
|
@@ -94,8 +102,8 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
94
102
|
}
|
|
95
103
|
return statement;
|
|
96
104
|
}
|
|
97
|
-
reducedTypePropertyPolicies.forEach(policy => {
|
|
98
|
-
policy.policy.statements = policy.policy.statements.map(x => fillPrincipal(x));
|
|
105
|
+
reducedTypePropertyPolicies.forEach((policy) => {
|
|
106
|
+
policy.policy.statements = policy.policy.statements.map((x) => fillPrincipal(x));
|
|
99
107
|
});
|
|
100
108
|
const currentTPPolicies = await new sdk_1.Entities().get({
|
|
101
109
|
entityName: 'type-property-policy',
|
|
@@ -112,14 +120,14 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
112
120
|
try {
|
|
113
121
|
const found = currentTPPByLabel[label];
|
|
114
122
|
if (!found) {
|
|
115
|
-
|
|
123
|
+
logger_1.default.info('Creating: ', label);
|
|
116
124
|
await new sdk_1.Entities().create({
|
|
117
125
|
entityName: 'type-property-policy',
|
|
118
|
-
object: loadedTPP
|
|
126
|
+
object: loadedTPP,
|
|
119
127
|
});
|
|
120
128
|
}
|
|
121
129
|
else {
|
|
122
|
-
|
|
130
|
+
logger_1.default.info('Updating: ', label);
|
|
123
131
|
await new sdk_1.Entities().update({
|
|
124
132
|
entityName: 'type-property-policy',
|
|
125
133
|
id: found.id,
|
|
@@ -135,7 +143,7 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
135
143
|
try {
|
|
136
144
|
const found = loadedTPPByName[label];
|
|
137
145
|
if (!found) {
|
|
138
|
-
|
|
146
|
+
logger_1.default.info('Deleting: ', label);
|
|
139
147
|
await new sdk_1.Entities().delete({
|
|
140
148
|
entityName: 'type-property-policy',
|
|
141
149
|
id: currentTPP['id'],
|
|
@@ -150,7 +158,7 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
150
158
|
async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
151
159
|
const typesWithProperties = await (0, type_extractor_1.getTypes)();
|
|
152
160
|
const typeProperties = [];
|
|
153
|
-
typesWithProperties.forEach(type => {
|
|
161
|
+
typesWithProperties.forEach((type) => {
|
|
154
162
|
if (type.typeProperties) {
|
|
155
163
|
for (const tp of type.typeProperties) {
|
|
156
164
|
tp.typeId = type.id;
|
|
@@ -167,10 +175,10 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
167
175
|
});
|
|
168
176
|
const currentLinksHashes = {};
|
|
169
177
|
for (const currentLink of currentTPPLinks) {
|
|
170
|
-
const foundTypeProperty = typeProperties.find(tp => tp.id === currentLink.typePropertyId);
|
|
171
|
-
const foundTPP = currentTPPs.find(tpp => tpp.id === currentLink.typePropertyPolicyId);
|
|
178
|
+
const foundTypeProperty = typeProperties.find((tp) => tp.id === currentLink.typePropertyId);
|
|
179
|
+
const foundTPP = currentTPPs.find((tpp) => tpp.id === currentLink.typePropertyPolicyId);
|
|
172
180
|
if (!foundTypeProperty || !foundTPP) {
|
|
173
|
-
|
|
181
|
+
logger_1.default.info('skipping unhashable, invalid policy link:', currentLink);
|
|
174
182
|
}
|
|
175
183
|
const hash = `${foundTypeProperty.typeSlug}${foundTypeProperty.slug}|${foundTPP.label}`;
|
|
176
184
|
currentLinksHashes[hash] = currentLink;
|
|
@@ -209,7 +217,7 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
209
217
|
try {
|
|
210
218
|
const found = reducedLinksByHashes[currentLinkHash];
|
|
211
219
|
if (!found) {
|
|
212
|
-
|
|
220
|
+
logger_1.default.info('Deleting: ', currentLinkHash);
|
|
213
221
|
await new sdk_1.Entities().delete({
|
|
214
222
|
entityName: 'type-property-policy-link',
|
|
215
223
|
id: currentLink['id'],
|
|
@@ -222,15 +230,15 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
222
230
|
}
|
|
223
231
|
}
|
|
224
232
|
function transformReducedLink(TPPLink, typeProperties, typePropertyPolicies) {
|
|
225
|
-
const foundTP = typeProperties.find(tp => tp.slug === TPPLink.typePropertySlug && tp.typeSlug === TPPLink.typeSlug);
|
|
233
|
+
const foundTP = typeProperties.find((tp) => tp.slug === TPPLink.typePropertySlug && tp.typeSlug === TPPLink.typeSlug);
|
|
226
234
|
if (!foundTP) {
|
|
227
|
-
|
|
235
|
+
logger_1.default.error('Could not find type property with label', TPPLink.typePropertySlug);
|
|
228
236
|
return false;
|
|
229
237
|
}
|
|
230
238
|
TPPLink.typePropertyId = foundTP.id;
|
|
231
|
-
const foundTPP = typePropertyPolicies.find(tpp => tpp.label === TPPLink.typePropertyPolicyLabel);
|
|
239
|
+
const foundTPP = typePropertyPolicies.find((tpp) => tpp.label === TPPLink.typePropertyPolicyLabel);
|
|
232
240
|
if (!foundTPP) {
|
|
233
|
-
|
|
241
|
+
logger_1.default.error('Could not find type property policy with label', TPPLink.typePropertyPolicyLabel);
|
|
234
242
|
return false;
|
|
235
243
|
}
|
|
236
244
|
TPPLink.typePropertyPolicyId = foundTPP.id;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class UploadTypes extends
|
|
1
|
+
import { BaseCommand } from '../basecommand';
|
|
2
|
+
export default class UploadTypes extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.uploadTypes = void 0;
|
|
4
4
|
const type_uploader_1 = require("../../helpers/types/type-uploader");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
|
-
const
|
|
7
|
-
class UploadTypes extends
|
|
6
|
+
const basecommand_1 = require("../basecommand");
|
|
7
|
+
class UploadTypes extends basecommand_1.BaseCommand {
|
|
8
8
|
async run() {
|
|
9
9
|
const { flags } = await this.parse(UploadTypes);
|
|
10
|
+
await super.setLogLevel(flags.logLevel);
|
|
10
11
|
return await uploadTypes(flags.dir);
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -17,9 +18,14 @@ UploadTypes.examples = [
|
|
|
17
18
|
`,
|
|
18
19
|
];
|
|
19
20
|
UploadTypes.flags = {
|
|
20
|
-
dir: core_1.Flags.string({
|
|
21
|
+
dir: core_1.Flags.string({
|
|
22
|
+
char: 'd',
|
|
23
|
+
description: 'The directory from which to export the option set data. Defaults to the current directory. The option set data will be loaded from $dir/types',
|
|
24
|
+
required: false,
|
|
25
|
+
default: '.',
|
|
26
|
+
}),
|
|
21
27
|
};
|
|
22
28
|
async function uploadTypes(dir) {
|
|
23
|
-
(0, type_uploader_1.uploadTypes)(dir);
|
|
29
|
+
await (0, type_uploader_1.uploadTypes)(dir);
|
|
24
30
|
}
|
|
25
31
|
exports.uploadTypes = uploadTypes;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class UploadUsageInfo extends
|
|
1
|
+
import { BaseCommand } from '../basecommand';
|
|
2
|
+
export default class UploadUsageInfo extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -9,10 +9,13 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
|
9
9
|
const path = tslib_1.__importStar(require("path"));
|
|
10
10
|
const core_1 = require("@oclif/core");
|
|
11
11
|
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const basecommand_1 = require("../basecommand");
|
|
13
|
+
const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
14
|
+
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
15
|
+
class UploadUsageInfo extends basecommand_1.BaseCommand {
|
|
14
16
|
async run() {
|
|
15
17
|
const { flags } = await this.parse(UploadUsageInfo);
|
|
18
|
+
await super.setLogLevel(flags.logLevel);
|
|
16
19
|
await uploadUsageInfo(flags.dir);
|
|
17
20
|
}
|
|
18
21
|
}
|
|
@@ -23,26 +26,31 @@ UploadUsageInfo.examples = [
|
|
|
23
26
|
`,
|
|
24
27
|
];
|
|
25
28
|
UploadUsageInfo.flags = {
|
|
26
|
-
dir: core_1.Flags.string({
|
|
29
|
+
dir: core_1.Flags.string({
|
|
30
|
+
char: 'd',
|
|
31
|
+
description: 'The directory from which to export the usage info data. Defaults to the current directory. The option set data will be loaded from $dir/usage-info.yml',
|
|
32
|
+
required: false,
|
|
33
|
+
default: '.',
|
|
34
|
+
}),
|
|
27
35
|
};
|
|
28
36
|
async function uploadUsageInfo(dir) {
|
|
29
37
|
try {
|
|
30
38
|
await (0, login_1.authUser)();
|
|
31
|
-
|
|
39
|
+
logger_1.default.info('%s Uploading', chalk_1.default.yellow.bold('USAGE INFO'));
|
|
32
40
|
const reducedUsageInfo = await loadUsageInfo(dir);
|
|
33
41
|
await uploadUsageInfoObjects(reducedUsageInfo);
|
|
34
|
-
|
|
42
|
+
logger_1.default.info('%s Uploaded', chalk_1.default.yellow.bold('USAGE INFO'));
|
|
35
43
|
}
|
|
36
44
|
catch (e) {
|
|
37
|
-
|
|
45
|
+
logger_1.default.info(`%s Usage Info Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
38
46
|
return;
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
logger_1.default.info('%s Usage Info Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
41
49
|
}
|
|
42
50
|
exports.uploadUsageInfo = uploadUsageInfo;
|
|
43
51
|
function loadUsageInfo(dir) {
|
|
44
52
|
try {
|
|
45
|
-
const doc =
|
|
53
|
+
const doc = js_yaml_1.default.load(fs_1.default.readFileSync(path.join(dir, 'usage-info.yml'), 'utf8'));
|
|
46
54
|
return doc;
|
|
47
55
|
}
|
|
48
56
|
catch (e) {
|
|
@@ -52,18 +60,18 @@ function loadUsageInfo(dir) {
|
|
|
52
60
|
async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
53
61
|
const typesWithProperties = await (0, type_extractor_1.getTypes)();
|
|
54
62
|
const typeProperties = typesWithProperties
|
|
55
|
-
.filter(t => !!t.typeProperties)
|
|
56
|
-
.map(t => t.typeProperties)
|
|
63
|
+
.filter((t) => !!t.typeProperties)
|
|
64
|
+
.map((t) => t.typeProperties)
|
|
57
65
|
.reduce((a, b) => a.concat(b));
|
|
58
66
|
const currentUsageInfo = await new sdk_1.Entities().get({
|
|
59
67
|
entityName: 'type-property-usage-info',
|
|
60
68
|
});
|
|
61
69
|
const currentUsageInfosHashes = {};
|
|
62
70
|
for (const currentUI of currentUsageInfo) {
|
|
63
|
-
const foundType = typesWithProperties.find(t => t.id === currentUI.typeId);
|
|
64
|
-
const foundTypeProperty = typeProperties.find(tp => tp.id === currentUI.typePropertyId);
|
|
71
|
+
const foundType = typesWithProperties.find((t) => t.id === currentUI.typeId);
|
|
72
|
+
const foundTypeProperty = typeProperties.find((tp) => tp.id === currentUI.typePropertyId);
|
|
65
73
|
if (!foundType || !foundTypeProperty) {
|
|
66
|
-
|
|
74
|
+
logger_1.default.info('skipping unhashable, invalid usage info:', currentUI);
|
|
67
75
|
continue;
|
|
68
76
|
}
|
|
69
77
|
const hash = `${foundType.slug}|${foundTypeProperty.slug}`;
|
|
@@ -74,8 +82,8 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
|
74
82
|
const hash = `${loadedUI.typeSlug}|${loadedUI.typePropertySlug}`;
|
|
75
83
|
reducedUsageInfoHashes[hash] = loadedUI;
|
|
76
84
|
}
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
logger_1.default.debug('current usage info:', currentUsageInfo);
|
|
86
|
+
logger_1.default.debug('loaded usage info:', loadedUsageInfo);
|
|
79
87
|
for (const loadedUI of loadedUsageInfo) {
|
|
80
88
|
try {
|
|
81
89
|
const found = currentUsageInfosHashes[`${loadedUI.typeSlug}|${loadedUI.typePropertySlug}`];
|
|
@@ -83,7 +91,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
|
83
91
|
if (!transformReducedUI(loadedUI, typesWithProperties, typeProperties)) {
|
|
84
92
|
continue;
|
|
85
93
|
}
|
|
86
|
-
|
|
94
|
+
logger_1.default.debug('Creating: ', loadedUI);
|
|
87
95
|
await new sdk_1.Entities().create({
|
|
88
96
|
entityName: 'type-property-usage-info',
|
|
89
97
|
object: {
|
|
@@ -96,21 +104,21 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
|
96
104
|
numberFormat: loadedUI.numberFormat,
|
|
97
105
|
defaultValue: loadedUI.defaultValue,
|
|
98
106
|
label: loadedUI.label,
|
|
99
|
-
}
|
|
107
|
+
},
|
|
100
108
|
});
|
|
101
109
|
}
|
|
102
110
|
else {
|
|
103
111
|
if (!transformReducedUI(loadedUI, typesWithProperties, typeProperties)) {
|
|
104
112
|
continue;
|
|
105
113
|
}
|
|
106
|
-
|
|
114
|
+
logger_1.default.info('Updating: ', loadedUI);
|
|
107
115
|
await new sdk_1.Entities().update({
|
|
108
116
|
entityName: 'type-property-usage-info',
|
|
109
117
|
id: found.id,
|
|
110
118
|
object: {
|
|
111
119
|
editable: loadedUI.editable,
|
|
112
120
|
used: loadedUI.used,
|
|
113
|
-
}
|
|
121
|
+
},
|
|
114
122
|
});
|
|
115
123
|
}
|
|
116
124
|
}
|
|
@@ -122,7 +130,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
|
122
130
|
try {
|
|
123
131
|
const found = reducedUsageInfoHashes[hash];
|
|
124
132
|
if (!found) {
|
|
125
|
-
|
|
133
|
+
logger_1.default.debug('Deleting: ', hash);
|
|
126
134
|
await new sdk_1.Entities().delete({
|
|
127
135
|
entityName: 'type-property-usage-info',
|
|
128
136
|
id: currentUI['id'],
|
|
@@ -136,15 +144,15 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
|
|
|
136
144
|
}
|
|
137
145
|
// transforms the reduced Usage Info from name slugs to ids
|
|
138
146
|
function transformReducedUI(reducedUsageInfo, types, typeProperties) {
|
|
139
|
-
const foundType = types.find(t => t.slug === reducedUsageInfo.typeSlug);
|
|
147
|
+
const foundType = types.find((t) => t.slug === reducedUsageInfo.typeSlug);
|
|
140
148
|
if (!foundType) {
|
|
141
|
-
|
|
149
|
+
logger_1.default.error('Could not find type with slug', reducedUsageInfo.typeSlug, 'while transforming', reducedUsageInfo);
|
|
142
150
|
return false;
|
|
143
151
|
}
|
|
144
152
|
reducedUsageInfo.typeId = foundType.id;
|
|
145
|
-
const foundTypeProperty = typeProperties.find(tp => tp.slug === reducedUsageInfo.typePropertySlug);
|
|
153
|
+
const foundTypeProperty = typeProperties.find((tp) => tp.slug === reducedUsageInfo.typePropertySlug);
|
|
146
154
|
if (!foundTypeProperty) {
|
|
147
|
-
|
|
155
|
+
logger_1.default.error('Could not find type property with slug', reducedUsageInfo.typePropertySlug, 'while transforming', reducedUsageInfo);
|
|
148
156
|
return false;
|
|
149
157
|
}
|
|
150
158
|
reducedUsageInfo.typePropertyId = foundTypeProperty.id;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseCommand } from '../basecommand';
|
|
2
2
|
export declare const DEFAULT_FILE_LOCATION = "users.yml";
|
|
3
|
-
export default class ExportUsers extends
|
|
3
|
+
export default class ExportUsers extends BaseCommand {
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
@@ -10,11 +10,13 @@ const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
|
10
10
|
const core_1 = require("@oclif/core");
|
|
11
11
|
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
12
12
|
const users_1 = require("../../api/users");
|
|
13
|
+
const basecommand_1 = require("../basecommand");
|
|
13
14
|
exports.DEFAULT_FILE_LOCATION = 'users.yml';
|
|
14
|
-
class ExportUsers extends
|
|
15
|
+
class ExportUsers extends basecommand_1.BaseCommand {
|
|
15
16
|
async run() {
|
|
16
17
|
var _a;
|
|
17
18
|
const { flags } = await this.parse(ExportUsers);
|
|
19
|
+
await super.setLogLevel(flags.logLevel);
|
|
18
20
|
try {
|
|
19
21
|
await (0, login_1.authUser)();
|
|
20
22
|
this.log('%s Getting Users.', chalk_1.default.blue.bold('START'));
|
|
@@ -35,8 +37,17 @@ ExportUsers.examples = [
|
|
|
35
37
|
`,
|
|
36
38
|
];
|
|
37
39
|
ExportUsers.flags = {
|
|
38
|
-
outFile: core_1.Flags.string({
|
|
39
|
-
|
|
40
|
+
outFile: core_1.Flags.string({
|
|
41
|
+
char: 'f',
|
|
42
|
+
description: 'The location for the file to be saved',
|
|
43
|
+
required: false,
|
|
44
|
+
default: exports.DEFAULT_FILE_LOCATION,
|
|
45
|
+
}),
|
|
46
|
+
overwrite: core_1.Flags.boolean({
|
|
47
|
+
description: 'Replaces existing files if they exist',
|
|
48
|
+
required: false,
|
|
49
|
+
default: false,
|
|
50
|
+
}),
|
|
40
51
|
};
|
|
41
52
|
async function exportUsers(fileLocation, overwrite) {
|
|
42
53
|
const allUsersInOrg = await (0, users_1.getUserOrgs)();
|
|
@@ -50,7 +61,7 @@ async function exportUsers(fileLocation, overwrite) {
|
|
|
50
61
|
}
|
|
51
62
|
users.push({
|
|
52
63
|
role: userInOrg.role,
|
|
53
|
-
...userInOrg.user
|
|
64
|
+
...userInOrg.user,
|
|
54
65
|
});
|
|
55
66
|
}
|
|
56
67
|
users = users.sort((one, two) => (one.email < two.email ? -1 : 1));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class ImportUsers extends
|
|
1
|
+
import { BaseCommand } from '../basecommand';
|
|
2
|
+
export default class ImportUsers extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|