@adobe/aio-cli-plugin-app 8.2.0 → 8.5.0

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.
@@ -0,0 +1,46 @@
1
+ /*
2
+ Copyright 2019 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const BaseCommand = require('../../../../../BaseCommand')
13
+ const rtLib = require('@adobe/aio-lib-runtime')
14
+ const ora = require('ora')
15
+
16
+ class ErrorsCommand extends BaseCommand {
17
+ async run () {
18
+ const spinner = ora()
19
+ const lf = await this.getLogForwarding()
20
+ spinner.start('Checking for errors...')
21
+ const res = await lf.getErrors()
22
+ const destinationMessage = res.configured_forwarder !== undefined
23
+ ? ` for the last configured destination '${res.configured_forwarder}'`
24
+ : ''
25
+ if (res.errors && res.errors.length > 0) {
26
+ spinner.succeed(`Log forwarding errors${destinationMessage}:\n` + res.errors.join('\n'))
27
+ } else {
28
+ spinner.succeed(`No log forwarding errors${destinationMessage}`)
29
+ }
30
+ }
31
+
32
+ async getLogForwarding () {
33
+ const runtimeConfig = this.getFullConfig().aio.runtime
34
+ rtLib.utils.checkOpenWhiskCredentials({ ow: runtimeConfig })
35
+ const rt = await rtLib.init({
36
+ ...runtimeConfig,
37
+ api_key: runtimeConfig.auth
38
+ })
39
+ return rt.logForwarding
40
+ }
41
+ }
42
+
43
+ ErrorsCommand.description = 'Get log forwarding errors'
44
+ ErrorsCommand.aliases = ['app:config:get:log-forwarding:errors', 'app:config:get:lf:errors']
45
+
46
+ module.exports = ErrorsCommand
@@ -0,0 +1,50 @@
1
+ /*
2
+ Copyright 2019 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const BaseCommand = require('../../../../BaseCommand')
13
+ const LogForwarding = require('../../../../lib/log-forwarding')
14
+
15
+ class LogForwardingCommand extends BaseCommand {
16
+ async run () {
17
+ const lf = await LogForwarding.init(this.getFullConfig().aio)
18
+
19
+ const localConfig = lf.getLocalConfig()
20
+ const serverConfig = await lf.getServerConfig()
21
+
22
+ if (!localConfig.isEqual(serverConfig)) {
23
+ this.log('Local and server log forwarding configuration is different')
24
+ let message = 'Run'
25
+ if (localConfig.isDefined()) {
26
+ message += " either 'aio app:deploy' to update the server, or"
27
+ }
28
+ message += " 'aio app:config:set:log-forwarding' to set new local and server configuration"
29
+ this.log(message)
30
+ this.log('Local configuration:')
31
+ this.printConfig(localConfig)
32
+ this.log('\nServer configuration:')
33
+ }
34
+ this.printConfig(serverConfig)
35
+ }
36
+
37
+ printConfig (config) {
38
+ if (config.isDefined()) {
39
+ this.log(`destination: ${config.getDestination()}`)
40
+ this.log('settings:', config.getSettings())
41
+ } else {
42
+ this.log('Not defined')
43
+ }
44
+ }
45
+ }
46
+
47
+ LogForwardingCommand.description = 'Get log forwarding destination configuration'
48
+ LogForwardingCommand.aliases = ['app:config:get:log-forwarding', 'app:config:get:lf']
49
+
50
+ module.exports = LogForwardingCommand
@@ -0,0 +1,25 @@
1
+ /*
2
+ Copyright 2019 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const HHelp = require('@oclif/plugin-help').default
13
+ const BaseCommand = require('../../../BaseCommand')
14
+
15
+ class IndexCommand extends BaseCommand {
16
+ async run () {
17
+ const help = new HHelp(this.config)
18
+ help.showHelp(['app:config', '--help'])
19
+ }
20
+ }
21
+
22
+ IndexCommand.description = 'Manage app config'
23
+ IndexCommand.aliases = ['app:config', 'app:config']
24
+
25
+ module.exports = IndexCommand
@@ -0,0 +1,25 @@
1
+ /*
2
+ Copyright 2019 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const HHelp = require('@oclif/plugin-help').default
13
+ const BaseCommand = require('../../../../BaseCommand')
14
+
15
+ class IndexCommand extends BaseCommand {
16
+ async run () {
17
+ const help = new HHelp(this.config)
18
+ help.showHelp(['app:config:set', '--help'])
19
+ }
20
+ }
21
+
22
+ IndexCommand.description = 'Set app config'
23
+ IndexCommand.aliases = ['app:config:set']
24
+
25
+ module.exports = IndexCommand
@@ -0,0 +1,46 @@
1
+ /*
2
+ Copyright 2019 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const BaseCommand = require('../../../../BaseCommand')
13
+ const LogForwarding = require('../../../../lib/log-forwarding')
14
+
15
+ class LogForwardingCommand extends BaseCommand {
16
+ async run () {
17
+ const lf = await LogForwarding.init(this.getFullConfig().aio)
18
+
19
+ const destination = await this.promptDestination(lf.getSupportedDestinations())
20
+ const destinationSettingsConfig = lf.getSettingsConfig(destination)
21
+ const settings = await this.prompt(destinationSettingsConfig)
22
+ const lfConfig = new LogForwarding.LogForwardingConfig(destination, settings)
23
+
24
+ const res = await lf.updateServerConfig(lfConfig)
25
+ this.log(`Log forwarding is set to '${destination}'`)
26
+
27
+ const fullSanitizedConfig = lfConfig.getMergedConfig(lf.getConfigFromJson(res))
28
+ await lf.updateLocalConfig(fullSanitizedConfig)
29
+ this.log('Log forwarding settings are saved to the local configuration')
30
+ }
31
+
32
+ async promptDestination (supportedDestinations) {
33
+ const responses = await this.prompt([{
34
+ name: 'type',
35
+ message: 'select log forwarding destination',
36
+ type: 'list',
37
+ choices: supportedDestinations
38
+ }])
39
+ return responses.type
40
+ }
41
+ }
42
+
43
+ LogForwardingCommand.description = 'Set log forwarding destination configuration'
44
+ LogForwardingCommand.aliases = ['app:config:set:log-forwarding', 'app:config:set:lf']
45
+
46
+ module.exports = LogForwardingCommand
@@ -87,7 +87,7 @@ class DeleteActionCommand extends BaseCommand {
87
87
  // NOTE: (attempt) to delete test files. The test file must match the action name
88
88
  // file in the same folder, which is true in most cases, but won't work for asset compute action tests for example.
89
89
  try {
90
- const pathToE2eTests = path.join(action.e2eTestsDir, action.actionName + '.e2e.js')
90
+ const pathToE2eTests = path.join(action.e2eTestsDir, action.actionName + '.e2e.test.js')
91
91
  const pathToUnitTests = path.join(action.unitTestsDir, action.actionName + '.test.js')
92
92
  fs.removeSync(pathToE2eTests)
93
93
  aioLogger.debug(`deleted '${pathToE2eTests}'`)
@@ -24,7 +24,9 @@ class DeleteCICommand extends BaseCommand {
24
24
  const env = yeoman.createEnv()
25
25
  const gen = env.instantiate(generators['delete-ci'], {
26
26
  options: {
27
- 'skip-prompt': flags.yes
27
+ 'skip-prompt': flags.yes,
28
+ // by default yeoman runs the install, we control installation from the app plugin
29
+ 'skip-install': true
28
30
  }
29
31
  })
30
32
  await env.runGenerator(gen)
@@ -21,6 +21,7 @@ const webLib = require('@adobe/aio-lib-web')
21
21
  const { flags } = require('@oclif/command')
22
22
  const { createWebExportFilter, runScript, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata } = require('../../lib/app-helper')
23
23
  const rtLib = require('@adobe/aio-lib-runtime')
24
+ const LogForwarding = require('../../lib/log-forwarding')
24
25
 
25
26
  class Deploy extends BuildCommand {
26
27
  async run () {
@@ -55,7 +56,36 @@ class Deploy extends BuildCommand {
55
56
  const spinner = ora()
56
57
 
57
58
  try {
58
- // 1. deploy actions and web assets for each extension
59
+ const aioConfig = this.getFullConfig().aio
60
+ // 1. update log forwarding configuration
61
+ // note: it is possible that .aio file does not exist, which means there is no local lg config
62
+ if (aioConfig &&
63
+ aioConfig.project &&
64
+ aioConfig.project.workspace &&
65
+ flags['log-forwarding-update'] &&
66
+ flags.actions) {
67
+ spinner.start('Updating log forwarding configuration')
68
+ try {
69
+ const lf = await LogForwarding.init(aioConfig)
70
+ if (lf.isLocalConfigChanged()) {
71
+ const lfConfig = lf.getLocalConfigWithSecrets()
72
+ if (lfConfig.isDefined()) {
73
+ await lf.updateServerConfig(lfConfig)
74
+ spinner.succeed(chalk.green(`Log forwarding is set to '${lfConfig.getDestination()}'`))
75
+ } else {
76
+ if (flags.verbose) {
77
+ spinner.info(chalk.dim('Log forwarding is not updated: no configuration is provided'))
78
+ }
79
+ }
80
+ } else {
81
+ spinner.info(chalk.dim('Log forwarding is not updated: configuration not changed since last update'))
82
+ }
83
+ } catch (error) {
84
+ spinner.fail(chalk.red('Log forwarding is not updated.'))
85
+ throw error
86
+ }
87
+ }
88
+ // 2. deploy actions and web assets for each extension
59
89
  // Possible improvements:
60
90
  // - parallelize
61
91
  // - break into smaller pieces deploy, allowing to first deploy all actions then all web assets
@@ -64,9 +94,9 @@ class Deploy extends BuildCommand {
64
94
  const v = values[i]
65
95
  await this.deploySingleConfig(k, v, flags, spinner)
66
96
  }
67
- // 2. deploy extension manifest
97
+
98
+ // 3. deploy extension manifest
68
99
  if (flags.publish) {
69
- const aioConfig = this.getFullConfig().aio
70
100
  const payload = await this.publishExtensionPoints(libConsoleCLI, deployConfigs, aioConfig, flags['force-publish'])
71
101
  this.log(chalk.blue(chalk.bold(`New Extension Point(s) in Workspace '${aioConfig.project.workspace.name}': '${Object.keys(payload.endpoints)}'`)))
72
102
  } else {
@@ -84,12 +114,14 @@ class Deploy extends BuildCommand {
84
114
  }
85
115
 
86
116
  async deploySingleConfig (name, config, flags, spinner) {
87
- const onProgress = !flags.verbose ? info => {
88
- spinner.text = info
89
- } : info => {
90
- spinner.info(chalk.dim(`${info}`))
91
- spinner.start()
92
- }
117
+ const onProgress = !flags.verbose
118
+ ? info => {
119
+ spinner.text = info
120
+ }
121
+ : info => {
122
+ spinner.info(chalk.dim(`${info}`))
123
+ spinner.start()
124
+ }
93
125
 
94
126
  // build phase
95
127
  if (flags.build) {
@@ -300,6 +332,11 @@ Deploy.flags = {
300
332
  'web-optimize': flags.boolean({
301
333
  description: '[default: false] Enable optimization (minification) of web js/css/html',
302
334
  default: false
335
+ }),
336
+ 'log-forwarding-update': flags.boolean({
337
+ description: '[default: true] Update log forwarding configuration on server',
338
+ default: true,
339
+ allowNo: true
303
340
  })
304
341
  }
305
342
 
@@ -9,7 +9,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
9
9
  governing permissions and limitations under the License.
10
10
  */
11
11
 
12
- const BaseCommand = require('../../BaseCommand')
12
+ const AddCommand = require('../../AddCommand')
13
13
  const yeoman = require('yeoman-environment')
14
14
  const path = require('path')
15
15
  const fs = require('fs-extra')
@@ -20,14 +20,14 @@ const { flags } = require('@oclif/command')
20
20
  const generators = require('@adobe/generator-aio-app')
21
21
 
22
22
  const { loadAndValidateConfigFile, importConfigJson } = require('../../lib/import')
23
- const { installPackages, atLeastOne } = require('../../lib/app-helper')
23
+ const { atLeastOne } = require('../../lib/app-helper')
24
24
 
25
25
  const { ENTP_INT_CERTS_FOLDER, SERVICE_API_KEY_ENV, implPromptChoices } = require('../../lib/defaults')
26
26
  const cloneDeep = require('lodash.clonedeep')
27
27
 
28
28
  const DEFAULT_WORKSPACE = 'Stage'
29
29
 
30
- class InitCommand extends BaseCommand {
30
+ class InitCommand extends AddCommand {
31
31
  async run () {
32
32
  const { args, flags } = this.parse(InitCommand)
33
33
 
@@ -56,11 +56,7 @@ class InitCommand extends BaseCommand {
56
56
  }
57
57
 
58
58
  // install packages, always at the end, so user can ctrl+c
59
- if (!flags['skip-install']) {
60
- await installPackages('.', { spinner, verbose: flags.verbose })
61
- } else {
62
- this.log('--skip-install, make sure to run \'npm install\' later on')
63
- }
59
+ await this.runInstallPackages(flags, spinner)
64
60
 
65
61
  this.log(chalk.bold(chalk.green('✔ App initialization finished!')))
66
62
  this.log('> Tip: you can add more actions, web-assets and events to your project via the `aio app add` commands')
@@ -106,7 +102,7 @@ class InitCommand extends BaseCommand {
106
102
  // 3. select or create project
107
103
  const project = await this.selectOrCreateConsoleProject(consoleCLI, org)
108
104
  // 4. retrieve workspace details, defaults to Stage
109
- const workspace = await this.retrieveWorkspaceFromName(consoleCLI, org, project, flags.workspace)
105
+ const workspace = await this.retrieveWorkspaceFromName(consoleCLI, org, project, flags)
110
106
  // 5. ask for exensionPoints, only allow selection for extensions that have services enabled in Org
111
107
  const extensionPoints = await this.selectExtensionPoints(flags, orgSupportedServices)
112
108
  // 6. add any required services to Workspace
@@ -143,7 +139,7 @@ class InitCommand extends BaseCommand {
143
139
  }
144
140
  return extList
145
141
  } else {
146
- const choices = cloneDeep(implPromptChoices).filter(i => i.value.name !== 'application')
142
+ const choices = cloneDeep(implPromptChoices)
147
143
 
148
144
  // disable extensions that lack required services
149
145
  if (orgSupportedServices) {
@@ -190,12 +186,23 @@ class InitCommand extends BaseCommand {
190
186
  return project
191
187
  }
192
188
 
193
- async retrieveWorkspaceFromName (consoleCLI, org, project, workspaceName) {
189
+ async retrieveWorkspaceFromName (consoleCLI, org, project, flags) {
190
+ const workspaceName = flags.workspace
194
191
  // get workspace details
195
192
  const workspaces = await consoleCLI.getWorkspaces(org.id, project.id)
196
- const workspace = workspaces.find(w => w.name.toLowerCase() === workspaceName.toLowerCase())
193
+ let workspace = workspaces.find(w => w.name.toLowerCase() === workspaceName.toLowerCase())
197
194
  if (!workspace) {
198
- throw new Error(`'--workspace=${workspaceName}' in Project '${project.name}' not found.`)
195
+ if (!flags['confirm-new-workspace']) {
196
+ const shouldNewWorkspace = await consoleCLI.prompt.promptConfirm(`Workspace '${workspaceName}' does not exist \n > Do you wish to create a new workspace?`)
197
+ if (!shouldNewWorkspace) {
198
+ this.error(`Workspace '${workspaceName}' does not exist and creation aborted`)
199
+ }
200
+ }
201
+ this.log(`'--workspace=${workspaceName}' in Project '${project.name}' not found. \n Creating one...`)
202
+ workspace = await consoleCLI.createWorkspace(org.id, project.id, {
203
+ name: workspaceName,
204
+ title: ''
205
+ })
199
206
  }
200
207
  return workspace
201
208
  }
@@ -245,14 +252,19 @@ class InitCommand extends BaseCommand {
245
252
 
246
253
  async runCodeGenerators (flags, extensionPoints, projectName) {
247
254
  let env = yeoman.createEnv()
248
- // first run app generator that will generate the root skeleton
249
- const appGen = env.instantiate(generators['base-app'], {
250
- options: {
251
- 'skip-prompt': flags.yes,
252
- 'project-name': projectName
253
- }
254
- })
255
- await env.runGenerator(appGen)
255
+ const initialGenerators = ['base-app', 'add-ci']
256
+ // first run app generator that will generate the root skeleton + ci
257
+ for (const generatorKey of initialGenerators) {
258
+ const appGen = env.instantiate(generators[generatorKey], {
259
+ options: {
260
+ 'skip-prompt': flags.yes,
261
+ 'project-name': projectName,
262
+ // by default yeoman runs the install, we control installation from the app plugin
263
+ 'skip-install': true
264
+ }
265
+ })
266
+ await env.runGenerator(appGen)
267
+ }
256
268
 
257
269
  // Creating new Yeoman env here to workaround an issue where yeoman reuses the conflicter from previous environment.
258
270
  // https://github.com/yeoman/environment/issues/324
@@ -266,7 +278,9 @@ class InitCommand extends BaseCommand {
266
278
  options: {
267
279
  'skip-prompt': flags.yes,
268
280
  // do not prompt for overwrites
269
- force: true
281
+ force: true,
282
+ // by default yeoman runs the install, we control installation from the app plugin
283
+ 'skip-install': true
270
284
  }
271
285
  })
272
286
  await env.runGenerator(extGen)
@@ -295,17 +309,12 @@ InitCommand.description = `Create a new Adobe I/O App
295
309
  `
296
310
 
297
311
  InitCommand.flags = {
298
- ...BaseCommand.flags,
312
+ ...AddCommand.flags,
299
313
  yes: flags.boolean({
300
314
  description: 'Skip questions, and use all default values',
301
315
  default: false,
302
316
  char: 'y'
303
317
  }),
304
- 'skip-install': flags.boolean({
305
- description: 'Skip npm installation after files are created',
306
- char: 's',
307
- default: false
308
- }),
309
318
  import: flags.string({
310
319
  description: 'Import an Adobe I/O Developer Console configuration file',
311
320
  char: 'i'
@@ -331,6 +340,10 @@ InitCommand.flags = {
331
340
  default: DEFAULT_WORKSPACE,
332
341
  char: 'w',
333
342
  exclusive: ['import'] // also no-login
343
+ }),
344
+ 'confirm-new-workspace': flags.boolean({
345
+ description: 'Skip and confirm prompt for creating a new workspace',
346
+ default: false
334
347
  })
335
348
  }
336
349
 
@@ -11,10 +11,10 @@ governing permissions and limitations under the License.
11
11
  */
12
12
 
13
13
  const { flags } = require('@oclif/command')
14
- // const { cli } = require('cli-ux')
15
14
  const BaseCommand = require('../../BaseCommand')
16
15
  const { wrapError } = require('../../lib/app-helper')
17
16
  const rtLib = require('@adobe/aio-lib-runtime')
17
+ const LogForwarding = require('../../lib/log-forwarding')
18
18
 
19
19
  class Logs extends BaseCommand {
20
20
  _processEachAction (fullConfig, processFn) {
@@ -40,6 +40,15 @@ class Logs extends BaseCommand {
40
40
  throw new Error('There are no backend implementations for this project folder.')
41
41
  }
42
42
 
43
+ const lf = await LogForwarding.init(fullConfig.aio)
44
+ const serverConfig = await lf.getServerConfig()
45
+ const logForwardingDestination = serverConfig.getDestination()
46
+ if (logForwardingDestination !== 'adobe_io_runtime') {
47
+ this.log(`Namespace is configured with custom log forwarding destination: '${logForwardingDestination}'. ` +
48
+ 'Please use corresponding logging platform to view logs.')
49
+ return
50
+ }
51
+
43
52
  if (flags.limit < 1) {
44
53
  this.log('--limit should be > 0, using --limit=1')
45
54
  flags.limit = 1
@@ -97,12 +97,14 @@ class Run extends BaseCommand {
97
97
  }
98
98
  }
99
99
 
100
- const onProgress = !flags.verbose ? info => {
101
- spinner.text = info
102
- } : info => {
103
- spinner.info(chalk.dim(`${info}`))
104
- spinner.start()
105
- }
100
+ const onProgress = !flags.verbose
101
+ ? info => {
102
+ spinner.text = info
103
+ }
104
+ : info => {
105
+ spinner.info(chalk.dim(`${info}`))
106
+ spinner.start()
107
+ }
106
108
 
107
109
  const frontendUrl = await runDev(config, this.config.dataDir, runOptions, onProgress)
108
110
  try {
@@ -72,12 +72,14 @@ class Undeploy extends BaseCommand {
72
72
  }
73
73
 
74
74
  async undeployOneExt (extName, config, flags, spinner) {
75
- const onProgress = !flags.verbose ? info => {
76
- spinner.text = info
77
- } : info => {
78
- spinner.info(chalk.dim(`${info}`))
79
- spinner.start()
80
- }
75
+ const onProgress = !flags.verbose
76
+ ? info => {
77
+ spinner.text = info
78
+ }
79
+ : info => {
80
+ spinner.info(chalk.dim(`${info}`))
81
+ spinner.start()
82
+ }
81
83
  // undeploy
82
84
  try {
83
85
  await runScript(config.hooks['pre-app-undeploy'])
@@ -78,14 +78,6 @@ class Use extends BaseCommand {
78
78
  this.error(message)
79
79
  }
80
80
  newConfig = globalConfig
81
- if (
82
- currentConfigIsComplete &&
83
- newConfig.org.id === currentConfig.org.id &&
84
- newConfig.project.id === currentConfig.project.id &&
85
- newConfig.workspace.id === currentConfig.workspace.id
86
- ) {
87
- this.error('The selected configuration is the same as the current configuration.')
88
- }
89
81
  } else {
90
82
  // useOperation = 'workspace'
91
83
  if (!currentConfigIsComplete) {
@@ -190,37 +182,37 @@ class Use extends BaseCommand {
190
182
  * @returns {Buffer} the Adobe Developer Console configuration file for the workspace
191
183
  */
192
184
  async selectTargetWorkspaceInProject (consoleCLI, config, flags) {
193
- const project = { name: config.project.name, id: config.project.id }
194
- const currentWorkspace = { name: config.workspace.name, id: config.workspace.id }
195
-
196
- // make sure user is not trying to switch to current workspace
197
- const workspaceFlag = flags.workspace
198
- if (workspaceFlag === currentWorkspace.name) {
199
- this.cleanConsoleCLIOutput()
200
- this.error(`--workspace=${workspaceFlag} is the same as the currently selected workspace, nothing to be done.`)
201
- }
185
+ const { project, org } = config
186
+ const workspaceNameOrId = flags.workspace
202
187
 
203
188
  // retrieve all workspaces
204
189
  const workspaces = await consoleCLI.getWorkspaces(
205
- config.org.id,
206
- config.project.id
190
+ org.id,
191
+ project.id
207
192
  )
208
- const workspacesButCurrent = workspaces.filter(w => w.id !== currentWorkspace.id)
209
-
210
193
  let workspace
211
-
212
- if (workspaceFlag) {
213
- // workspace name is given, make sure the workspace is in there
214
- workspace = workspacesButCurrent.find(w => w.name === workspaceFlag)
215
- if (!workspace) {
216
- this.cleanConsoleCLIOutput()
217
- this.error(`--workspace=${workspaceFlag} does not exist in current Project ${project.name}.`)
194
+ let workspaceData = { name: workspaceNameOrId }
195
+ // does not prompt if workspaceNameOrId is defined via the flag
196
+ workspace = await consoleCLI.promptForSelectWorkspace(workspaces, { workspaceId: workspaceNameOrId, workspaceName: workspaceNameOrId }, { allowCreate: true })
197
+ if (!workspace) {
198
+ aioLogger.debug(`--workspace=${workspaceNameOrId} was not found in the current Project ${project.name}`)
199
+ if (workspaceNameOrId) {
200
+ if (!flags['confirm-new-workspace']) {
201
+ const shouldNewWorkspace = await consoleCLI.prompt.promptConfirm(`Workspace '${workspaceNameOrId}' does not exist \n > Do you wish to create a new workspace?`)
202
+ if (!shouldNewWorkspace) {
203
+ this.error('Workspace creation aborted')
204
+ }
205
+ }
206
+ } else {
207
+ workspaceData = await consoleCLI.promptForCreateWorkspaceDetails()
218
208
  }
219
- } else {
220
- // workspace name is not given, let the user choose the
221
- workspace = await consoleCLI.promptForSelectWorkspace(workspacesButCurrent)
209
+ aioLogger.debug(`Creating workspace: ${workspaceData.name}`)
210
+ workspace = await consoleCLI.createWorkspace(org.id, project.id, workspaceData)
211
+ }
212
+ return {
213
+ name: workspace.name,
214
+ id: workspace.id
222
215
  }
223
- return { name: workspace.name, id: workspace.id }
224
216
  }
225
217
 
226
218
  /**
@@ -395,11 +387,15 @@ Use.flags = {
395
387
  exclusive: ['workspace']
396
388
  }),
397
389
  workspace: flags.string({
398
- description: 'Specify the Adobe Developer Console Workspace name to import the configuration from',
390
+ description: 'Specify the Adobe Developer Console Workspace name or Workspace id to import the configuration from',
399
391
  default: '',
400
392
  char: 'w',
401
393
  exclusive: ['global', 'workspace-name']
402
394
  }),
395
+ 'confirm-new-workspace': flags.boolean({
396
+ description: 'Skip and confirm prompt for creating a new workspace',
397
+ default: false
398
+ }),
403
399
  'workspace-name': flags.string({
404
400
  description: '[DEPRECATED]: please use --workspace instead',
405
401
  default: '',