@codiac.io/codiac-cli 1.2.217 → 1.2.221

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.
@@ -12,159 +12,120 @@ const command_base_enterprise_1 = require("../../command-base-enterprise");
12
12
  const CodiacConstants = require("../../codiac-constants");
13
13
  const path = require("path");
14
14
  const render = require("../../uilogic/render-methods");
15
+ const config_ui_utils_1 = require("../../uilogic/config-ui-utils");
15
16
  // const { selectFiles, COMPLETED, CANCELLED } = require('select-files-cli'); // gd js wo ts...
16
17
  // const { selectFiles, COMPLETED, CANCELLED } = require('../../uilogic/file-selector'); // gd js wo ts...
17
18
  /** The value provided as input that indicates
18
19
  * a user's desire to be prompted with a list from which choose the value(s),
19
20
  * instead of entering them manually or taking a default. */
20
21
  exports.PROMPT_ME_DESIGNATOR = "?";
22
+ /** Reads the given stream directly without assigning listeners to its events. */
23
+ function read(stream) {
24
+ var _a, stream_1, stream_1_1;
25
+ var _b, e_1, _c, _d;
26
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
27
+ try {
28
+ const chunks = [];
29
+ try {
30
+ for (_a = true, stream_1 = tslib_1.__asyncValues(stream); stream_1_1 = yield stream_1.next(), _b = stream_1_1.done, !_b;) {
31
+ _d = stream_1_1.value;
32
+ _a = false;
33
+ try {
34
+ const chunk = _d;
35
+ chunks.push(chunk);
36
+ }
37
+ finally {
38
+ _a = true;
39
+ }
40
+ }
41
+ }
42
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
43
+ finally {
44
+ try {
45
+ if (!_a && !_b && (_c = stream_1.return)) yield _c.call(stream_1);
46
+ }
47
+ finally { if (e_1) throw e_1.error; }
48
+ }
49
+ const out = Buffer.concat(chunks).toString('utf8');
50
+ return out;
51
+ }
52
+ catch (err) {
53
+ throw err;
54
+ }
55
+ });
56
+ }
57
+ var InteractionModes;
58
+ (function (InteractionModes) {
59
+ InteractionModes["echo"] = "echo";
60
+ InteractionModes["toscript"] = "toscript";
61
+ InteractionModes["silent"] = "silent";
62
+ })(InteractionModes || (InteractionModes = {}));
21
63
  class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
64
+ constructor() {
65
+ super(...arguments);
66
+ /** CLI Command-line string to rerun this execution as a non-TTY script. */
67
+ this.cmd = ["cod", "config", "add", "--silent"];
68
+ }
69
+ // --------------------------------------------------------------------
70
+ // Lazy-loaded properties
71
+ get configUtils() {
72
+ if (this._configUtils_backer === undefined) {
73
+ this._configUtils_backer = this.ioc.get(config_ui_utils_1.ConfigUiUtils);
74
+ }
75
+ return this._configUtils_backer;
76
+ }
77
+ // --------------------------------------------------------------------
78
+ bootstrap() {
79
+ super.bootstrap();
80
+ this.ioc.bind(config_ui_utils_1.ConfigUiUtils).toSelf();
81
+ }
22
82
  run() {
23
83
  var _a;
24
84
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
25
85
  try {
26
86
  this.bootstrap();
27
- const { args, flags } = yield this.parse(ConfigAdd);
87
+ yield this.readStdin();
28
88
  (_a = this._relayContainer) === null || _a === void 0 ? void 0 : _a.ready$.subscribe((ready) => tslib_1.__awaiter(this, void 0, void 0, function* () {
29
- var _b, _c, _d;
30
- let partialConfigDef = {};
31
- let partialSetting = {};
32
- this._userCntx = yield this.establishTenantContext(this._userCntx);
33
- let enterprise = (yield this.establishEnterpriseContext()).enterprise;
34
- partialConfigDef.enterprise = enterprise.code;
35
- partialSetting.enterprise = enterprise.code;
36
- let rootMap = yield this.getRootMap(enterprise.code);
37
- let confirmed = false;
38
- do {
39
- // 1. Select Asset
40
- partialConfigDef.asset = yield this.promptForAsset(enterprise.assets);
41
- // 2. Set Target File
42
- let selectedFile = (yield this.promptForTargetFile(partialConfigDef.enterprise, partialConfigDef.asset));
43
- partialConfigDef.targetFile = selectedFile.targetFile;
44
- partialConfigDef.settings = selectedFile.settings;
45
- // 3. Setting
46
- partialSetting.setting = yield this.promptForSetting((_b = partialConfigDef.settings) !== null && _b !== void 0 ? _b : [], (_c = args.setting) !== null && _c !== void 0 ? _c : flags.setting);
47
- let existingValues = (_d = partialConfigDef.settings) === null || _d === void 0 ? void 0 : _d.filter(s => s.setting === partialSetting.setting);
48
- // 4. Scope
49
- let selectedScope = yield this.promptForScope(partialConfigDef.enterprise, rootMap, existingValues);
50
- partialSetting.scope = selectedScope.scope;
51
- partialSetting.target = selectedScope.target;
52
- // 5. Value
53
- partialSetting.value = yield this.promptForValue({ setting: partialSetting.setting, scope: partialSetting.scope, target: partialSetting.target, enterprise: partialSetting.enterprise }, existingValues, rootMap);
54
- // 6. Confirm or loop back around to enterprise
55
- confirmed = yield this._ui.promptConfirm("confirm", "Apply? ");
56
- } while (!confirmed);
57
- let candidate = Object.assign({ setting: partialSetting.setting, value: partialSetting.value, targetFile: partialConfigDef.targetFile, asset: partialConfigDef.asset, enterprise: partialConfigDef.enterprise, scope: partialSetting.scope, target: partialSetting.target, description: partialSetting.description }, this.createAuditable());
58
- yield this.upsertSetting(candidate);
59
- /*
60
- MarkStartHere("NEW WORKFLOW...");
61
-
62
- 1. Prompt for Asset
63
- default = this._projUserCfg?.enterprise?.assetBindings?[0] ?? this._userCntx.currentEnterprise?.asset;
64
- let aCntx = await this.establishAssetContext(enterprise, true);
65
-
66
- 2. Target File
67
- (select from existing or AddNEw option)
68
- if (addNew)
69
- freehand prompt with "?" as default (enter "?" to browse)
70
- enter rel path from container root (app root?)
71
-
72
- 3. Setting
73
- select from existing
74
- if file selected, merge and dim
75
- (tree with "+newChild" at top of each branch) (How do you prevent selection of branch vs leaf?)
76
-
77
- 4. Scope ("Where will it apply?")
78
- cabinet tree view with un-hydrated scopes dimmed, hydrated showing values
79
-
80
- 5. Value
81
- (render pedigree)
82
- default = flags.value ?? selectedFile.value ?? existing.value
83
-
84
- 6. Confirm or loop back around to enterprise
85
- */
86
- // let cab = await this.establishCabinet(flags.cabinet, true);
87
- // let configName = flags.file || CodiacConstants.DEFAULT_APP_SETTINGS_FILENAME;
88
- // if (configName == PROMPT_ME_DESIGNATOR) {
89
- // let confirmed = false;
90
- // while (!confirmed) {
91
- // // Step 1) select the distribution folder (aka: the build output folder)
92
- // let folderOptions: FolderSelectionOptions = {
93
- // root: this._projectRoot,
94
- // startingPath: process.cwd(),
95
- // };
96
- // let distFolder = await this._ui.promptSelectFolder("distFolder", "Select the distribution folder (aka: the build output folder)...", folderOptions);
97
- // // Step 2) select the config file within it.
98
- // let options: FileSelectionOptions = {
99
- // root: distFolder,
100
- // startingPath: distFolder,
101
- // extensions: ["json", "config", "yaml", "ini", "properties"],
102
- // asRelative: true
103
- // };
104
- // configName = await this._ui.promptSelectFile("targetFile", "Select the target file...", options);
105
- // confirmed = await this._ui.promptConfirm("targetFileCOnfirmation", `Target file: ${configName}`, true);
106
- // }
107
- // // this._ui.userMessage("Select the target file...")
108
- // // let relativeTo = process.cwd();
109
- // // let exts = ["json", "config", "yaml", "ini", "properties"];
110
- // // let ptn = `\\.(${exts.join("|")})$`;
111
- // // let rx = new RegExp(ptn, "i");
112
- // // let options: any = {
113
- // // multi: true,
114
- // // clearConsole: false,
115
- // // root: this._projectRoot
116
- // // // fileFilter: (filename: string) => { return /\.(json|yaml|config|properties|ini)$/i.test(filename) } });
117
- // // }
118
- // // options.fileFilter = (fileName: string) => rx.test(fileName);
119
- // // let fileResult = await selectFiles(options);
120
- // // console.dir(fileResult);
121
- // // if (fileResult.status == COMPLETED && fileResult.selectedFiles && fileResult.selectedFiles.length > 0) {
122
- // // let selected = fileResult.selectedFiles[0];
123
- // // let relPathName = path.relative(relativeTo, selected);
124
- // // this._ui.userMessage(`Selected file: ${relPathName}`);
125
- // // }
126
- // }
127
- // // 1 Get the list of available built in system settings
128
- // // stub:
129
- // this._appConfig = this._ops.loadConfig();
130
- // let avails = await this.getAvailableSettings();
131
- // // Prompt for setting if reqd
132
- // let setting: string = args.setting || flags.setting;
133
- // if (!setting) {
134
- // let result = await inquirer.prompt({ type: 'list', name: 'setting', message: 'Setting to add:', choices: avails });
135
- // setting = result.setting;
136
- // }
137
- // // this.log(result.setting);
138
- // // PROMPT FOR VALUE (if reqd)
139
- // let val: string;
140
- // if (flags.value) {
141
- // val = flags.value;
142
- // } else {
143
- // // TODO: this current value needs to support the scoped value set
144
- // let currentValue = (this._appConfig) ? this._appConfig[setting] : undefined;
145
- // let response = await inquirer.prompt({ type: 'input', name: 'settingValue', message: `Value for ${setting}: `, default: currentValue });
146
- // val = response.settingValue;
147
- // }
148
- // if (flags.enterprise || flags.environment || flags.cabinet) {
149
- // // WRITE SCOPED TO THE API
150
- // let level: ScopeLevel = ScopeLevel.enterprise;
151
- // let scopeName: string = "";
152
- // if (flags.enterprise) {
153
- // level = ScopeLevel.enterprise;
154
- // scopeName = flags.enterprise;
155
- // } else if (flags.environment) {
156
- // level = ScopeLevel.environment;
157
- // scopeName = flags.environment;
158
- // } else if (flags.cabinet) {
159
- // level = ScopeLevel.cabinet;
160
- // scopeName = flags.cabinet;
161
- // }
162
- // this.writeSetting_Api(partialConfigDef.enterprise, partialConfigDef.asset, configName, setting, level, scopeName, val);
163
- // } else {
164
- // // WRITE UNSCOPED TO LOCAL
165
- // this.writeSetting_local(setting, val);
166
- // }
167
- // this.log(`Applied ${configName} setting "${setting}" = "${val}"`);
89
+ try {
90
+ // 0. SET DEFAULTS
91
+ this._userCntx = yield this.establishTenantContext(this._userCntx);
92
+ let enterprise = (yield this.establishEnterpriseContext()).enterprise;
93
+ // 1. CAPTURE ARGS
94
+ let [partial, interactionMode] = yield this.captureArgs(enterprise.code);
95
+ // 2. ACQUIRE INPUT
96
+ let rootMap = yield this.getRootMap(enterprise.code);
97
+ let candidate;
98
+ if (interactionMode == InteractionModes.silent) {
99
+ candidate = this.buildCandidate_silently(partial, rootMap);
100
+ }
101
+ else {
102
+ candidate = yield this.buildCandidate_interactively(partial, rootMap);
103
+ }
104
+ // In case we're hanging waiting for piped-in data that doesnt exist...
105
+ if (!process.stdin.destroyed)
106
+ process.stdin.destroy();
107
+ if (candidate == undefined) {
108
+ this.logger.notice(`Operation cancelled. No work was done.`);
109
+ this._ui.userMessage(`Operation cancelled. No work was done.`);
110
+ this.exit(0);
111
+ }
112
+ else {
113
+ // 3. RENDER COMMAND STRING
114
+ if (interactionMode != undefined && [InteractionModes.echo, InteractionModes.toscript].includes(interactionMode)) {
115
+ this.cmd = this.buildCommandString(candidate, this.cmd);
116
+ this._ui.userMessage(this.cmd.join(" "));
117
+ }
118
+ if (interactionMode != InteractionModes.toscript) {
119
+ // 4. EXECUTE THE MAIN TASK
120
+ yield this.executeTask(candidate);
121
+ }
122
+ }
123
+ return;
124
+ }
125
+ catch (err) {
126
+ this.handleError(err);
127
+ // dont rethrow - err handling in the observable isnt yet user-friendly.
128
+ }
168
129
  }));
169
130
  }
170
131
  catch (err) {
@@ -173,11 +134,149 @@ class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
173
134
  }
174
135
  });
175
136
  }
176
- promptForAsset(assets) {
137
+ captureArgs(currentEnterprise) {
138
+ var _a, _b, _c, _d, _e, _f, _g;
177
139
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
140
+ // TODO: Move this into the base class
141
+ const { args, flags } = yield this.parse(ConfigAdd);
142
+ // TODO: Consider making this parse a separate abstract base method
143
+ // stdin
144
+ let inputDoc;
145
+ if (this.pipedInput) {
146
+ inputDoc = this.configUtils.parseInputString(this.pipedInput.trim());
147
+ this._ui.userMessage(`Found ${inputDoc.length} record(s) to add in the stdin pipeline.`);
148
+ }
149
+ let partial = { enterprise: currentEnterprise };
150
+ partial.asset = flags.asset;
151
+ if (flags.type) {
152
+ partial.configType = Object.values(config_ui_utils_1.SpecialConfigTypes).find(x => x.toString() == flags.type);
153
+ if (partial.configType == undefined)
154
+ delete partial.configType;
155
+ }
156
+ else if (flags.file) {
157
+ partial.targetFile = flags.file;
158
+ }
159
+ partial.scope =
160
+ (_b = (_a = (flags['enterprise-scope'] ? codiac_relay_contracts_1.ScopeLevel.enterprise : undefined)) !== null && _a !== void 0 ? _a : (flags.enviro ? codiac_relay_contracts_1.ScopeLevel.environment : undefined)) !== null && _b !== void 0 ? _b : (flags.cabinet ? codiac_relay_contracts_1.ScopeLevel.cabinet : undefined);
161
+ partial.target =
162
+ (_d = (_c = (flags['enterprise-scope'] ? partial.enterprise : undefined)) !== null && _c !== void 0 ? _c : flags.enviro) !== null && _d !== void 0 ? _d : flags.cabinet;
163
+ if (flags.setting) {
164
+ partial.settings = [{ setting: flags.setting, value: flags.value }];
165
+ }
166
+ if (inputDoc != undefined) {
167
+ partial.settings = ((_e = partial.settings) !== null && _e !== void 0 ? _e : []).concat(inputDoc);
168
+ }
169
+ // partial.description = flags.description;
170
+ // TODO: move this into the base class
171
+ const interactionMode = (this.pipedInput) ? InteractionModes.silent : (_g = (_f = undefined !== null && undefined !== void 0 ? undefined : (flags.echo ? InteractionModes.echo : undefined)) !== null && _f !== void 0 ? _f : (flags["to-script"] ? InteractionModes.toscript : undefined)) !== null && _g !== void 0 ? _g : (flags.silent ? InteractionModes.silent : undefined);
172
+ return [partial, interactionMode];
173
+ });
174
+ }
175
+ parseTable(input, separator = ",") {
176
+ let output = [];
177
+ let lines = input
178
+ .split("\n")
179
+ .map(x => x.trim());
180
+ lines.shift();
181
+ lines.forEach(x => {
182
+ let parts = x.split(",").map(x => x.trim());
183
+ output.push({ setting: parts[0], value: parts[1] });
184
+ });
185
+ return output;
186
+ }
187
+ buildCandidate_silently(partial, rootMap) {
188
+ var _a;
189
+ try {
190
+ // VALIDATE / SET DEFAULTS
191
+ if (partial.asset == undefined || _.isEmpty(partial.asset))
192
+ throw new Error(`Invalid input: missing asset name.`);
193
+ if (partial.enterprise == undefined || _.isEmpty(partial.enterprise)) {
194
+ // Derive the one OR throw if it's indeterminate
195
+ let assetParents = rootMap.enterprises.filter(e => e.assets.find(a => a.name == partial.asset));
196
+ if (assetParents.length == 1) {
197
+ partial.enterprise = assetParents[0].name;
198
+ }
199
+ else if (assetParents.length > 1) {
200
+ throw new Error(`Invalid input: missing enterprise.`);
201
+ }
202
+ }
203
+ if (partial.targetFile == undefined && partial.configType == undefined)
204
+ throw new Error("Invalid input: Must specify the file or type.");
205
+ // Validate scope/target
206
+ if (partial.scope == undefined || _.isEmpty(partial.scope)) {
207
+ throw new Error(`Invalid input: scope required. Please set --enterprise-scope, --enviro, or --cabinet.`);
208
+ }
209
+ else if (!(Object.keys(codiac_relay_contracts_1.ScopeLevel)).includes(partial.scope)) {
210
+ throw new Error(`Invalid input: invalid scope level. Please set --enterprise-scope, --enviro, or --cabinet.`);
211
+ }
212
+ if (partial.scope == codiac_relay_contracts_1.ScopeLevel.enterprise) {
213
+ // This code should never get reached. Its just here for completeness.
214
+ if ((partial.target != undefined || _.isEmpty(partial.target)) && (partial.target != partial.enterprise))
215
+ throw new Error(`Invalid input: scope target for enterprise scope should match the enterprise.`);
216
+ }
217
+ else if (partial.target == undefined || _.isEmpty(partial.target)) {
218
+ throw new Error(`Invalid input: missing scope target. Please set --enterprise-scope, --enviro, or --cabinet.`);
219
+ }
220
+ else if ((0, config_ui_utils_1.findScopeTarget)(rootMap, partial.scope, partial.target) == undefined) {
221
+ throw new Error(`Invalid input: the given ${partial.scope} was not found.`);
222
+ }
223
+ if (partial.settings == undefined || partial.settings.length == 0)
224
+ throw new Error(`Invalid input: missing setting name/value.`);
225
+ // if (partial.setting == undefined || _.isEmpty(partial.setting)) throw new Error(`Invalid input: missing setting name.`)
226
+ if (partial.settings[0].value == undefined || _.isEmpty(partial.settings[0].value))
227
+ throw new Error(`Invalid input: missing setting value.`);
228
+ let output = Object.assign({ enterprise: partial.enterprise, asset: partial.asset, scope: (_a = partial.scope) !== null && _a !== void 0 ? _a : codiac_relay_contracts_1.ScopeLevel.enterprise, target: partial.target, targetFile: (partial.targetFile) ? partial.targetFile : `[${partial.configType}]`, settings: partial.settings,
229
+ // setting: partial.setting,
230
+ // value: partial.value,
231
+ description: partial.description }, this.createAuditable());
232
+ return output;
233
+ }
234
+ catch (err) {
235
+ throw err;
236
+ }
237
+ }
238
+ buildCandidate_interactively(partial, rootMap) {
239
+ var _a;
240
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
241
+ let output;
178
242
  try {
179
- let choices = assets.map(a => { return { name: a.name, value: a.name }; });
180
- let output = (yield this._ui.promptSelect("asset", "Asset: ", choices));
243
+ let partialConfigDef = {};
244
+ partialConfigDef.enterprise = partial.enterprise;
245
+ let enterprise = rootMap.enterprises.find(e => e.name == partial.enterprise);
246
+ if (enterprise == undefined)
247
+ throw new Error("Invalid enterprise"); // <--- here just for TS - shd never get hit (if it hit, itd be guaranteed to confuse the user).
248
+ let confirmed = false;
249
+ do {
250
+ // 1. Select Asset
251
+ let assetChanged;
252
+ [partialConfigDef.asset, assetChanged] = yield this.configUtils.promptForAsset(enterprise.assets, partial.asset);
253
+ // 2. Set Target File
254
+ let selectedFile = (yield this.promptForTargetFile(partial.enterprise, partialConfigDef.asset));
255
+ partialConfigDef.targetFile = selectedFile.targetFile;
256
+ partialConfigDef.settings = selectedFile.settings;
257
+ // 3. Setting
258
+ let settingName;
259
+ let value;
260
+ let instances;
261
+ if (partial.settings != undefined && partial.settings.length > 0) {
262
+ settingName = partial.settings[0].setting;
263
+ value = partial.settings[0].value;
264
+ }
265
+ [settingName, instances] = yield this.configUtils.promptForOneSetting((_a = partialConfigDef.settings) !== null && _a !== void 0 ? _a : [], "write", settingName);
266
+ // 4. Scope
267
+ let selectedScope = yield this.promptForScope(partialConfigDef.enterprise, rootMap, instances);
268
+ partial.scope = selectedScope.scope;
269
+ partial.target = selectedScope.target;
270
+ // 5. Value
271
+ value = yield this.promptForValue({ setting: settingName, value: value, scope: partial.scope, target: partial.target, enterprise: partial.enterprise }, instances, rootMap);
272
+ partial.settings = [{ setting: settingName, value: value }];
273
+ // 6. Confirm or loop back around to enterprise
274
+ confirmed = yield this._ui.promptConfirm("confirm", "Apply? ");
275
+ } while (!confirmed);
276
+ output = Object.assign({
277
+ // setting: partial.setting,
278
+ // value: partial.value,
279
+ settings: partial.settings, targetFile: partialConfigDef.targetFile, asset: partialConfigDef.asset, enterprise: partialConfigDef.enterprise, scope: partial.scope, target: partial.target, description: partial.description }, this.createAuditable());
181
280
  return output;
182
281
  }
183
282
  catch (err) {
@@ -185,6 +284,50 @@ class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
185
284
  }
186
285
  });
187
286
  }
287
+ buildCommandString(ultimate, cmd) {
288
+ cmd.push("--enterprise", ultimate.enterprise);
289
+ cmd.push("-a", ultimate.asset);
290
+ if (ultimate.configType) {
291
+ cmd.push("-t", ultimate.configType);
292
+ }
293
+ else {
294
+ cmd.push("-f", ultimate.targetFile); // assertion is ok bc we forced one or the other just above ^.
295
+ }
296
+ if (ultimate.scope) {
297
+ if (ultimate.scope == codiac_relay_contracts_1.ScopeLevel.enterprise) {
298
+ cmd.push("--enterprise-scope");
299
+ }
300
+ else if (ultimate.target) {
301
+ if (ultimate.scope == codiac_relay_contracts_1.ScopeLevel.environment)
302
+ cmd.push("-e", ultimate.target);
303
+ if (ultimate.scope == codiac_relay_contracts_1.ScopeLevel.cabinet)
304
+ cmd.push("-c", ultimate.target);
305
+ }
306
+ }
307
+ // NOTE: We can't provide for multiple settings in the cli.
308
+ // Unless:
309
+ // a) we allow multple --setting args and use the --setting "key=value" syntax
310
+ // OR b) we send them back a command string that pipes the settings in
311
+ if (ultimate.settings && ultimate.settings.length > 0) {
312
+ // for (let setting of ultimate.settings) {
313
+ let setting = ultimate.settings[0];
314
+ if (ultimate.settings[0].setting)
315
+ cmd.push("--setting", setting.setting);
316
+ if (ultimate.settings[0].value)
317
+ cmd.push("--value", setting.value);
318
+ // }
319
+ }
320
+ return cmd;
321
+ }
322
+ // private async promptForAsset(assets: AtLeast<Asset, "name">[]): Promise<string> {
323
+ // try {
324
+ // let choices = assets.map(a => { return { name: a.name, value: a.name }; })
325
+ // let output = (await this._ui.promptSelect("asset", "Asset: ", choices))!;
326
+ // return output;
327
+ // } catch (err) {
328
+ // throw err;
329
+ // }
330
+ // }
188
331
  promptForValue(setting, existingValues, rootMap) {
189
332
  var _a;
190
333
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -341,52 +484,6 @@ class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
341
484
  }
342
485
  return output;
343
486
  }
344
- /**
345
- *
346
- * Use this inquirer plugin for navigating the object structure:
347
- * https://github.com/insightfuls/inquirer-tree-prompt
348
- *
349
- * See if this file tree selector could be fashioned to do the same:
350
- * https://github.com/anc95/inquirer-file-tree-selection
351
- *
352
- * @param existing
353
- * @param defaultSetting
354
- */
355
- promptForSetting(existing, defaultSetting) {
356
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
357
- try {
358
- let setting;
359
- // TODO: render a tree of settings (cant select the branches, just the leaf nodes)
360
- if (existing.length > 0) {
361
- // let choices = existing.map(s => { return { name: s.setting, value: s.setting }; });
362
- let choices = _.uniq(existing.map(s => s.setting));
363
- choices.push(CodiacConstants.CliConstants.CHOICE_VALUE_FOR_NEW);
364
- setting = (yield this._ui.promptSelect("settingSelect", "Setting: ", choices));
365
- }
366
- if (setting === CodiacConstants.CliConstants.CHOICE_VALUE_FOR_NEW || setting === undefined) {
367
- setting = (yield this._ui.prompt("settingFreehand", "Setting (use '.' for hierarchy): "));
368
- }
369
- if (existing.find(s => s.setting === setting)) {
370
- // matched an existing setting afterall
371
- }
372
- // ----------------------------------------------------------------------------------------------
373
- // // Try to implement un-selectable options...
374
- // let settings = ["bill", "sam", "tom", "harry"];
375
- // let choices: any[] = settings.map(s => { return { name: s, value: s }; });
376
- // // choices.push({ name: "some branch", value: new inquirer.Separator("--I am a branch") });
377
- // choices.push(new inquirer.Separator("--I am a branch"));
378
- // choices.push({ name: "sally", value: "sally" });
379
- // choices.push({ name: "Sue", value: "Sue" });
380
- // choices.push({ name: "Suzy", value: "Suzy" });
381
- // let nada = await this._ui.promptSelect("test", "try this", choices);
382
- // ----------------------------------------------------------------------------------------------
383
- return setting;
384
- }
385
- catch (err) {
386
- throw err;
387
- }
388
- });
389
- }
390
487
  /** Copy of this method is in config:view */
391
488
  promptForTargetFile(enterprise, asset) {
392
489
  var _a, _b;
@@ -460,14 +557,28 @@ class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
460
557
  }
461
558
  });
462
559
  }
463
- writeSetting_Api(enterprise, assetName, configName, setting, scopeLevel, scopeName, val) {
560
+ // async writeSetting_Api(enterprise: string, assetName: string, configName: string, setting: string, scopeLevel: ScopeLevel, scopeName: string, val: any): Promise<void> {
561
+ // try {
562
+ // let settingObj: ScopedSetting = {
563
+ // setting: setting,
564
+ // value: val,
565
+ // targetFile: configName,
566
+ // asset: assetName,
567
+ // enterprise: enterprise,
568
+ // scope: scopeLevel,
569
+ // target: scopeName,
570
+ // ...this.createAuditable()
571
+ // };
572
+ // return this.upsertSetting(settingObj);
573
+ // } catch (err) {
574
+ // throw err;
575
+ // }
576
+ // }
577
+ executeTask(candidate) {
464
578
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
465
- try {
466
- let settingObj = Object.assign({ setting: setting, value: val, targetFile: configName, asset: assetName, enterprise: enterprise, scope: scopeLevel, target: scopeName }, this.createAuditable());
467
- return this.upsertSetting(settingObj);
468
- }
469
- catch (err) {
470
- throw err;
579
+ // TODO: Do this in a single batch call
580
+ for (let setting of candidate.settings) {
581
+ yield this.upsertSetting(Object.assign(Object.assign({}, candidate), { setting: setting.setting, value: setting.value }));
471
582
  }
472
583
  });
473
584
  }
@@ -475,12 +586,6 @@ class ConfigAdd extends command_base_enterprise_1.CommandBaseEnterprise {
475
586
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
476
587
  return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
477
588
  try {
478
- // TODO: Look to enterprise context instead.
479
- // let enterprise = /* this._cfg.enterprise || */ this._projCfg.tenantCode;
480
- // TODO: Look to asset context instead - and if none, fail and call for "$ cod asset:set"
481
- // let assetName = this._projCfg.name; // this needs to be taken from an image definition. (AssetBinding[] needs to be added to each ImageExport)
482
- // NOTE: We could bind a config to an image name,
483
- // and then allow for an Asset scope to set values on it...
484
589
  let crit = {
485
590
  enterprise: settingObj.enterprise,
486
591
  asset: settingObj.asset,
@@ -547,14 +652,21 @@ ConfigAdd.description = 'Adds a key value pair to the app config';
547
652
  ConfigAdd.aliases = ['config:set', 'cfg:add'];
548
653
  ConfigAdd.flags = {
549
654
  help: core_1.Flags.help({ char: 'h' }),
550
- setting: core_1.Flags.string({ char: 's', required: false, description: "The config key (in dotpath/JSONPath), relative to the root of the config." }),
551
- value: core_1.Flags.string({ char: 'v', required: false, description: "The actual concrete data to be applied as the setting value." }),
552
- enterprise: core_1.Flags.string({ char: 'n', exclusive: ["environment", "cabinet"], description: 'The name of the enterprise to which this value is to apply.' }),
553
- environment: core_1.Flags.string({ char: 'e', exclusive: ["enterprise", "cabinet"], description: 'The name of the environment to which this value is to apply.' }),
554
- cabinet: core_1.Flags.string({ char: 'c', exclusive: ["enterprise", "environment"], description: 'The name of the cabinet to which this value is to apply.' }),
555
- file: core_1.Flags.string({ char: 'f', description: 'The path-name to the file to which the settings are written, relative to the root of the Codiac project.' })
655
+ enterprise: core_1.Flags.string({ char: 'n', description: '(required only when more than one enterprise exists) The name of the enterprise containing the asset.' }),
656
+ asset: core_1.Flags.string({ char: 'a', description: 'The name of the asset to which the settings belong.' }),
657
+ file: core_1.Flags.string({ char: 'f', description: 'The path-name to the file to which the settings are written, relative to the root of the Codiac project.' }),
658
+ type: core_1.Flags.string({ char: 't', exclusive: ["file"], options: Object.keys(config_ui_utils_1.SpecialConfigTypes), description: 'Filters for the settings types that do not land in a config file (such as... env: OS environment variables, footprint: container footprint specs, and helm: helm chart settings).' }),
659
+ "enterprise-scope": core_1.Flags.boolean({ char: 's', exclusive: ["enviro", "cabinet"], description: 'Filters for settings scoped at the enterprise level.' }),
660
+ enviro: core_1.Flags.string({ char: 'e', exclusive: ["enterprise-scope", "cabinet"], description: 'The name of the environment to which this value is to apply.' }),
661
+ cabinet: core_1.Flags.string({ char: 'c', exclusive: ["enterprise-scope", "enviro"], description: 'The name of the cabinet to which this value is to apply.' }),
662
+ setting: core_1.Flags.string({ required: false, description: "The config key (in dotpath/JSONPath), relative to the root of the config." }),
663
+ value: core_1.Flags.string({ required: false, description: "The actual concrete data to be applied as the setting value." }),
664
+ silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
665
+ echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
666
+ "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
667
+ // "take-defaults": Flags.boolean({ exclusive: ["silent"], description: "Prevents prompting for confirmation on parameters that were passed in or were set to default values." }),
556
668
  };
557
669
  ConfigAdd.args = {
558
- setting: core_1.Args.string({ description: 'The key for the config setting to add' })
670
+ // setting: Args.string({ description: 'The key for the config setting to add' })
559
671
  };
560
672
  //# sourceMappingURL=add.js.map