@adobe/aio-cli-plugin-app 9.1.0 → 9.2.0-pre.2022-09-27.805ee90c
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 +105 -687
- package/bin/run +5 -2
- package/oclif.manifest.json +1 -1
- package/package.json +14 -10
- package/schema/config.schema.json +22 -2
- package/src/AddCommand.js +1 -7
- package/src/TemplatesCommand.js +246 -0
- package/src/commands/app/add/action.js +80 -31
- package/src/commands/app/add/extension.js +27 -77
- package/src/commands/app/add/web-assets.js +29 -27
- package/src/commands/app/delete/ci.js +25 -10
- package/src/commands/app/delete/extension.js +7 -8
- package/src/commands/app/deploy.js +25 -3
- package/src/commands/app/init.js +165 -144
- package/src/commands/app/list/extension-points.js +15 -5
- package/src/commands/app/list/extension.js +22 -21
- package/src/commands/app/run.js +1 -1
- package/src/lib/defaults.js +1 -41
|
@@ -0,0 +1,246 @@
|
|
|
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 {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
52
|
+
* @returns {Array<string>} an array of selected template module name(s)
|
|
53
|
+
*/
|
|
54
|
+
async selectTemplates (searchCriteria, orderByCriteria, templateRegistryConfig = {}) {
|
|
55
|
+
aioLogger.debug('searchCriteria', JSON.stringify(searchCriteria, null, 2))
|
|
56
|
+
aioLogger.debug('orderByCriteria', JSON.stringify(orderByCriteria, null, 2))
|
|
57
|
+
|
|
58
|
+
const spinner = ora()
|
|
59
|
+
spinner.start('Getting available templates')
|
|
60
|
+
|
|
61
|
+
const templateList = await this.getTemplates(searchCriteria, orderByCriteria, templateRegistryConfig)
|
|
62
|
+
aioLogger.debug('templateList', JSON.stringify(templateList, null, 2))
|
|
63
|
+
spinner.succeed('Downloaded the list of templates')
|
|
64
|
+
|
|
65
|
+
if (templateList.length === 0) {
|
|
66
|
+
throw new Error('There are no templates that match the query for selection')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { columns: terminalColumns } = terminalSize()
|
|
70
|
+
|
|
71
|
+
const colPadding = 3
|
|
72
|
+
const colWidths = [
|
|
73
|
+
Math.round(0.3 * terminalColumns) - colPadding,
|
|
74
|
+
Math.round(0.3 * terminalColumns) - colPadding,
|
|
75
|
+
Math.round(0.2 * terminalColumns) - colPadding,
|
|
76
|
+
Math.round(0.2 * terminalColumns) - colPadding]
|
|
77
|
+
|
|
78
|
+
const COLUMNS = {
|
|
79
|
+
COL_TEMPLATE: 'Template',
|
|
80
|
+
COL_DESCRIPTION: 'Description',
|
|
81
|
+
COL_EXTENSION_POINT: 'Extension Point',
|
|
82
|
+
COL_CATEGORIES: 'Categories'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const rows = templateList.map(template => {
|
|
86
|
+
const extensionPoint = template.extensions ? template.extensions.map(ext => ext.extensionPointId).join(',') : 'N/A'
|
|
87
|
+
const name = template.adobeRecommended ? `${template.name} *` : template.name
|
|
88
|
+
return {
|
|
89
|
+
value: template.name,
|
|
90
|
+
[COLUMNS.COL_TEMPLATE]: name,
|
|
91
|
+
[COLUMNS.COL_DESCRIPTION]: template.description,
|
|
92
|
+
[COLUMNS.COL_EXTENSION_POINT]: extensionPoint,
|
|
93
|
+
[COLUMNS.COL_CATEGORIES]: template?.categories?.join(', ')
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
const promptName = 'select template'
|
|
97
|
+
|
|
98
|
+
inquirer.registerPrompt('table', inquirerTableCheckbox)
|
|
99
|
+
const answers = await inquirer
|
|
100
|
+
.prompt([
|
|
101
|
+
{
|
|
102
|
+
type: 'table',
|
|
103
|
+
name: promptName,
|
|
104
|
+
bottomContent: `* = recommended by Adobe; to learn more about the templates, go to ${hyperlinker('https://adobe.ly/templates', 'https://adobe.ly/templates')}`,
|
|
105
|
+
message: 'Choose the template(s) to install:',
|
|
106
|
+
style: { head: [], border: [] },
|
|
107
|
+
wordWrap: true,
|
|
108
|
+
wrapOnWordBoundary: false,
|
|
109
|
+
colWidths,
|
|
110
|
+
columns: [
|
|
111
|
+
{ name: COLUMNS.COL_TEMPLATE },
|
|
112
|
+
{ name: COLUMNS.COL_DESCRIPTION, wrapOnWordBoundary: true },
|
|
113
|
+
{ name: COLUMNS.COL_EXTENSION_POINT },
|
|
114
|
+
{ name: COLUMNS.COL_CATEGORIES, wrapOnWordBoundary: false }
|
|
115
|
+
],
|
|
116
|
+
rows
|
|
117
|
+
}
|
|
118
|
+
])
|
|
119
|
+
|
|
120
|
+
return answers[promptName]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Install the templates.
|
|
125
|
+
*
|
|
126
|
+
* @param {object} templateData the template data
|
|
127
|
+
* @param {boolean} [templateData.useDefaultValues=false] use default values when installing the template
|
|
128
|
+
* @param {boolean} [templateData.installConfig=true] process the install.yml of the template
|
|
129
|
+
* @param {boolean} [templateData.installNpm=true] run npm install after installing the template
|
|
130
|
+
* @param {object} [templateData.templateOptions=null] set the template options for installation
|
|
131
|
+
* @param {Array} templateData.templates the list of templates to install
|
|
132
|
+
*/
|
|
133
|
+
async installTemplates ({
|
|
134
|
+
useDefaultValues = false,
|
|
135
|
+
installConfig = true,
|
|
136
|
+
installNpm = true,
|
|
137
|
+
templateOptions = null,
|
|
138
|
+
templates = []
|
|
139
|
+
} = {}) {
|
|
140
|
+
const spinner = ora()
|
|
141
|
+
|
|
142
|
+
// install the templates in sequence
|
|
143
|
+
for (const template of templates) {
|
|
144
|
+
spinner.info(`Installing template ${template}`)
|
|
145
|
+
const installArgs = [template]
|
|
146
|
+
if (useDefaultValues) {
|
|
147
|
+
installArgs.push('--yes')
|
|
148
|
+
}
|
|
149
|
+
if (!installConfig) {
|
|
150
|
+
installArgs.push('--no-process-install-config')
|
|
151
|
+
}
|
|
152
|
+
if (!installNpm) {
|
|
153
|
+
installArgs.push('--no-install')
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (templateOptions) {
|
|
157
|
+
if (typeof templateOptions !== 'object' || Array.isArray(templateOptions)) { // must be a non-array object
|
|
158
|
+
aioLogger.debug('malformed templateOptions', templateOptions)
|
|
159
|
+
throw new Error('The templateOptions is not a JavaScript object.')
|
|
160
|
+
}
|
|
161
|
+
const jsonString = JSON.stringify(templateOptions)
|
|
162
|
+
installArgs.push(`--template-options=${Buffer.from(jsonString).toString('base64')}`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
await this.config.runCommand('templates:install', installArgs)
|
|
166
|
+
spinner.succeed(`Installed template ${template}`)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** @private */
|
|
171
|
+
_uniqueArray (array) {
|
|
172
|
+
return Array.from(new Set(array))
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get templates by extension point ids.
|
|
177
|
+
*
|
|
178
|
+
* @param {Array<string>} extensionsToInstall an array of extension point ids to install.
|
|
179
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
180
|
+
* @returns {object} returns the result
|
|
181
|
+
*/
|
|
182
|
+
async getTemplatesByExtensionPointIds (extensionsToInstall, templateRegistryConfig = {}) {
|
|
183
|
+
const orderByCriteria = {
|
|
184
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const searchCriteria = {
|
|
188
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
189
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: extensionsToInstall
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const templates = await this.getTemplates(searchCriteria, orderByCriteria, templateRegistryConfig)
|
|
193
|
+
aioLogger.debug('templateList', JSON.stringify(templates, null, 2))
|
|
194
|
+
|
|
195
|
+
// check whether we got all extensions
|
|
196
|
+
const found = this._uniqueArray(templates
|
|
197
|
+
.map(t => t.extensions.map(e => e.extensionPointId)) // array of array of extensionPointIds
|
|
198
|
+
.filter(ids => extensionsToInstall.some(item => ids.includes(item)))
|
|
199
|
+
.flat()
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
const notFound = this._uniqueArray(extensionsToInstall).filter(ext => !found.includes(ext))
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
found,
|
|
206
|
+
notFound,
|
|
207
|
+
templates
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Install templates by extension point ids.
|
|
213
|
+
*
|
|
214
|
+
* @param {Array<string>} extensionsToInstall an array of extension point ids to install.
|
|
215
|
+
* @param {Array<string>} extensionsAlreadyImplemented an array of extension point ids that have already been implemented (to filter)
|
|
216
|
+
* @param {boolean} [useDefaultValues=false] use default values when installing the template
|
|
217
|
+
* @param {boolean} [installNpm=true] run npm install after installing the template
|
|
218
|
+
* @param {object} [templateRegistryConfig={}] the optional Template Registry API config
|
|
219
|
+
*/
|
|
220
|
+
async installTemplatesByExtensionPointIds (extensionsToInstall, extensionsAlreadyImplemented, useDefaultValues = false, installNpm = true, templateRegistryConfig = {}) {
|
|
221
|
+
// no prompt
|
|
222
|
+
const alreadyThere = extensionsToInstall.filter(i => extensionsAlreadyImplemented.includes(i))
|
|
223
|
+
if (alreadyThere.length > 0) {
|
|
224
|
+
throw new Error(`'${alreadyThere.join(', ')}' extension(s) are already implemented in this project.`)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const { found, notFound, templates } = await this.getTemplatesByExtensionPointIds(extensionsToInstall, templateRegistryConfig)
|
|
228
|
+
|
|
229
|
+
if (notFound.length > 0) {
|
|
230
|
+
this.error(`Extension(s) '${notFound.join(', ')}' not found in the Template Registry.`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this.log(`Extension(s) '${found.join(', ')}' found in the Template Registry. Installing...`)
|
|
234
|
+
await this.installTemplates({
|
|
235
|
+
useDefaultValues,
|
|
236
|
+
installNpm,
|
|
237
|
+
templates: templates.map(t => t.name)
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
TemplatesCommand.flags = {
|
|
243
|
+
...AddCommand.flags
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
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,85 @@ 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
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
const consoleCLI = await this.getLibConsoleCLI()
|
|
38
|
+
const supportedOrgServices = await consoleCLI.getEnabledServicesForOrg(aioConfigLoader.get('project.org.id'))
|
|
39
|
+
|
|
40
|
+
const templateOptions = {
|
|
41
|
+
'skip-prompt': flags.yes,
|
|
42
|
+
'action-folder': actionFolder,
|
|
43
|
+
'config-path': configData.file,
|
|
44
|
+
'full-key-to-manifest': configData.key
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const [searchCriteria, orderByCriteria] = await this.getSearchCriteria(supportedOrgServices)
|
|
48
|
+
const templates = await this.selectTemplates(searchCriteria, orderByCriteria)
|
|
49
|
+
if (templates.length === 0) {
|
|
50
|
+
this.error('No action templates were chosen to be installed.')
|
|
51
|
+
} else {
|
|
52
|
+
await this.installTemplates({
|
|
53
|
+
useDefaultValues: flags.yes,
|
|
54
|
+
installNpm: flags.install,
|
|
55
|
+
templateOptions,
|
|
56
|
+
templates
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getSearchCriteria (orgSupportedServices) {
|
|
62
|
+
const choices = [
|
|
63
|
+
{
|
|
64
|
+
name: 'All Action Templates',
|
|
65
|
+
value: 'allActionTemplates',
|
|
66
|
+
checked: true
|
|
60
67
|
}
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
if (orgSupportedServices) {
|
|
71
|
+
choices.push({
|
|
72
|
+
name: 'Only Action Templates Supported By My Org',
|
|
73
|
+
value: 'orgActionTemplates',
|
|
74
|
+
checked: false
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { components: selection } = await inquirer.prompt([
|
|
79
|
+
{
|
|
80
|
+
type: 'list',
|
|
81
|
+
name: 'components',
|
|
82
|
+
message: 'What action templates do you want to search for?',
|
|
83
|
+
loop: false,
|
|
84
|
+
choices
|
|
85
|
+
}
|
|
86
|
+
])
|
|
87
|
+
|
|
88
|
+
const TEMPLATE_CATEGORIES = ['action', 'helper-template']
|
|
89
|
+
const searchCriteria = {
|
|
90
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED,
|
|
91
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_CATEGORIES]: TEMPLATE_CATEGORIES,
|
|
92
|
+
[TemplateRegistryAPI.SEARCH_CRITERIA_EXTENSIONS]: TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NONE
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
switch (selection) {
|
|
96
|
+
case 'orgActionTemplates': {
|
|
97
|
+
const supportedServiceCodes = new Set(orgSupportedServices.map(s => s.code))
|
|
98
|
+
searchCriteria[TemplateRegistryAPI.SEARCH_CRITERIA_APIS] = Array.from(supportedServiceCodes)
|
|
99
|
+
}
|
|
100
|
+
break
|
|
101
|
+
case 'allActionTemplates':
|
|
102
|
+
default:
|
|
103
|
+
break
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const { name: selectionLabel } = choices.find(item => item.value === selection)
|
|
107
|
+
|
|
108
|
+
// an optional OrderBy Criteria object
|
|
109
|
+
const orderByCriteria = {
|
|
110
|
+
[TemplateRegistryAPI.ORDER_BY_CRITERIA_PUBLISH_DATE]: TemplateRegistryAPI.ORDER_BY_CRITERIA_SORT_DESC
|
|
111
|
+
}
|
|
63
112
|
|
|
64
|
-
|
|
113
|
+
return [searchCriteria, orderByCriteria, selection, selectionLabel]
|
|
65
114
|
}
|
|
66
115
|
}
|
|
67
116
|
|
|
@@ -80,7 +129,7 @@ AddActionCommand.flags = {
|
|
|
80
129
|
multiple: false,
|
|
81
130
|
parse: str => [str]
|
|
82
131
|
}),
|
|
83
|
-
...
|
|
132
|
+
...TemplatesCommand.flags
|
|
84
133
|
}
|
|
85
134
|
|
|
86
135
|
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']
|
|
@@ -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,33 @@ 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
|
-
|
|
31
|
+
const templateOptions = {
|
|
32
|
+
'skip-prompt': flags.yes,
|
|
33
|
+
'project-name': projectName,
|
|
34
|
+
'web-src-folder': webSrcFolder
|
|
35
|
+
}
|
|
40
36
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// force: true
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
await env.runGenerator(gen)
|
|
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
|
+
}
|
|
54
46
|
|
|
55
|
-
await this.
|
|
47
|
+
const templates = await this.selectTemplates(searchCriteria, orderByCriteria)
|
|
48
|
+
if (templates.length === 0) {
|
|
49
|
+
this.error('No web-asset templates were chosen to be installed.')
|
|
50
|
+
} else {
|
|
51
|
+
await this.installTemplates({
|
|
52
|
+
useDefaultValues: flags.yes,
|
|
53
|
+
installNpm: flags.install,
|
|
54
|
+
templateOptions,
|
|
55
|
+
templates
|
|
56
|
+
})
|
|
57
|
+
}
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
|
|
@@ -71,7 +73,7 @@ AddWebAssetsCommand.flags = {
|
|
|
71
73
|
multiple: false,
|
|
72
74
|
parse: str => [str]
|
|
73
75
|
}),
|
|
74
|
-
...
|
|
76
|
+
...TemplatesCommand.flags
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
AddWebAssetsCommand.args = []
|
|
@@ -10,10 +10,16 @@ governing permissions and limitations under the License.
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const BaseCommand = require('../../../BaseCommand')
|
|
13
|
-
const
|
|
13
|
+
const path = require('path')
|
|
14
14
|
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:add:action', { provider: 'debug' })
|
|
15
15
|
const { Flags } = require('@oclif/core')
|
|
16
|
-
const
|
|
16
|
+
const fs = require('fs-extra')
|
|
17
|
+
|
|
18
|
+
const { constants } = require('@adobe/generator-app-common-lib')
|
|
19
|
+
const { ciDirName } = constants
|
|
20
|
+
const DEPLOY_PROD_FILENAME = '/workflows/deploy_prod.yml'
|
|
21
|
+
const DEPLOY_STAGE_FILENAME = '/workflows/deploy_stage.yml'
|
|
22
|
+
const TEST_PR_FILENAME = '/workflows/pr_test.yml'
|
|
17
23
|
|
|
18
24
|
class DeleteCICommand extends BaseCommand {
|
|
19
25
|
async run () {
|
|
@@ -21,15 +27,24 @@ class DeleteCICommand extends BaseCommand {
|
|
|
21
27
|
|
|
22
28
|
aioLogger.debug(`deleting CI files from the project, using flags: ${JSON.stringify(flags)}`)
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
if (!fs.existsSync(ciDirName)) {
|
|
31
|
+
this.error('you have no CI in your project')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const resConfirm = await this.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'confirm',
|
|
37
|
+
name: 'deleteCI',
|
|
38
|
+
message: `Please confirm the deletion of all your CI files in '${ciDirName}'`,
|
|
39
|
+
when: !flags.yes
|
|
30
40
|
}
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
])
|
|
42
|
+
if (flags.yes || resConfirm.deleteCI) {
|
|
43
|
+
fs.removeSync(path.join(ciDirName, DEPLOY_PROD_FILENAME))
|
|
44
|
+
fs.removeSync(path.join(ciDirName, DEPLOY_STAGE_FILENAME))
|
|
45
|
+
fs.removeSync(path.join(ciDirName, TEST_PR_FILENAME))
|
|
46
|
+
this.log('✔ deleted CI files locally')
|
|
47
|
+
}
|
|
33
48
|
}
|
|
34
49
|
}
|
|
35
50
|
|