@adobe/aio-cli-plugin-app 9.2.0 → 10.0.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.
- package/README.md +21 -38
- package/oclif.manifest.json +1 -1
- package/package.json +5 -2
- package/src/AddCommand.js +1 -7
- package/src/TemplatesCommand.js +256 -0
- package/src/commands/app/add/action.js +85 -31
- package/src/commands/app/add/extension.js +27 -77
- package/src/commands/app/add/service.js +1 -1
- package/src/commands/app/add/web-assets.js +29 -28
- package/src/commands/app/build.js +1 -11
- package/src/commands/app/delete/extension.js +7 -8
- package/src/commands/app/delete/service.js +1 -1
- package/src/commands/app/deploy.js +81 -102
- package/src/commands/app/init.js +178 -147
- package/src/commands/app/run.js +4 -12
- package/src/commands/app/undeploy.js +0 -13
- package/src/lib/defaults.js +1 -32
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2021 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 AddCommand = require('./AddCommand')
|
|
13
|
+
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:TemplatesCommand', { provider: 'debug' })
|
|
14
|
+
const inquirerTableCheckbox = require('@adobe/inquirer-table-checkbox')
|
|
15
|
+
const inquirer = require('inquirer')
|
|
16
|
+
const TemplateRegistryAPI = require('@adobe/aio-lib-templates')
|
|
17
|
+
const hyperlinker = require('hyperlinker')
|
|
18
|
+
const ora = require('ora')
|
|
19
|
+
const terminalSize = require('term-size')
|
|
20
|
+
|
|
21
|
+
class TemplatesCommand extends AddCommand {
|
|
22
|
+
/**
|
|
23
|
+
* Gets a list of templates from the Template Registry API using the criteria provided.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} searchCriteria the Template Registry API search criteria
|
|
26
|
+
* @param {object} orderByCriteria the Template Registry API orderBy criteria
|
|
27
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
28
|
+
* @returns {Array<object>} list of templates
|
|
29
|
+
*/
|
|
30
|
+
async getTemplates (searchCriteria, orderByCriteria, templateRegistryConfig = {}) {
|
|
31
|
+
const templateRegistryClient = TemplateRegistryAPI.init(templateRegistryConfig)
|
|
32
|
+
const templateList = []
|
|
33
|
+
|
|
34
|
+
const templatesIterator = templateRegistryClient.getTemplates(searchCriteria, orderByCriteria)
|
|
35
|
+
|
|
36
|
+
for await (const templates of templatesIterator) {
|
|
37
|
+
for (const template of templates) {
|
|
38
|
+
templateList.push(template)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
aioLogger.debug('template list', JSON.stringify(templateList, null, 2))
|
|
42
|
+
|
|
43
|
+
return templateList
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Select templates from the Template Registry API, via a cli table.
|
|
48
|
+
*
|
|
49
|
+
* @param {object} searchCriteria the Template Registry API search criteria
|
|
50
|
+
* @param {object} orderByCriteria the Template Registry API orderBy criteria
|
|
51
|
+
* @param {Array<object>} orgSupportedServices Services supported by the org
|
|
52
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
53
|
+
* @returns {Array<string>} an array of selected template module name(s)
|
|
54
|
+
*/
|
|
55
|
+
async selectTemplates (searchCriteria, orderByCriteria, orgSupportedServices = undefined, templateRegistryConfig = {}) {
|
|
56
|
+
aioLogger.debug('searchCriteria', JSON.stringify(searchCriteria, null, 2))
|
|
57
|
+
aioLogger.debug('orderByCriteria', JSON.stringify(orderByCriteria, null, 2))
|
|
58
|
+
let supportedServiceCodes
|
|
59
|
+
if (orgSupportedServices) {
|
|
60
|
+
supportedServiceCodes = new Set(orgSupportedServices.map(s => s.code))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const spinner = ora()
|
|
64
|
+
spinner.start('Getting available templates')
|
|
65
|
+
|
|
66
|
+
const templateList = await this.getTemplates(searchCriteria, orderByCriteria, templateRegistryConfig)
|
|
67
|
+
aioLogger.debug('templateList', JSON.stringify(templateList, null, 2))
|
|
68
|
+
spinner.succeed('Downloaded the list of templates')
|
|
69
|
+
|
|
70
|
+
if (templateList.length === 0) {
|
|
71
|
+
throw new Error('There are no templates that match the query for selection')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const { columns: terminalColumns } = terminalSize()
|
|
75
|
+
|
|
76
|
+
const colPadding = 3
|
|
77
|
+
const colWidths = [
|
|
78
|
+
Math.round(0.3 * terminalColumns) - colPadding,
|
|
79
|
+
Math.round(0.3 * terminalColumns) - colPadding,
|
|
80
|
+
Math.round(0.2 * terminalColumns) - colPadding,
|
|
81
|
+
Math.round(0.2 * terminalColumns) - colPadding]
|
|
82
|
+
|
|
83
|
+
const COLUMNS = {
|
|
84
|
+
COL_TEMPLATE: 'Template',
|
|
85
|
+
COL_DESCRIPTION: 'Description',
|
|
86
|
+
COL_EXTENSION_POINT: 'Extension Point',
|
|
87
|
+
COL_CATEGORIES: 'Categories'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const rows = templateList.map(template => {
|
|
91
|
+
const extensionPoint = template.extensions ? template.extensions.map(ext => ext.extensionPointId).join(',') : 'N/A'
|
|
92
|
+
const name = template.adobeRecommended ? `${template.name} *` : template.name
|
|
93
|
+
let disabled = false
|
|
94
|
+
if (template.apis && supportedServiceCodes) {
|
|
95
|
+
disabled = !template.apis.map(api => api.code).every(code => supportedServiceCodes.has(code))
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
value: template.name,
|
|
99
|
+
disabled,
|
|
100
|
+
[COLUMNS.COL_TEMPLATE]: name,
|
|
101
|
+
[COLUMNS.COL_DESCRIPTION]: template.description,
|
|
102
|
+
[COLUMNS.COL_EXTENSION_POINT]: extensionPoint,
|
|
103
|
+
[COLUMNS.COL_CATEGORIES]: template?.categories?.join(', ')
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
const promptName = 'select template'
|
|
107
|
+
|
|
108
|
+
inquirer.registerPrompt('table', inquirerTableCheckbox)
|
|
109
|
+
const answers = await inquirer
|
|
110
|
+
.prompt([
|
|
111
|
+
{
|
|
112
|
+
type: 'table',
|
|
113
|
+
name: promptName,
|
|
114
|
+
bottomContent: `* = recommended by Adobe; to learn more about the templates, go to ${hyperlinker('https://adobe.ly/templates', 'https://adobe.ly/templates')}`,
|
|
115
|
+
message: 'Choose the template(s) to install:',
|
|
116
|
+
style: { head: [], border: [] },
|
|
117
|
+
wordWrap: true,
|
|
118
|
+
wrapOnWordBoundary: false,
|
|
119
|
+
colWidths,
|
|
120
|
+
columns: [
|
|
121
|
+
{ name: COLUMNS.COL_TEMPLATE },
|
|
122
|
+
{ name: COLUMNS.COL_DESCRIPTION, wrapOnWordBoundary: true },
|
|
123
|
+
{ name: COLUMNS.COL_EXTENSION_POINT },
|
|
124
|
+
{ name: COLUMNS.COL_CATEGORIES, wrapOnWordBoundary: false }
|
|
125
|
+
],
|
|
126
|
+
rows
|
|
127
|
+
}
|
|
128
|
+
])
|
|
129
|
+
|
|
130
|
+
return answers[promptName]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Install the templates.
|
|
135
|
+
*
|
|
136
|
+
* @param {object} templateData the template data
|
|
137
|
+
* @param {boolean} [templateData.useDefaultValues=false] use default values when installing the template
|
|
138
|
+
* @param {boolean} [templateData.installConfig=true] process the install.yml of the template
|
|
139
|
+
* @param {boolean} [templateData.installNpm=true] run npm install after installing the template
|
|
140
|
+
* @param {object} [templateData.templateOptions=null] set the template options for installation
|
|
141
|
+
* @param {Array} templateData.templates the list of templates to install
|
|
142
|
+
*/
|
|
143
|
+
async installTemplates ({
|
|
144
|
+
useDefaultValues = false,
|
|
145
|
+
installConfig = true,
|
|
146
|
+
installNpm = true,
|
|
147
|
+
templateOptions = null,
|
|
148
|
+
templates = []
|
|
149
|
+
} = {}) {
|
|
150
|
+
const spinner = ora()
|
|
151
|
+
|
|
152
|
+
// install the templates in sequence
|
|
153
|
+
for (const template of templates) {
|
|
154
|
+
spinner.info(`Installing template ${template}`)
|
|
155
|
+
const installArgs = [template]
|
|
156
|
+
if (useDefaultValues) {
|
|
157
|
+
installArgs.push('--yes')
|
|
158
|
+
}
|
|
159
|
+
if (!installConfig) {
|
|
160
|
+
installArgs.push('--no-process-install-config')
|
|
161
|
+
}
|
|
162
|
+
if (!installNpm) {
|
|
163
|
+
installArgs.push('--no-install')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (templateOptions) {
|
|
167
|
+
if (typeof templateOptions !== 'object' || Array.isArray(templateOptions)) { // must be a non-array object
|
|
168
|
+
aioLogger.debug('malformed templateOptions', templateOptions)
|
|
169
|
+
throw new Error('The templateOptions is not a JavaScript object.')
|
|
170
|
+
}
|
|
171
|
+
const jsonString = JSON.stringify(templateOptions)
|
|
172
|
+
installArgs.push(`--template-options=${Buffer.from(jsonString).toString('base64')}`)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await this.config.runCommand('templates:install', installArgs)
|
|
176
|
+
spinner.succeed(`Installed template ${template}`)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** @private */
|
|
181
|
+
_uniqueArray (array) {
|
|
182
|
+
return Array.from(new Set(array))
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get templates by extension point ids.
|
|
187
|
+
*
|
|
188
|
+
* @param {Array<string>} extensionsToInstall an array of extension point ids to install.
|
|
189
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
190
|
+
* @returns {object} returns the result
|
|
191
|
+
*/
|
|
192
|
+
async getTemplatesByExtensionPointIds (extensionsToInstall, templateRegistryConfig = {}) {
|
|
193
|
+
const orderByCriteria = {
|
|
194
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const searchCriteria = {
|
|
198
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
199
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: extensionsToInstall
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const templates = await this.getTemplates(searchCriteria, orderByCriteria, templateRegistryConfig)
|
|
203
|
+
aioLogger.debug('templateList', JSON.stringify(templates, null, 2))
|
|
204
|
+
|
|
205
|
+
// check whether we got all extensions
|
|
206
|
+
const found = this._uniqueArray(templates
|
|
207
|
+
.map(t => t.extensions.map(e => e.extensionPointId)) // array of array of extensionPointIds
|
|
208
|
+
.filter(ids => extensionsToInstall.some(item => ids.includes(item)))
|
|
209
|
+
.flat()
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
const notFound = this._uniqueArray(extensionsToInstall).filter(ext => !found.includes(ext))
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
found,
|
|
216
|
+
notFound,
|
|
217
|
+
templates
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Install templates by extension point ids.
|
|
223
|
+
*
|
|
224
|
+
* @param {Array<string>} extensionsToInstall an array of extension point ids to install.
|
|
225
|
+
* @param {Array<string>} extensionsAlreadyImplemented an array of extension point ids that have already been implemented (to filter)
|
|
226
|
+
* @param {boolean} [useDefaultValues=false] use default values when installing the template
|
|
227
|
+
* @param {boolean} [installNpm=true] run npm install after installing the template
|
|
228
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
229
|
+
*/
|
|
230
|
+
async installTemplatesByExtensionPointIds (extensionsToInstall, extensionsAlreadyImplemented, useDefaultValues = false, installNpm = true, templateRegistryConfig = {}) {
|
|
231
|
+
// no prompt
|
|
232
|
+
const alreadyThere = extensionsToInstall.filter(i => extensionsAlreadyImplemented.includes(i))
|
|
233
|
+
if (alreadyThere.length > 0) {
|
|
234
|
+
throw new Error(`'${alreadyThere.join(', ')}' extension(s) are already implemented in this project.`)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const { found, notFound, templates } = await this.getTemplatesByExtensionPointIds(extensionsToInstall, templateRegistryConfig)
|
|
238
|
+
|
|
239
|
+
if (notFound.length > 0) {
|
|
240
|
+
this.error(`Extension(s) '${notFound.join(', ')}' not found in the Template Registry.`)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
this.log(`Extension(s) '${found.join(', ')}' found in the Template Registry. Installing...`)
|
|
244
|
+
await this.installTemplates({
|
|
245
|
+
useDefaultValues,
|
|
246
|
+
installNpm,
|
|
247
|
+
templates: templates.map(t => t.name)
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
TemplatesCommand.flags = {
|
|
253
|
+
...AddCommand.flags
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = TemplatesCommand
|
|
@@ -9,22 +9,19 @@ 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
|
|
13
|
-
const yeoman = require('yeoman-environment')
|
|
12
|
+
const TemplatesCommand = require('../../../TemplatesCommand')
|
|
14
13
|
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:add:action', { provider: 'debug' })
|
|
15
14
|
const { Flags } = require('@oclif/core')
|
|
16
|
-
const ora = require('ora')
|
|
17
15
|
const path = require('path')
|
|
18
|
-
const generators = require('@adobe/generator-aio-app')
|
|
19
|
-
const { servicesToGeneratorInput } = require('../../../lib/app-helper')
|
|
20
16
|
const aioConfigLoader = require('@adobe/aio-lib-core-config')
|
|
17
|
+
const TemplateRegistryAPI = require('@adobe/aio-lib-templates')
|
|
18
|
+
const inquirer = require('inquirer')
|
|
21
19
|
|
|
22
|
-
class AddActionCommand extends
|
|
20
|
+
class AddActionCommand extends TemplatesCommand {
|
|
23
21
|
async run () {
|
|
24
22
|
const { flags } = await this.parse(AddActionCommand)
|
|
25
23
|
|
|
26
24
|
aioLogger.debug(`add actions with flags: ${JSON.stringify(flags)}`)
|
|
27
|
-
const spinner = ora()
|
|
28
25
|
|
|
29
26
|
// guaranteed to have at least one, otherwise would throw in config load or in matching the ext name
|
|
30
27
|
const entries = Object.entries(this.getAppExtConfigs(flags))
|
|
@@ -35,33 +32,90 @@ class AddActionCommand extends AddCommand {
|
|
|
35
32
|
const config = entries[0][1]
|
|
36
33
|
|
|
37
34
|
const actionFolder = path.relative(config.root, config.actions.src)
|
|
38
|
-
|
|
39
35
|
const configData = this.getRuntimeManifestConfigFile(configName)
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
const projectOrgId = aioConfigLoader.get('project.org.id')
|
|
38
|
+
if (!projectOrgId) {
|
|
39
|
+
this.error(`Incomplete .aio configuration, please import a valid Adobe Developer Console configuration via \`${this.config.bin} app use\` first.`)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const consoleCLI = await this.getLibConsoleCLI()
|
|
43
|
+
const orgSupportedServices = await consoleCLI.getEnabledServicesForOrg(projectOrgId)
|
|
44
|
+
|
|
45
|
+
const templateOptions = {
|
|
46
|
+
'skip-prompt': flags.yes,
|
|
47
|
+
'action-folder': actionFolder,
|
|
48
|
+
'config-path': configData.file,
|
|
49
|
+
'full-key-to-manifest': configData.key
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const [searchCriteria, orderByCriteria] = await this.getSearchCriteria(orgSupportedServices)
|
|
53
|
+
const templates = await this.selectTemplates(searchCriteria, orderByCriteria, orgSupportedServices)
|
|
54
|
+
if (templates.length === 0) {
|
|
55
|
+
this.error('No action templates were chosen to be installed.')
|
|
56
|
+
} else {
|
|
57
|
+
await this.installTemplates({
|
|
58
|
+
useDefaultValues: flags.yes,
|
|
59
|
+
installNpm: flags.install,
|
|
60
|
+
templateOptions,
|
|
61
|
+
templates
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getSearchCriteria (orgSupportedServices) {
|
|
67
|
+
const choices = [
|
|
68
|
+
{
|
|
69
|
+
name: 'All Action Templates',
|
|
70
|
+
value: 'allActionTemplates',
|
|
71
|
+
checked: true
|
|
60
72
|
}
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
if (orgSupportedServices) {
|
|
76
|
+
choices.push({
|
|
77
|
+
name: 'Only Action Templates Supported By My Org',
|
|
78
|
+
value: 'orgActionTemplates',
|
|
79
|
+
checked: false
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const { components: selection } = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: 'list',
|
|
86
|
+
name: 'components',
|
|
87
|
+
message: 'What action templates do you want to search for?',
|
|
88
|
+
loop: false,
|
|
89
|
+
choices
|
|
90
|
+
}
|
|
91
|
+
])
|
|
92
|
+
|
|
93
|
+
const TEMPLATE_CATEGORIES = ['action', 'helper-template']
|
|
94
|
+
const searchCriteria = {
|
|
95
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
96
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_CATEGORIES]: TEMPLATE_CATEGORIES,
|
|
97
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NONE
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
switch (selection) {
|
|
101
|
+
case 'orgActionTemplates': {
|
|
102
|
+
const supportedServiceCodes = new Set(orgSupportedServices.map(s => `|${s.code}`)) // | symbol denotes an OR clause
|
|
103
|
+
searchCriteria[TemplateRegistryAPI.SEARCH_CRITERIA_APIS] = Array.from(supportedServiceCodes)
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
case 'allActionTemplates':
|
|
107
|
+
default:
|
|
108
|
+
break
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const { name: selectionLabel } = choices.find(item => item.value === selection)
|
|
112
|
+
|
|
113
|
+
// an optional OrderBy Criteria object
|
|
114
|
+
const orderByCriteria = {
|
|
115
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
116
|
+
}
|
|
63
117
|
|
|
64
|
-
|
|
118
|
+
return [searchCriteria, orderByCriteria, selection, selectionLabel]
|
|
65
119
|
}
|
|
66
120
|
}
|
|
67
121
|
|
|
@@ -80,7 +134,7 @@ AddActionCommand.flags = {
|
|
|
80
134
|
multiple: false,
|
|
81
135
|
parse: str => [str]
|
|
82
136
|
}),
|
|
83
|
-
...
|
|
137
|
+
...TemplatesCommand.flags
|
|
84
138
|
}
|
|
85
139
|
|
|
86
140
|
AddActionCommand.aliases = ['app:add:actions']
|
|
@@ -9,107 +9,57 @@ 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
|
|
13
|
-
const yeoman = require('yeoman-environment')
|
|
12
|
+
const TemplatesCommand = require('../../../TemplatesCommand')
|
|
14
13
|
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:add:action', { provider: 'debug' })
|
|
15
14
|
const { Flags } = require('@oclif/core')
|
|
16
|
-
const
|
|
15
|
+
const TemplateRegistryAPI = require('@adobe/aio-lib-templates')
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
const aioConfigLoader = require('@adobe/aio-lib-core-config')
|
|
20
|
-
const { implPromptChoices } = require('../../../lib/defaults')
|
|
21
|
-
const chalk = require('chalk')
|
|
22
|
-
|
|
23
|
-
class AddExtensionCommand extends AddCommand {
|
|
17
|
+
class AddExtensionCommand extends TemplatesCommand {
|
|
24
18
|
async run () {
|
|
25
19
|
const { flags } = await this.parse(AddExtensionCommand)
|
|
26
20
|
|
|
27
21
|
aioLogger.debug(`add extensions with flags: ${JSON.stringify(flags)}`)
|
|
28
|
-
const spinner = ora()
|
|
29
22
|
|
|
30
23
|
if (flags.yes && !flags.extension) {
|
|
31
24
|
this.error('--extension= must also be provided when using --yes')
|
|
32
25
|
}
|
|
33
26
|
|
|
34
27
|
const fullConfig = this.getFullConfig({ allowNoImpl: true })
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
await this.runCodeGenerators(flags, implementationsToAdd)
|
|
38
|
-
|
|
39
|
-
await this.runInstallPackages(flags, spinner)
|
|
28
|
+
const alreadyImplemented = fullConfig.implements
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const supportedServiceCodesInWorkspace = new Set(workspaceServices.map(s => s.code))
|
|
48
|
-
implementationsToAdd.forEach(i => {
|
|
49
|
-
const missingServices = i.requiredServices.filter(s => !supportedServiceCodesInWorkspace.has(s))
|
|
50
|
-
if (missingServices.length > 0) {
|
|
51
|
-
this.warn(`Please add missing services '${missingServices}' required by '${i.name}'`)
|
|
52
|
-
}
|
|
53
|
-
})
|
|
30
|
+
if (flags.extension) {
|
|
31
|
+
await this.installTemplatesByExtensionPointIds(flags.extension, alreadyImplemented, flags.yes, flags.install)
|
|
32
|
+
} else {
|
|
33
|
+
await this.selectExtensionsToInstall(alreadyImplemented, flags.yes, flags.install)
|
|
34
|
+
}
|
|
54
35
|
}
|
|
55
36
|
|
|
56
|
-
async
|
|
57
|
-
const
|
|
58
|
-
const availableChoices = implPromptChoices
|
|
59
|
-
const availableImplementations = availableChoices.map(i => i.value.name)
|
|
37
|
+
async selectExtensionsToInstall (alreadyImplemented, useDefaultValues, installNpm) {
|
|
38
|
+
const excludeExtensions = alreadyImplemented.map(e => `${TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NOT}${e}`)
|
|
60
39
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
throw new Error('All available extensions are already implemented in this project.')
|
|
40
|
+
const orderByCriteria = {
|
|
41
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
64
42
|
}
|
|
65
43
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (alreadyThere.length > 0) {
|
|
70
|
-
throw new Error(`'${alreadyThere}' is/are already implemented by this project`)
|
|
71
|
-
}
|
|
72
|
-
const invalid = flags.extension.filter(i => !availableImplementations.includes(i))
|
|
73
|
-
if (invalid.length > 0) {
|
|
74
|
-
throw new Error(`Invalid extension(s) '${invalid}', available implementations are '${availableImplementations}'`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return flags.extension.map(i => possibleChoices.find(c => c.value.name === i).value)
|
|
44
|
+
const searchCriteria = {
|
|
45
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
46
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: excludeExtensions
|
|
78
47
|
}
|
|
79
48
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return answers.res
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async runCodeGenerators (flags, implementations) {
|
|
93
|
-
const env = yeoman.createEnv()
|
|
94
|
-
// by default yeoman runs the install, we control installation from the app plugin
|
|
95
|
-
env.options = { skipInstall: true }
|
|
96
|
-
for (let i = 0; i < implementations.length; ++i) {
|
|
97
|
-
const implementation = implementations[i]
|
|
98
|
-
const gen = env.instantiate(implementation.generator,
|
|
99
|
-
{
|
|
100
|
-
options: {
|
|
101
|
-
'skip-prompt': flags.yes,
|
|
102
|
-
// no yeoman overwrite prompts
|
|
103
|
-
force: true
|
|
104
|
-
}
|
|
105
|
-
})
|
|
106
|
-
this.log(chalk.blue(chalk.bold(`Running generator for ${implementation.name}`)))
|
|
107
|
-
await env.runGenerator(gen)
|
|
49
|
+
const templates = await this.selectTemplates(searchCriteria, orderByCriteria)
|
|
50
|
+
if (templates.length === 0) {
|
|
51
|
+
this.error('No extensions were chosen to be installed.')
|
|
52
|
+
} else {
|
|
53
|
+
await this.installTemplates({
|
|
54
|
+
useDefaultValues,
|
|
55
|
+
installNpm,
|
|
56
|
+
templates
|
|
57
|
+
})
|
|
108
58
|
}
|
|
109
59
|
}
|
|
110
60
|
}
|
|
111
61
|
|
|
112
|
-
AddExtensionCommand.description = `Add new extensions
|
|
62
|
+
AddExtensionCommand.description = `Add new extensions to the project
|
|
113
63
|
`
|
|
114
64
|
AddExtensionCommand.flags = {
|
|
115
65
|
yes: Flags.boolean({
|
|
@@ -122,7 +72,7 @@ AddExtensionCommand.flags = {
|
|
|
122
72
|
char: 'e',
|
|
123
73
|
multiple: true
|
|
124
74
|
}),
|
|
125
|
-
...
|
|
75
|
+
...TemplatesCommand.flags
|
|
126
76
|
}
|
|
127
77
|
|
|
128
78
|
AddExtensionCommand.aliases = ['app:add:ext', 'app:add:extensions']
|
|
@@ -37,7 +37,7 @@ class AddServiceCommand extends BaseCommand {
|
|
|
37
37
|
// load console configuration from .aio and .env files
|
|
38
38
|
const projectConfig = config.get('project')
|
|
39
39
|
if (!projectConfig) {
|
|
40
|
-
this.error(
|
|
40
|
+
this.error(`Incomplete .aio configuration, please import a valid Adobe Developer Console configuration via \`${this.config.bin} app use\` first.`)
|
|
41
41
|
}
|
|
42
42
|
const orgId = projectConfig.org.id
|
|
43
43
|
const project = { name: projectConfig.name, id: projectConfig.id }
|
|
@@ -9,19 +9,14 @@ 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
|
|
13
|
-
const yeoman = require('yeoman-environment')
|
|
12
|
+
const TemplatesCommand = require('../../../TemplatesCommand')
|
|
14
13
|
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:add:web-assets', { provider: 'debug' })
|
|
15
14
|
const { Flags } = require('@oclif/core')
|
|
16
|
-
const
|
|
17
|
-
const generators = require('@adobe/generator-aio-app')
|
|
18
|
-
const aioConfigLoader = require('@adobe/aio-lib-core-config')
|
|
19
|
-
const { servicesToGeneratorInput } = require('../../../lib/app-helper')
|
|
15
|
+
const TemplateRegistryAPI = require('@adobe/aio-lib-templates')
|
|
20
16
|
|
|
21
|
-
class AddWebAssetsCommand extends
|
|
17
|
+
class AddWebAssetsCommand extends TemplatesCommand {
|
|
22
18
|
async run () {
|
|
23
19
|
const { flags } = await this.parse(AddWebAssetsCommand)
|
|
24
|
-
const spinner = ora()
|
|
25
20
|
aioLogger.debug(`add web-assets with flags: ${JSON.stringify(flags)}`)
|
|
26
21
|
|
|
27
22
|
const projectName = this.getFullConfig().packagejson.name
|
|
@@ -33,26 +28,32 @@ class AddWebAssetsCommand extends AddCommand {
|
|
|
33
28
|
const config = entries[0][1]
|
|
34
29
|
const webSrcFolder = config.web.src
|
|
35
30
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const env = yeoman.createEnv()
|
|
42
|
-
// by default yeoman runs the install, we control installation from the app plugin
|
|
43
|
-
env.options = { skipInstall: true }
|
|
44
|
-
const gen = env.instantiate(generators['add-web-assets'], {
|
|
45
|
-
options: {
|
|
46
|
-
'skip-prompt': flags.yes,
|
|
47
|
-
'project-name': projectName,
|
|
48
|
-
'web-src-folder': webSrcFolder,
|
|
49
|
-
'adobe-services': servicesToGeneratorInput(workspaceServices)
|
|
50
|
-
// force: true
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
await env.runGenerator(gen)
|
|
31
|
+
const templateOptions = {
|
|
32
|
+
'skip-prompt': flags.yes,
|
|
33
|
+
'project-name': projectName,
|
|
34
|
+
'web-src-folder': webSrcFolder
|
|
35
|
+
}
|
|
54
36
|
|
|
55
|
-
|
|
37
|
+
const TEMPLATE_CATEGORIES = ['ui', 'helper-template']
|
|
38
|
+
const searchCriteria = {
|
|
39
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
40
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_CATEGORIES]: TEMPLATE_CATEGORIES,
|
|
41
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NONE
|
|
42
|
+
}
|
|
43
|
+
const orderByCriteria = {
|
|
44
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
45
|
+
}
|
|
46
|
+
const templates = await this.selectTemplates(searchCriteria, orderByCriteria)
|
|
47
|
+
if (templates.length === 0) {
|
|
48
|
+
this.error('No web-asset templates were chosen to be installed.')
|
|
49
|
+
} else {
|
|
50
|
+
await this.installTemplates({
|
|
51
|
+
useDefaultValues: flags.yes,
|
|
52
|
+
installNpm: flags.install,
|
|
53
|
+
templateOptions,
|
|
54
|
+
templates
|
|
55
|
+
})
|
|
56
|
+
}
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -71,7 +72,7 @@ AddWebAssetsCommand.flags = {
|
|
|
71
72
|
multiple: false,
|
|
72
73
|
parse: str => [str]
|
|
73
74
|
}),
|
|
74
|
-
...
|
|
75
|
+
...TemplatesCommand.flags
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
AddWebAssetsCommand.args = []
|
|
@@ -26,8 +26,7 @@ class Build extends BaseCommand {
|
|
|
26
26
|
// cli input
|
|
27
27
|
const { flags } = await this.parse(Build)
|
|
28
28
|
// flags
|
|
29
|
-
flags['web-assets'] = flags['web-assets'] && !flags
|
|
30
|
-
flags.actions = flags.actions && !flags['skip-actions']
|
|
29
|
+
flags['web-assets'] = flags['web-assets'] && !flags.action
|
|
31
30
|
|
|
32
31
|
const buildConfigs = this.getAppExtConfigs(flags)
|
|
33
32
|
|
|
@@ -144,15 +143,6 @@ This will always force a rebuild unless --no-force-build is set.
|
|
|
144
143
|
|
|
145
144
|
Build.flags = {
|
|
146
145
|
...BaseCommand.flags,
|
|
147
|
-
'skip-static': Flags.boolean({
|
|
148
|
-
description: '[deprecated] Please use --no-web-assets'
|
|
149
|
-
}),
|
|
150
|
-
'skip-web-assets': Flags.boolean({
|
|
151
|
-
description: '[deprecated] Please use --no-web-assets'
|
|
152
|
-
}),
|
|
153
|
-
'skip-actions': Flags.boolean({
|
|
154
|
-
description: '[deprecated] Please use --no-actions'
|
|
155
|
-
}),
|
|
156
146
|
actions: Flags.boolean({
|
|
157
147
|
description: '[default: true] Build actions if any',
|
|
158
148
|
default: true,
|