@adobe/aio-cli-plugin-app 10.3.1 → 10.4.0-pre.2023-07-10.283ea03c

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.
Files changed (33) hide show
  1. package/README.md +3 -2
  2. package/bin/openwhisk-standalone-config/get-runtimes.js +2 -1
  3. package/bin/openwhisk-standalone-config/runtimes.json +13 -5
  4. package/oclif.manifest.json +14 -1
  5. package/package.json +5 -4
  6. package/schema/index.js +1 -2
  7. package/src/BaseCommand.js +10 -10
  8. package/src/commands/app/add/action.js +2 -2
  9. package/src/commands/app/add/event.js +2 -2
  10. package/src/commands/app/add/extension.js +1 -1
  11. package/src/commands/app/add/web-assets.js +2 -2
  12. package/src/commands/app/build.js +6 -6
  13. package/src/commands/app/config/get/log-forwarding/errors.js +1 -1
  14. package/src/commands/app/config/get/log-forwarding.js +1 -1
  15. package/src/commands/app/config/set/log-forwarding.js +1 -1
  16. package/src/commands/app/delete/action.js +13 -10
  17. package/src/commands/app/delete/extension.js +7 -7
  18. package/src/commands/app/delete/web-assets.js +1 -1
  19. package/src/commands/app/deploy.js +19 -15
  20. package/src/commands/app/get-url.js +1 -1
  21. package/src/commands/app/info.js +1 -1
  22. package/src/commands/app/install.js +4 -2
  23. package/src/commands/app/list/extension-points.js +1 -1
  24. package/src/commands/app/list/extension.js +1 -1
  25. package/src/commands/app/logs.js +1 -1
  26. package/src/commands/app/pack.js +2 -1
  27. package/src/commands/app/run.js +4 -4
  28. package/src/commands/app/test.js +1 -1
  29. package/src/commands/app/undeploy.js +9 -7
  30. package/src/lib/app-helper.js +40 -2
  31. package/src/lib/build-actions.js +4 -4
  32. package/src/lib/deploy-actions.js +6 -6
  33. package/schema/app.config.yaml.schema.json +0 -157
package/README.md CHANGED
@@ -71,7 +71,7 @@ DESCRIPTION
71
71
  Create, run, test, and deploy Adobe I/O Apps
72
72
  ```
73
73
 
74
- _See code: [src/commands/app/index.js](https://github.com/adobe/aio-cli-plugin-app/blob/10.3.1/src/commands/app/index.js)_
74
+ _See code: [src/commands/app/index.js](https://github.com/adobe/aio-cli-plugin-app/blob/10.4.0-pre.2023-07-10.283ea03c/src/commands/app/index.js)_
75
75
 
76
76
  ## `aio app add`
77
77
 
@@ -415,7 +415,7 @@ Build and deploy an Adobe I/O App
415
415
  USAGE
416
416
  $ aio app deploy [-v] [--version] [--actions | -a <value>] [--web-assets] [--force-build | ] [--content-hash]
417
417
  [--web-optimize] [-e <value> | ] [--build] [--open] [--force-deploy] [--force-publish | | --publish]
418
- [--log-forwarding-update]
418
+ [--force-events ] [--log-forwarding-update]
419
419
 
420
420
  FLAGS
421
421
  -a, --action=<value>... Deploy only a specific action, the flags can be specified multiple times, this will set
@@ -428,6 +428,7 @@ FLAGS
428
428
  --[no-]force-build [default: true] Force a build even if one already exists
429
429
  --force-deploy [default: false] Force deploy changes, regardless of production Workspace being
430
430
  published in Exchange.
431
+ --[no-]force-events [default: false] Force event registrations and overwrite any previous registrations
431
432
  --force-publish [default: false] Force publish extension(s) to Exchange, delete previously published
432
433
  extension points
433
434
  --[no-]log-forwarding-update [default: true] Update log forwarding configuration on server
@@ -17,9 +17,10 @@ const DOCKER_REPOS = { // repo-name:kind
17
17
  'adobe-action-nodejs-v12': 'nodejs:12',
18
18
  'adobe-action-nodejs-v14': 'nodejs:14',
19
19
  'adobe-action-nodejs-v16': 'nodejs:16',
20
+ 'adobe-action-nodejs-v18': 'nodejs:18'
20
21
  }
21
22
 
22
- const DEFAULT_KIND = 'nodejs:16'
23
+ const DEFAULT_KIND = 'nodejs:18'
23
24
 
24
25
  async function main() {
25
26
  const nodejs = []
@@ -6,7 +6,7 @@
6
6
  "image": {
7
7
  "prefix": "adobeapiplatform",
8
8
  "name": "adobe-action-nodejs-v10",
9
- "tag": "3.0.32"
9
+ "tag": "3.0.37"
10
10
  }
11
11
  },
12
12
  {
@@ -14,7 +14,7 @@
14
14
  "image": {
15
15
  "prefix": "adobeapiplatform",
16
16
  "name": "adobe-action-nodejs-v12",
17
- "tag": "3.0.32"
17
+ "tag": "3.0.37"
18
18
  }
19
19
  },
20
20
  {
@@ -22,16 +22,24 @@
22
22
  "image": {
23
23
  "prefix": "adobeapiplatform",
24
24
  "name": "adobe-action-nodejs-v14",
25
- "tag": "3.0.32"
25
+ "tag": "3.0.37"
26
26
  }
27
27
  },
28
28
  {
29
29
  "kind": "nodejs:16",
30
- "default": true,
31
30
  "image": {
32
31
  "prefix": "adobeapiplatform",
33
32
  "name": "adobe-action-nodejs-v16",
34
- "tag": "3.0.32"
33
+ "tag": "3.0.37"
34
+ }
35
+ },
36
+ {
37
+ "kind": "nodejs:18",
38
+ "default": true,
39
+ "image": {
40
+ "prefix": "adobeapiplatform",
41
+ "name": "adobe-action-nodejs-v18",
42
+ "tag": "3.0.37"
35
43
  }
36
44
  }
37
45
  ]
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "10.3.1",
2
+ "version": "10.4.0-pre.2023-07-10.283ea03c",
3
3
  "commands": {
4
4
  "app:build": {
5
5
  "id": "app:build",
@@ -232,6 +232,19 @@
232
232
  "publish"
233
233
  ]
234
234
  },
235
+ "force-events": {
236
+ "name": "force-events",
237
+ "type": "boolean",
238
+ "description": "[default: false] Force event registrations and overwrite any previous registrations",
239
+ "allowNo": true,
240
+ "dependsOn": [
241
+ "feature-event-hooks"
242
+ ],
243
+ "exclusive": [
244
+ "action",
245
+ "publish"
246
+ ]
247
+ },
235
248
  "log-forwarding-update": {
236
249
  "name": "log-forwarding-update",
237
250
  "type": "boolean",
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@adobe/aio-cli-plugin-app",
3
3
  "description": "Create, Build and Deploy Adobe I/O Applications",
4
- "version": "10.3.1",
4
+ "version": "10.4.0-pre.2023-07-10.283ea03c",
5
5
  "author": "Adobe Inc.",
6
6
  "bugs": "https://github.com/adobe/aio-cli-plugin-app/issues",
7
7
  "dependencies": {
8
- "@adobe/aio-cli-lib-app-config": "^1.0.1",
8
+ "@adobe/aio-cli-lib-app-config": "next",
9
9
  "@adobe/aio-cli-lib-console": "^4.1.0",
10
10
  "@adobe/aio-lib-core-config": "^3.0.0",
11
11
  "@adobe/aio-lib-core-logging": "^2.0.0",
@@ -102,5 +102,6 @@
102
102
  },
103
103
  "bin": {
104
104
  "aio-next": "./bin/run"
105
- }
106
- }
105
+ },
106
+ "prereleaseSha": "283ea03ce635f35a5ed9c2d75e3ae837246970c0"
107
+ }
package/schema/index.js CHANGED
@@ -10,10 +10,9 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- const { USER_CONFIG_FILE, DEPLOY_CONFIG_FILE, IMPORT_CONFIG_FILE } = require('../src/lib/defaults')
13
+ const { DEPLOY_CONFIG_FILE, IMPORT_CONFIG_FILE } = require('../src/lib/defaults')
14
14
 
15
15
  module.exports = {
16
16
  [IMPORT_CONFIG_FILE]: require('./config.schema.json'),
17
- [USER_CONFIG_FILE]: require('./app.config.yaml.schema.json'),
18
17
  [DEPLOY_CONFIG_FILE]: require('./deploy.yaml.schema.json')
19
18
  }
@@ -14,7 +14,7 @@ const chalk = require('chalk')
14
14
  const coreConfig = require('@adobe/aio-lib-core-config')
15
15
  const DEFAULT_LAUNCH_PREFIX = 'https://experience.adobe.com/?devMode=true#/custom-apps/?localDevUrl='
16
16
  const STAGE_LAUNCH_PREFIX = 'https://experience-stage.adobe.com/?devMode=true#/custom-apps/?localDevUrl='
17
- const loadConfig = require('@adobe/aio-cli-lib-app-config')
17
+ const libAppConfig = require('@adobe/aio-cli-lib-app-config')
18
18
  const inquirer = require('inquirer')
19
19
  const { CONSOLE_API_KEYS, APPLICATION_CONFIG_KEY, EXTENSIONS_CONFIG_KEY } = require('./lib/defaults')
20
20
  const { getCliInfo } = require('./lib/app-helper')
@@ -67,8 +67,8 @@ class BaseCommand extends Command {
67
67
  LibConsoleCLI.cleanStdOut()
68
68
  }
69
69
 
70
- getAppExtConfigs (flags, options = {}) {
71
- const all = this.getFullConfig(options).all
70
+ async getAppExtConfigs (flags, options = {}) {
71
+ const all = (await this.getFullConfig(options)).all
72
72
 
73
73
  // default case: no flags, return all
74
74
  let ret = all
@@ -98,25 +98,25 @@ class BaseCommand extends Command {
98
98
  return ret
99
99
  }
100
100
 
101
- getRuntimeManifestConfigFile (implName) {
101
+ async getRuntimeManifestConfigFile (implName) {
102
102
  let configKey
103
103
  if (implName === APPLICATION_CONFIG_KEY) {
104
104
  configKey = APPLICATION_CONFIG_KEY
105
105
  } else {
106
106
  configKey = `${EXTENSIONS_CONFIG_KEY}.${implName}`
107
107
  }
108
- let configData = this.getConfigFileForKey(`${configKey}.runtimeManifest`)
108
+ let configData = await this.getConfigFileForKey(`${configKey}.runtimeManifest`)
109
109
  if (!configData.file) {
110
110
  // first action manifest is not defined
111
- configData = this.getConfigFileForKey(`${configKey}`)
111
+ configData = await this.getConfigFileForKey(`${configKey}`)
112
112
  configData.key = configData.key + '.runtimeManifest'
113
113
  }
114
114
  return configData
115
115
  }
116
116
 
117
- getConfigFileForKey (fullKey) {
117
+ async getConfigFileForKey (fullKey) {
118
118
  // NOTE: the index returns undefined if the key is loaded from a legacy configuration file
119
- const fullConfig = this.getFullConfig()
119
+ const fullConfig = await this.getFullConfig()
120
120
  // full key like 'extensions.dx/excshell/1.runtimeManifest'
121
121
  // returns { key: relKey, file: configFile}
122
122
  const configData = fullConfig.includeIndex[fullKey]
@@ -128,9 +128,9 @@ class BaseCommand extends Command {
128
128
  return configData || {}
129
129
  }
130
130
 
131
- getFullConfig (options = {}) {
131
+ async getFullConfig (options = {}) {
132
132
  if (!this.appConfig) {
133
- this.appConfig = loadConfig(options)
133
+ this.appConfig = await libAppConfig.load(options)
134
134
  }
135
135
  return this.appConfig
136
136
  }
@@ -24,7 +24,7 @@ class AddActionCommand extends TemplatesCommand {
24
24
  aioLogger.debug(`add actions with flags: ${JSON.stringify(flags)}`)
25
25
 
26
26
  // guaranteed to have at least one, otherwise would throw in config load or in matching the ext name
27
- const entries = Object.entries(this.getAppExtConfigs(flags))
27
+ const entries = Object.entries(await this.getAppExtConfigs(flags))
28
28
  if (entries.length > 1) {
29
29
  this.error('Please use the \'-e\' flag to specify to which implementation you want to add actions to.')
30
30
  }
@@ -32,7 +32,7 @@ class AddActionCommand extends TemplatesCommand {
32
32
  const config = entries[0][1]
33
33
 
34
34
  const actionFolder = path.relative(config.root, config.actions.src)
35
- const configData = this.getRuntimeManifestConfigFile(configName)
35
+ const configData = await this.getRuntimeManifestConfigFile(configName)
36
36
 
37
37
  const projectOrgId = aioConfigLoader.get('project.org.id')
38
38
  if (!projectOrgId) {
@@ -25,14 +25,14 @@ class AddEventCommand extends AddCommand {
25
25
  const spinner = ora()
26
26
 
27
27
  // guaranteed to have at least one, otherwise would throw in config load or in matching the ext name
28
- const entries = Object.entries(this.getAppExtConfigs(flags))
28
+ const entries = Object.entries(await this.getAppExtConfigs(flags))
29
29
  if (entries.length > 1) {
30
30
  this.error('Please use the \'-e\' flag to specify to which implementation you want to add events to.')
31
31
  }
32
32
  const configName = entries[0][0]
33
33
  const config = entries[0][1]
34
34
  const actionFolder = path.relative(config.root, config.actions.src)
35
- const configData = this.getRuntimeManifestConfigFile(configName)
35
+ const configData = await this.getRuntimeManifestConfigFile(configName)
36
36
 
37
37
  const env = yeoman.createEnv()
38
38
  // by default yeoman runs the install, we control installation from the app plugin
@@ -24,7 +24,7 @@ class AddExtensionCommand extends TemplatesCommand {
24
24
  this.error('--extension= must also be provided when using --yes')
25
25
  }
26
26
 
27
- const fullConfig = this.getFullConfig({ allowNoImpl: true })
27
+ const fullConfig = await this.getFullConfig({ allowNoImpl: true })
28
28
  const alreadyImplemented = fullConfig.implements
29
29
 
30
30
  if (flags.extension) {
@@ -19,9 +19,9 @@ class AddWebAssetsCommand extends TemplatesCommand {
19
19
  const { flags } = await this.parse(AddWebAssetsCommand)
20
20
  aioLogger.debug(`add web-assets with flags: ${JSON.stringify(flags)}`)
21
21
 
22
- const projectName = this.getFullConfig().packagejson.name
22
+ const projectName = (await this.getFullConfig()).packagejson.name
23
23
  // guaranteed to have at least one, otherwise would throw in config load or in matching the ext name
24
- const entries = Object.entries(this.getAppExtConfigs(flags))
24
+ const entries = Object.entries(await this.getAppExtConfigs(flags))
25
25
  if (entries.length > 1) {
26
26
  this.error('Please use the \'-e\' flag to specify to which implementation you want to add web-assets to.')
27
27
  }
@@ -15,7 +15,7 @@ const chalk = require('chalk')
15
15
 
16
16
  const BaseCommand = require('../../BaseCommand')
17
17
  const { Flags } = require('@oclif/core')
18
- const { runScript, writeConfig } = require('../../lib/app-helper')
18
+ const { runInProcess, writeConfig } = require('../../lib/app-helper')
19
19
  const RuntimeLib = require('@adobe/aio-lib-runtime')
20
20
  const { bundle } = require('@adobe/aio-lib-web')
21
21
  const fs = require('fs-extra')
@@ -28,7 +28,7 @@ class Build extends BaseCommand {
28
28
  // flags
29
29
  flags['web-assets'] = flags['web-assets'] && !flags.action
30
30
 
31
- const buildConfigs = this.getAppExtConfigs(flags)
31
+ const buildConfigs = await this.getAppExtConfigs(flags)
32
32
 
33
33
  // 1. build actions and web assets for each extension
34
34
  const keys = Object.keys(buildConfigs)
@@ -64,7 +64,7 @@ class Build extends BaseCommand {
64
64
 
65
65
  const filterActions = flags.action
66
66
  try {
67
- await runScript(config.hooks['pre-app-build'])
67
+ await runInProcess(config.hooks['pre-app-build'], config)
68
68
  } catch (err) {
69
69
  this.log(err)
70
70
  }
@@ -73,7 +73,7 @@ class Build extends BaseCommand {
73
73
  if (config.app.hasBackend && (flags['force-build'] || !fs.existsSync(config.actions.dist))) {
74
74
  try {
75
75
  let builtList = []
76
- const script = await runScript(config.hooks['build-actions'])
76
+ const script = await runInProcess(config.hooks['build-actions'], config)
77
77
  aioLogger.debug(`run hook for 'build-actions' for actions in '${name}' returned ${script}`)
78
78
  spinner.start(`Building actions for '${name}'`)
79
79
  if (!script) {
@@ -105,7 +105,7 @@ class Build extends BaseCommand {
105
105
  }
106
106
  spinner.start('Building web assets')
107
107
  try {
108
- const script = await runScript(config.hooks['build-static'])
108
+ const script = await runInProcess(config.hooks['build-static'], config)
109
109
  if (script) {
110
110
  spinner.fail(chalk.green(`build-static skipped by hook '${name}'`))
111
111
  } else {
@@ -129,7 +129,7 @@ class Build extends BaseCommand {
129
129
  }
130
130
  }
131
131
  try {
132
- await runScript(config.hooks['post-app-build'])
132
+ await runInProcess(config.hooks['post-app-build'], config)
133
133
  } catch (err) {
134
134
  this.log(err)
135
135
  }
@@ -30,7 +30,7 @@ class ErrorsCommand extends BaseCommand {
30
30
  }
31
31
 
32
32
  async getLogForwarding () {
33
- const runtimeConfig = this.getFullConfig().aio.runtime
33
+ const runtimeConfig = (await this.getFullConfig()).aio.runtime
34
34
  rtLib.utils.checkOpenWhiskCredentials({ ow: runtimeConfig })
35
35
  const rt = await rtLib.init({
36
36
  ...runtimeConfig,
@@ -14,7 +14,7 @@ const LogForwarding = require('../../../../lib/log-forwarding')
14
14
 
15
15
  class LogForwardingCommand extends BaseCommand {
16
16
  async run () {
17
- const lf = await LogForwarding.init(this.getFullConfig().aio)
17
+ const lf = await LogForwarding.init((await this.getFullConfig()).aio)
18
18
 
19
19
  const localConfig = lf.getLocalConfig()
20
20
  const serverConfig = await lf.getServerConfig()
@@ -14,7 +14,7 @@ const LogForwarding = require('../../../../lib/log-forwarding')
14
14
 
15
15
  class LogForwardingCommand extends BaseCommand {
16
16
  async run () {
17
- const lf = await LogForwarding.init(this.getFullConfig().aio)
17
+ const lf = await LogForwarding.init((await this.getFullConfig()).aio)
18
18
 
19
19
  const destination = await this.promptDestination(lf.getSupportedDestinations())
20
20
  const destinationSettingsConfig = lf.getSettingsConfig(destination)
@@ -30,8 +30,8 @@ class DeleteActionCommand extends BaseCommand {
30
30
  this.error('<action-name> must also be provided when using --yes')
31
31
  }
32
32
 
33
- const fullConfig = this.getFullConfig()
34
- const { actions, actionsByImpl } = this.getAllActions(fullConfig)
33
+ const fullConfig = await this.getFullConfig()
34
+ const { actions, actionsByImpl } = await this.getAllActions(fullConfig)
35
35
  if (actions.length <= 0) {
36
36
  this.error('There are no actions in this project!')
37
37
  }
@@ -108,17 +108,20 @@ class DeleteActionCommand extends BaseCommand {
108
108
  )))
109
109
  }
110
110
 
111
- getAllActions (config) {
111
+ async getAllActions (config) {
112
112
  const actions = []
113
113
  const actionsByImpl = {}
114
- Object.entries(config.all).forEach(([implName, implConfig]) => {
114
+ const allConfigEntries = Object.entries(config.all)
115
+ for (const [implName, implConfig] of allConfigEntries) {
115
116
  if (implConfig.app.hasBackend) {
116
117
  actionsByImpl[implName] = []
117
- Object.entries(implConfig.manifest.full.packages).forEach(([pkgName, pkg]) => {
118
- Object.entries(pkg.actions).forEach(([actionName, action]) => {
118
+ const allPackagesEntries = Object.entries(implConfig.manifest.full.packages)
119
+ for (const [pkgName, pkg] of allPackagesEntries) {
120
+ const actionEntries = Object.entries(pkg.actions)
121
+ for (const [actionName, action] of actionEntries) {
119
122
  const fullActionName = `${pkgName}/${actionName}`
120
123
  const startKey = implName === 'application' ? 'application' : `extensions.${implName}`
121
- const configData = this.getConfigFileForKey(`${startKey}.runtimeManifest.packages.${pkgName}.actions.${actionName}`)
124
+ const configData = await this.getConfigFileForKey(`${startKey}.runtimeManifest.packages.${pkgName}.actions.${actionName}`)
122
125
  const actionObj = {
123
126
  // assumes path is not relative
124
127
  path: action.function,
@@ -131,12 +134,12 @@ class DeleteActionCommand extends BaseCommand {
131
134
  }
132
135
  actions.push(actionObj)
133
136
  actionsByImpl[implName].push(actionObj)
134
- })
135
- })
137
+ }
138
+ }
136
139
  } else {
137
140
  aioLogger.debug(`'${implName}' .app.hasBackend is not true`)
138
141
  }
139
- })
142
+ }
140
143
  return { actions, actionsByImpl }
141
144
  }
142
145
  }
@@ -28,7 +28,7 @@ class DeleteExtensionCommand extends BaseCommand {
28
28
  this.error('--extension= must also be provided when using --yes')
29
29
  }
30
30
 
31
- const fullConfig = this.getFullConfig({ allowNoImpl: true })
31
+ const fullConfig = await this.getFullConfig({ allowNoImpl: true })
32
32
  const configs = await this.selectOrGetConfigsToDelete(flags, fullConfig)
33
33
 
34
34
  const resConfirm = await this.prompt([
@@ -68,11 +68,11 @@ class DeleteExtensionCommand extends BaseCommand {
68
68
  }])
69
69
  flags.extension = answers.res
70
70
  }
71
- return this.getAppExtConfigs(flags)
71
+ return await this.getAppExtConfigs(flags)
72
72
  }
73
73
 
74
- deleteImplementations (configs) {
75
- Object.entries(configs).forEach(([id, c]) => {
74
+ async deleteImplementations (configs) {
75
+ for (const [id, c] of Object.entries(configs)) {
76
76
  // delete actions
77
77
  if (c.app.hasBackend) {
78
78
  fs.removeSync(c.actions.src)
@@ -89,14 +89,14 @@ class DeleteExtensionCommand extends BaseCommand {
89
89
  // delete config
90
90
  // try to find another config file => case of init extension in another folder
91
91
  const configKey = id === 'application' ? 'application' : `extensions.${id}`
92
- const configDataOp = this.getConfigFileForKey(configKey + '.operations')
92
+ const configDataOp = await this.getConfigFileForKey(configKey + '.operations')
93
93
  if (configDataOp.file) {
94
94
  fs.removeSync(configDataOp.file)
95
95
  }
96
96
  // delete config in parent config file
97
- const configData = this.getConfigFileForKey(configKey)
97
+ const configData = await this.getConfigFileForKey(configKey)
98
98
  deleteUserConfig(configData)
99
- })
99
+ }
100
100
  }
101
101
  }
102
102
 
@@ -25,7 +25,7 @@ class DeleteWebAssetsCommand extends BaseCommand {
25
25
 
26
26
  aioLogger.debug(`deleting web assets from the project, using flags: ${JSON.stringify(flags)}`)
27
27
 
28
- const fullConfig = this.getFullConfig()
28
+ const fullConfig = await this.getFullConfig()
29
29
  const webAssetsByImpl = this.getAllWebAssets(fullConfig)
30
30
  if (!webAssetsByImpl) {
31
31
  this.error('web-assets not found')
@@ -17,7 +17,7 @@ const BaseCommand = require('../../BaseCommand')
17
17
  const BuildCommand = require('./build')
18
18
  const webLib = require('@adobe/aio-lib-web')
19
19
  const { Flags, CliUx: { ux: cli } } = require('@oclif/core')
20
- const { createWebExportFilter, runScript, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata } = require('../../lib/app-helper')
20
+ const { createWebExportFilter, runInProcess, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata } = require('../../lib/app-helper')
21
21
  const rtLib = require('@adobe/aio-lib-runtime')
22
22
  const LogForwarding = require('../../lib/log-forwarding')
23
23
 
@@ -30,7 +30,7 @@ class Deploy extends BuildCommand {
30
30
  flags['web-assets'] = flags['web-assets'] && !flags.action
31
31
  flags.publish = flags.publish && !flags.action
32
32
 
33
- const deployConfigs = this.getAppExtConfigs(flags)
33
+ const deployConfigs = await this.getAppExtConfigs(flags)
34
34
  const keys = Object.keys(deployConfigs)
35
35
  const values = Object.values(deployConfigs)
36
36
  const isStandaloneApp = (keys.length === 1 && keys[0] === 'application')
@@ -51,13 +51,11 @@ class Deploy extends BuildCommand {
51
51
  const spinner = ora()
52
52
 
53
53
  try {
54
- const aioConfig = this.getFullConfig().aio
54
+ const aioConfig = (await this.getFullConfig()).aio
55
55
 
56
56
  // 1. update log forwarding configuration
57
57
  // note: it is possible that .aio file does not exist, which means there is no local lg config
58
- if (aioConfig &&
59
- aioConfig.project &&
60
- aioConfig.project.workspace &&
58
+ if (aioConfig?.project?.workspace &&
61
59
  flags['log-forwarding-update'] &&
62
60
  flags.actions) {
63
61
  spinner.start('Updating log forwarding configuration')
@@ -142,18 +140,17 @@ class Deploy extends BuildCommand {
142
140
  const filterActions = flags.action
143
141
 
144
142
  try {
145
- await runScript(config.hooks['pre-app-deploy'])
146
-
143
+ await runInProcess(config.hooks['pre-app-deploy'], config)
147
144
  if (flags['feature-event-hooks']) {
148
145
  this.log('feature-event-hooks is enabled, running pre-deploy-event-reg hook')
149
- const hookResults = await this.config.runHook('pre-deploy-event-reg', { appConfig: config })
146
+ const hookResults = await this.config.runHook('pre-deploy-event-reg', { appConfig: config, force: flags['force-events'] })
150
147
  if (hookResults?.failures?.length > 0) {
151
148
  // output should be "Error : <plugin-name> : <error-message>\n" for each failure
152
149
  this.error(hookResults.failures.map(f => `${f.plugin.name} : ${f.error.message}`).join('\nError: '), { exit: 1 })
153
150
  }
154
151
  }
155
152
  } catch (err) {
156
- this.log(err)
153
+ this.error(err)
157
154
  }
158
155
 
159
156
  if (flags.actions) {
@@ -165,7 +162,7 @@ class Deploy extends BuildCommand {
165
162
  const message = `Deploying actions for '${name}'`
166
163
  spinner.start(message)
167
164
  try {
168
- const script = await runScript(config.hooks['deploy-actions'])
165
+ const script = await runInProcess(config.hooks['deploy-actions'], config)
169
166
  if (!script) {
170
167
  const hookResults = await this.config.runHook('deploy-actions', {
171
168
  appConfig: config,
@@ -202,7 +199,7 @@ class Deploy extends BuildCommand {
202
199
  const message = `Deploying web assets for '${name}'`
203
200
  spinner.start(message)
204
201
  try {
205
- const script = await runScript(config.hooks['deploy-static'])
202
+ const script = await runInProcess(config.hooks['deploy-static'], config)
206
203
  if (script) {
207
204
  spinner.fail(chalk.green(`deploy-static skipped by hook '${name}'`))
208
205
  } else {
@@ -251,17 +248,17 @@ class Deploy extends BuildCommand {
251
248
  }
252
249
 
253
250
  try {
254
- await runScript(config.hooks['post-app-deploy'])
251
+ await runInProcess(config.hooks['post-app-deploy'], config)
255
252
  if (flags['feature-event-hooks']) {
256
253
  this.log('feature-event-hooks is enabled, running post-deploy-event-reg hook')
257
- const hookResults = await this.config.runHook('post-deploy-event-reg', { appConfig: config })
254
+ const hookResults = await this.config.runHook('post-deploy-event-reg', { appConfig: config, force: flags['force-events'] })
258
255
  if (hookResults?.failures?.length > 0) {
259
256
  // output should be "Error : <plugin-name> : <error-message>\n" for each failure
260
257
  this.error(hookResults.failures.map(f => `${f.plugin.name} : ${f.error.message}`).join('\nError: '), { exit: 1 })
261
258
  }
262
259
  }
263
260
  } catch (err) {
264
- this.log(err)
261
+ this.error(err)
265
262
  }
266
263
  }
267
264
 
@@ -354,6 +351,13 @@ Deploy.flags = {
354
351
  default: false,
355
352
  exclusive: ['action', 'publish'] // no-publish is excluded
356
353
  }),
354
+ 'force-events': Flags.boolean({
355
+ description: '[default: false] Force event registrations and overwrite any previous registrations',
356
+ default: false,
357
+ allowNo: true,
358
+ dependsOn: ['feature-event-hooks'],
359
+ exclusive: ['action', 'publish'] // no-publish is excluded
360
+ }),
357
361
  'web-optimize': Flags.boolean({
358
362
  description: '[default: false] Enable optimization (minification) of web js/css/html',
359
363
  default: false
@@ -31,7 +31,7 @@ class GetUrlCommand extends BaseCommand {
31
31
  options.cdn = flags.cdn
32
32
 
33
33
  const urls = {}
34
- const fullConfig = this.getFullConfig()
34
+ const fullConfig = await this.getFullConfig()
35
35
  if (options.action) {
36
36
  let action
37
37
  // search for action
@@ -19,7 +19,7 @@ class Info extends BaseCommand {
19
19
  async run () {
20
20
  // cli input
21
21
  const { flags } = await this.parse(Info)
22
- const appConfig = deepCopy(this.getFullConfig({ allowNoImpl: true }))
22
+ const appConfig = deepCopy(await this.getFullConfig({ allowNoImpl: true }))
23
23
 
24
24
  // includes .env secret delete all aio config for now
25
25
  delete appConfig.aio
@@ -22,6 +22,7 @@ const jsYaml = require('js-yaml')
22
22
  const { USER_CONFIG_FILE, DEPLOY_CONFIG_FILE } = require('../../lib/defaults')
23
23
  const ora = require('ora')
24
24
  const chalk = require('chalk')
25
+ const libAppConfig = require('@adobe/aio-cli-lib-app-config')
25
26
 
26
27
  class InstallCommand extends BaseCommand {
27
28
  async run () {
@@ -49,8 +50,9 @@ class InstallCommand extends BaseCommand {
49
50
  try {
50
51
  await this.validateZipDirectoryStructure(args.path)
51
52
  await this.unzipFile(args.path, outputPath)
52
- await this.validateConfig(outputPath, USER_CONFIG_FILE)
53
- await this.validateConfig(outputPath, DEPLOY_CONFIG_FILE)
53
+ // first coalesce the app config (resolving $include files), then validate it
54
+ await libAppConfig.validate(await libAppConfig.coalesce(USER_CONFIG_FILE))
55
+ await this.validateConfig(outputPath, DEPLOY_CONFIG_FILE, { throws: true })
54
56
  await this.npmInstall(flags.verbose)
55
57
  await this.runTests()
56
58
  this.spinner.succeed('Install done.')
@@ -22,7 +22,7 @@ class ListExtensionPointsCommand extends BaseCommand {
22
22
  const { flags } = await this.parse(ListExtensionPointsCommand)
23
23
  aioLogger.debug(`list all extensions points with flags: ${JSON.stringify(flags)}`)
24
24
 
25
- const extConfig = this.getAppExtConfigs(flags)
25
+ const extConfig = await this.getAppExtConfigs(flags)
26
26
  const extPointList = {}
27
27
 
28
28
  Object.keys(extConfig).forEach(name => {
@@ -22,7 +22,7 @@ class ListExtensionCommand extends BaseCommand {
22
22
  const { flags } = await this.parse(ListExtensionCommand)
23
23
  aioLogger.debug(`list extensions with flags: ${JSON.stringify(flags)}`)
24
24
 
25
- const extConfig = this.getAppExtConfigs(flags)
25
+ const extConfig = await this.getAppExtConfigs(flags)
26
26
  const extSummary = {}
27
27
 
28
28
  Object.keys(extConfig).forEach(extPoint => {
@@ -36,7 +36,7 @@ class Logs extends BaseCommand {
36
36
 
37
37
  async run () {
38
38
  const { flags } = await this.parse(Logs)
39
- const fullConfig = this.getFullConfig()
39
+ const fullConfig = await this.getFullConfig()
40
40
 
41
41
  // has any backend
42
42
  const hasAnyBackend = Object.values(fullConfig.all).reduce((hasBackend, config) => hasBackend && config.app.hasBackend, true)
@@ -37,7 +37,8 @@ class Pack extends BaseCommand {
37
37
  aioLogger.debug(`flags: ${JSON.stringify(flags, null, 2)}`)
38
38
  aioLogger.debug(`args: ${JSON.stringify(args, null, 2)}`)
39
39
 
40
- const appConfig = this.getFullConfig()
40
+ // NOTE: this will validate the app config file behind the scene
41
+ const appConfig = await this.getFullConfig()
41
42
 
42
43
  // resolve to absolute path before any chdir
43
44
  const outputZipFile = path.resolve(flags.output)
@@ -22,7 +22,7 @@ const coreConfig = require('@adobe/aio-lib-core-config')
22
22
  const BaseCommand = require('../../BaseCommand')
23
23
  const runDev = require('../../lib/run-dev')
24
24
  const { defaultHttpServerPort: SERVER_DEFAULT_PORT } = require('../../lib/defaults')
25
- const { runScript } = require('../../lib/app-helper')
25
+ const { runInProcess } = require('../../lib/app-helper')
26
26
 
27
27
  const DEV_KEYS_DIR = 'dist/dev-keys/'
28
28
  const PRIVATE_KEY_PATH = DEV_KEYS_DIR + 'private.key'
@@ -36,7 +36,7 @@ class Run extends BaseCommand {
36
36
 
37
37
  const spinner = ora()
38
38
 
39
- const runConfigs = this.getAppExtConfigs(flags)
39
+ const runConfigs = await this.getAppExtConfigs(flags)
40
40
  const entries = Object.entries(runConfigs)
41
41
  if (entries.length > 1) {
42
42
  this.error('Your app implements multiple extensions. You can only run one at the time, please select which extension to run with the \'-e\' flag.')
@@ -80,7 +80,7 @@ class Run extends BaseCommand {
80
80
  }
81
81
 
82
82
  try {
83
- await runScript(config.hooks['pre-app-run'])
83
+ await runInProcess(config.hooks['pre-app-run'], { config, options: runOptions })
84
84
  } catch (err) {
85
85
  this.log(err)
86
86
  }
@@ -107,7 +107,7 @@ class Run extends BaseCommand {
107
107
  const inprocHook = this.config.runHook.bind(this.config)
108
108
  const frontendUrl = await runDev(config, this.config.dataDir, runOptions, onProgress, inprocHook)
109
109
  try {
110
- await runScript(config.hooks['post-app-run'])
110
+ await runInProcess(config.hooks['post-app-run'], config)
111
111
  } catch (err) {
112
112
  this.log(err)
113
113
  }
@@ -31,7 +31,7 @@ class Test extends BaseCommand {
31
31
  unit = true
32
32
  }
33
33
 
34
- const buildConfigs = this.getAppExtConfigs({ extension })
34
+ const buildConfigs = await this.getAppExtConfigs({ extension })
35
35
  aioLogger.debug(`run buildConfigs:${JSON.stringify(buildConfigs, null, 2)}`)
36
36
 
37
37
  const totalResults = []
@@ -18,7 +18,7 @@ const { Flags } = require('@oclif/core')
18
18
 
19
19
  const BaseCommand = require('../../BaseCommand')
20
20
  const webLib = require('@adobe/aio-lib-web')
21
- const { runScript, buildExtensionPointPayloadWoMetadata } = require('../../lib/app-helper')
21
+ const { runInProcess, buildExtensionPointPayloadWoMetadata } = require('../../lib/app-helper')
22
22
  const rtLib = require('@adobe/aio-lib-runtime')
23
23
 
24
24
  class Undeploy extends BaseCommand {
@@ -26,7 +26,7 @@ class Undeploy extends BaseCommand {
26
26
  // cli input
27
27
  const { flags } = await this.parse(Undeploy)
28
28
 
29
- const undeployConfigs = this.getAppExtConfigs(flags)
29
+ const undeployConfigs = await this.getAppExtConfigs(flags)
30
30
  let libConsoleCLI
31
31
  if (flags.unpublish) {
32
32
  // force login at beginning (if required)
@@ -52,7 +52,7 @@ class Undeploy extends BaseCommand {
52
52
  }
53
53
  // 2. unpublish extension manifest
54
54
  if (flags.unpublish && !(keys.length === 1 && keys[0] === 'application')) {
55
- const aioConfig = this.getFullConfig().aio
55
+ const aioConfig = (await this.getFullConfig()).aio
56
56
  const payload = await this.unpublishExtensionPoints(libConsoleCLI, undeployConfigs, aioConfig, flags['force-unpublish'])
57
57
  this.log(chalk.blue(chalk.bold(`New Extension Point(s) in Workspace '${aioConfig.project.workspace.name}': '${Object.keys(payload.endpoints)}'`)))
58
58
  } else {
@@ -78,7 +78,7 @@ class Undeploy extends BaseCommand {
78
78
  }
79
79
  // undeploy
80
80
  try {
81
- await runScript(config.hooks['pre-app-undeploy'])
81
+ await runInProcess(config.hooks['pre-app-undeploy'], config)
82
82
  } catch (err) {
83
83
  this.log(err)
84
84
  }
@@ -86,7 +86,8 @@ class Undeploy extends BaseCommand {
86
86
  if (flags.actions) {
87
87
  if (config.app.hasBackend) {
88
88
  try {
89
- const script = await runScript(config.hooks['undeploy-actions'])
89
+ this.config.runHook('pre-undeploy-event-reg', { appConfig: config })
90
+ const script = await runInProcess(config.hooks['undeploy-actions'], config)
90
91
  if (!script) {
91
92
  await rtLib.undeployActions(config)
92
93
  }
@@ -102,7 +103,7 @@ class Undeploy extends BaseCommand {
102
103
  if (flags['web-assets']) {
103
104
  if (config.app.hasFrontend) {
104
105
  try {
105
- const script = await runScript(config.hooks['undeploy-static'])
106
+ const script = await runInProcess(config.hooks['undeploy-static'], config)
106
107
  if (!script) {
107
108
  await webLib.undeployWeb(config, onProgress)
108
109
  }
@@ -117,7 +118,8 @@ class Undeploy extends BaseCommand {
117
118
  }
118
119
 
119
120
  try {
120
- await runScript(config.hooks['post-app-undeploy'])
121
+ this.config.runHook('post-undeploy-event-reg', { appConfig: config })
122
+ await runInProcess(config.hooks['post-app-undeploy'], config)
121
123
  if (flags['feature-event-hooks'] && flags.events) {
122
124
  this.log('feature-event-hooks is enabled, running post-undeploy-event-reg hook')
123
125
  const hookResults = await this.config.runHook('post-undeploy-event-reg', { appConfig: config })
@@ -66,7 +66,12 @@ async function installPackages (dir, options = { spinner: null, verbose: false }
66
66
  return ret
67
67
  }
68
68
 
69
- /** @private */
69
+ // Is this still used? it is exported, but there are no references to it -jm
70
+ /**
71
+ * @param {string} scriptName npm script name
72
+ * @param {string} dir directory to run npm script in
73
+ * @param {string[]} cmdArgs args to pass to npm script
74
+ */
70
75
  async function runPackageScript (scriptName, dir, cmdArgs = []) {
71
76
  aioLogger.debug(`running npm run-script ${scriptName} in dir: ${dir}`)
72
77
  const pkg = await fs.readJSON(path.join(dir, 'package.json'))
@@ -79,7 +84,39 @@ async function runPackageScript (scriptName, dir, cmdArgs = []) {
79
84
  }
80
85
  }
81
86
 
82
- /** @private */
87
+ /**
88
+ *
89
+ * @param {string} hookPath to be require()'d and run. Should export an async function that takes a config object as its only argument
90
+ * @param {object} config which will be passed to the hook
91
+ * @returns {Promise<*>} whatever the hook returns
92
+ */
93
+ async function runInProcess (hookPath, config) {
94
+ if (hookPath) {
95
+ try {
96
+ const hook = require(path.resolve(hookPath))
97
+ aioLogger.debug('runInProcess: running project hook in process')
98
+ return hook(config)
99
+ } catch (e) {
100
+ aioLogger.debug('runInProcess: error running project hook in process, running as package script instead')
101
+ return runScript(hookPath)
102
+ }
103
+ } else {
104
+ aioLogger.debug('runInProcess: undefined hookPath')
105
+ }
106
+ }
107
+
108
+ /**
109
+ * @typedef ChildProcess
110
+ */
111
+
112
+ /**
113
+ * Runs a package script in a child process
114
+ *
115
+ * @param {string} command to run
116
+ * @param {string} dir to run command in
117
+ * @param {string[]} cmdArgs args to pass to command
118
+ * @returns {Promise<ChildProcess>} child process
119
+ */
83
120
  async function runScript (command, dir, cmdArgs = []) {
84
121
  if (!command) {
85
122
  return null
@@ -536,6 +573,7 @@ module.exports = {
536
573
  isGitInstalled,
537
574
  installPackages,
538
575
  runScript,
576
+ runInProcess,
539
577
  runPackageScript,
540
578
  wrapError,
541
579
  getCliInfo,
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- const utils = require('./app-helper')
13
+ const { runInProcess } = require('./app-helper')
14
14
  const { buildActions } = require('@adobe/aio-lib-runtime')
15
15
 
16
16
  /**
@@ -21,10 +21,10 @@ const { buildActions } = require('@adobe/aio-lib-runtime')
21
21
  * @param {boolean} [forceBuild=false] force a build (skip file changed hash check)
22
22
  */
23
23
  module.exports = async (config, filterActions, forceBuild = false) => {
24
- utils.runScript(config.hooks['pre-app-build'])
25
- const script = await utils.runScript(config.hooks['build-actions'])
24
+ await runInProcess(config.hooks['pre-app-build'], config)
25
+ const script = await runInProcess(config.hooks['build-actions'], { config, options: { filterActions, forceBuild } })
26
26
  if (!script) {
27
27
  await buildActions(config, filterActions, forceBuild)
28
28
  }
29
- utils.runScript(config.hooks['post-app-build'])
29
+ await runInProcess(config.hooks['post-app-build'], config)
30
30
  }
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- const utils = require('./app-helper')
13
+ const { runInProcess, createWebExportFilter } = require('./app-helper')
14
14
  const { deployActions } = require('@adobe/aio-lib-runtime')
15
15
 
16
16
  /**
@@ -23,8 +23,8 @@ const { deployActions } = require('@adobe/aio-lib-runtime')
23
23
  */
24
24
  /** @private */
25
25
  module.exports = async (config, isLocalDev = false, log = () => {}, filter = false, inprocHook) => {
26
- utils.runScript(config.hooks['pre-app-deploy'])
27
- const script = await utils.runScript(config.hooks['deploy-actions'])
26
+ await runInProcess(config.hooks['pre-app-deploy'], config)
27
+ const script = await runInProcess(config.hooks['deploy-actions'], { config, options: { isLocalDev, filter } })
28
28
  if (!script) {
29
29
  const deployConfig = {
30
30
  isLocalDev,
@@ -47,8 +47,8 @@ module.exports = async (config, isLocalDev = false, log = () => {}, filter = fal
47
47
  }
48
48
  const entities = await deployActions(config, deployConfig, log)
49
49
  if (entities.actions) {
50
- const web = entities.actions.filter(utils.createWebExportFilter(true))
51
- const nonWeb = entities.actions.filter(utils.createWebExportFilter(false))
50
+ const web = entities.actions.filter(createWebExportFilter(true))
51
+ const nonWeb = entities.actions.filter(createWebExportFilter(false))
52
52
 
53
53
  if (web.length > 0) {
54
54
  log('web actions:')
@@ -65,5 +65,5 @@ module.exports = async (config, isLocalDev = false, log = () => {}, filter = fal
65
65
  }
66
66
  }
67
67
  }
68
- utils.runScript(config.hooks['post-app-deploy'])
68
+ await runInProcess(config.hooks['post-app-deploy'], config)
69
69
  }
@@ -1,157 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://adobe.io/schemas/app-builder/app.config.yaml.json/v1",
4
- "type": "object",
5
- "properties": {
6
- "application": { "$ref": "#/definitions/application" },
7
- "extensions": { "$ref": "#/definitions/extensions" }
8
- },
9
- "oneOf": [
10
- {
11
- "required": ["application"],
12
- "allOf": [
13
- { "not": { "required": ["extensions"] } }
14
- ]
15
- },
16
- {
17
- "required": ["extensions"],
18
- "allOf": [
19
- { "not": { "required": ["application"] } }
20
- ]
21
- }
22
- ],
23
- "definitions": {
24
- "application": {
25
- "type": "object",
26
- "properties": {
27
- "runtimeManifest": { "$ref": "#/definitions/runtimeManifest" },
28
- "actions": { "type": "string" },
29
- "unitTest": { "type": "string" },
30
- "e2eTest": { "type": "string" },
31
- "dist": { "type": "string" },
32
- "tvmurl": { "type": "string" },
33
- "awsaccesskeyid": { "type": "string" },
34
- "awssecretaccesskey": { "type": "string" },
35
- "s3bucket": { "type": "string" },
36
- "events": { "type": "object" },
37
- "hostname": { "type": "string" },
38
- "htmlcacheduration": { "type": "number" },
39
- "jscacheduration": { "type": "number" },
40
- "csscacheduration": { "type": "number" },
41
- "imagecacheduration": { "type": "number" },
42
- "hooks": { "$ref": "#/definitions/hooks" },
43
- "web": { "$ref": "#/definitions/web" }
44
- },
45
- "required": ["runtimeManifest"]
46
- },
47
- "extensions": {
48
- "type": "object",
49
- "patternProperties": {
50
- "^[A-Za-z0-9-_/\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff]{1,20}$": {
51
- "$ref": "#/definitions/extension"
52
- }
53
- },
54
- "additionalProperties": false
55
- },
56
- "extension": {
57
- "type": "object",
58
- "properties": {
59
- "$include": { "type": "string" }
60
- }
61
- },
62
- "web": {
63
- "anyOf": [
64
- {
65
- "type": "string"
66
- },
67
- {
68
- "type": "object",
69
- "properties": {
70
- "response-headers": { "type": "object" }
71
- }
72
- }
73
- ]
74
- },
75
- "runtimeManifest": {
76
- "type": "object",
77
- "properties": {
78
- "packages": { "$ref": "#/definitions/packages" }
79
- },
80
- "required": ["packages"]
81
- },
82
- "packages": {
83
- "type": "object",
84
- "patternProperties": {
85
- "^[A-Za-z0-9-_\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff]{1,20}$": {
86
- "$ref": "#/definitions/package"
87
- }
88
- },
89
- "additionalProperties": false
90
- },
91
- "package": {
92
- "type": "object",
93
- "properties": {
94
- "license": { "type": "string" },
95
- "actions": { "$ref": "#/definitions/actions" }
96
- }
97
- },
98
- "actions": {
99
- "type": "object",
100
- "patternProperties": {
101
- "^[A-Za-z0-9-_\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff]{1,20}$": {
102
- "$ref": "#/definitions/action"
103
- }
104
- },
105
- "additionalProperties": false
106
- },
107
- "action": {
108
- "type": "object",
109
- "properties": {
110
- "function": { "type": "string" },
111
- "web": { "type": "string" },
112
- "runtime": { "type": "string" },
113
- "inputs": { "$ref": "#/definitions/inputs" },
114
- "annotations": { "$ref": "#/definitions/annotations" }
115
- },
116
- "required": ["function", "runtime"]
117
- },
118
- "inputs": {
119
- "type": "object",
120
- "patternProperties": {
121
- "^[A-Za-z0-9-_\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff]{1,20}$": {
122
- "type": ["string", "boolean"]
123
- }
124
- },
125
- "additionalProperties": false
126
- },
127
- "annotations": {
128
- "type": "object",
129
- "patternProperties": {
130
- "^[A-Za-z0-9-_\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff]{1,20}$": {
131
- "type": ["string", "boolean"]
132
- }
133
- },
134
- "additionalProperties": false
135
- },
136
- "hooks": {
137
- "type": "object",
138
- "properties": {
139
- "pre-app-build": { "type": "string" },
140
- "post-app-build": { "type": "string" },
141
- "build-actions": { "type": "string" },
142
- "build-static": { "type": "string" },
143
- "pre-app-deploy": { "type": "string" },
144
- "post-app-deploy": { "type": "string" },
145
- "deploy-actions": { "type": "string" },
146
- "deploy-static": { "type": "string" },
147
- "pre-app-undeploy": { "type": "string" },
148
- "post-app-undeploy": { "type": "string" },
149
- "undeploy-actions": { "type": "string" },
150
- "undeploy-static": { "type": "string" },
151
- "pre-app-run": { "type": "string" },
152
- "post-app-run": { "type": "string" },
153
- "serve-static": { "type": "string" }
154
- }
155
- }
156
- }
157
- }