diff --git a/schema/app.config.yaml.schema.json b/schema/app.config.yaml.schema.json
index 4b764b5..6738c2a 100644
--- a/schema/app.config.yaml.schema.json
+++ b/schema/app.config.yaml.schema.json
@@ -96,7 +96,8 @@
"runtimeManifest": {
"type": "object",
"properties": {
- "packages": { "$ref": "#/definitions/packages" }
+ "packages": { "$ref": "#/definitions/packages" },
+ "database": { "$ref": "#/definitions/database" }
},
"required": ["packages"]
},
@@ -109,6 +110,15 @@
},
"additionalProperties": false
},
+ "database": {
+ "type": "object",
+ "properties": {
+ "auto-provision": { "type": "boolean"},
+ "region": { "type": "string"}
+ },
+ "required": ["auto-provision"],
+ "additionalProperties": false
+ },
"package": {
"type": "object",
"properties": {
diff --git a/src/index.js b/src/index.js
index 40b98cd..6a02cf4 100644
--- a/src/index.js
+++ b/src/index.js
@@ -637,6 +637,9 @@ async function buildSingleConfig (configName, singleUserConfig, commonConfig, in
if (singleUserConfig.events) {
config.events = { ...singleUserConfig.events }
}
+ if (manifest && manifest.database) {
+ config.database = { ...manifest.database }
+ }
if (commonConfig?.aio?.project) {
config.project = commonConfig.aio.project
}
diff --git a/test/__fixtures__/app-with-database/app.config.yaml b/test/__fixtures__/app-with-database/app.config.yaml
new file mode 100644
index 0000000..f5277ef
--- /dev/null
+++ b/test/__fixtures__/app-with-database/app.config.yaml
@@ -0,0 +1,20 @@
+application:
+ actions: 'myactions'
+ runtimeManifest:
+ database:
+ auto-provision: true
+ region: 'emea'
+ packages:
+ my-app-package:
+ license: 'Apache-2.0'
+ actions:
+ action:
+ function: 'myactions/action.js'
+ web: 'yes'
+ runtime: 'nodejs:14'
+ inputs:
+ LOG_LEVEL: 'debug'
+ annotations:
+ final: true
+ require-adobe-auth: true
+ web: 'web-src'
diff --git a/test/__fixtures__/app-with-database/myactions/action.js b/test/__fixtures__/app-with-database/myactions/action.js
new file mode 100644
index 0000000..38a6e5a
--- /dev/null
+++ b/test/__fixtures__/app-with-database/myactions/action.js
@@ -0,0 +1,10 @@
+/**
+ * Main action function
+ * @param {object} params - Action parameters
+ * @returns {object} Response object
+ */
+function main (params) {
+ return { msg: 'Hello world with database!' }
+}
+
+module.exports.main = main
diff --git a/test/__fixtures__/app-with-database/package.json b/test/__fixtures__/app-with-database/package.json
new file mode 100644
index 0000000..8ec31ee
--- /dev/null
+++ b/test/__fixtures__/app-with-database/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "app-with-database",
+ "version": "1.0.0",
+ "scripts": {
+ "test": "echo test"
+ }
+}
diff --git a/test/__fixtures__/app-with-database/web-src/index.html b/test/__fixtures__/app-with-database/web-src/index.html
new file mode 100644
index 0000000..41631a1
--- /dev/null
+++ b/test/__fixtures__/app-with-database/web-src/index.html
@@ -0,0 +1,9 @@
+
+
+
+ App with Database
+
+
+ Hello from App with Database!
+
+
diff --git a/test/data-mocks/config-loader.js b/test/data-mocks/config-loader.js
index 6eb135c..1dd2623 100644
--- a/test/data-mocks/config-loader.js
+++ b/test/data-mocks/config-loader.js
@@ -284,6 +284,73 @@ const applicationSingleConfig = {
}
}
+const appWithDatabaseActionsFolder = winCompat(`${root}myactions`)
+const applicationWithDatabaseSingleConfig = {
+ application: {
+ app: {
+ hasBackend: true,
+ hasFrontend: true,
+ dist: winCompat(`${root}dist/application`),
+ defaultHostname: 'adobeio-static.net',
+ hostname: 'mydomain.test',
+ htmlCacheDuration: '60',
+ jsCacheDuration: '60',
+ cssCacheDuration: '60',
+ imageCacheDuration: '60'
+ },
+ ow,
+ s3: {
+ credsCacheFile: winCompat(`${root}.aws.tmp.creds.json`)
+ },
+ web: {
+ src: winCompat(`${root}web-src`),
+ injectedConfig: winCompat(`${root}web-src/src/config.json`),
+ distDev: winCompat(`${root}dist/application/web-dev`),
+ distProd: winCompat(`${root}dist/application/web-prod`)
+ },
+ manifest: {
+ src: 'manifest.yml',
+ full: {
+ packages: {
+ 'my-app-package': {
+ license: 'Apache-2.0',
+ actions: {
+ action: {
+ function: winCompat(`${appWithDatabaseActionsFolder}/action.js`),
+ web: 'yes',
+ runtime: 'nodejs:14',
+ inputs: {
+ LOG_LEVEL: 'debug'
+ },
+ annotations: {
+ final: true,
+ 'require-adobe-auth': true
+ }
+ }
+ }
+ }
+ },
+ database: {
+ 'auto-provision': true,
+ region: 'emea'
+ }
+ },
+ packagePlaceholder: '__APP_PACKAGE__',
+ package: undefined
+ },
+ actions: {
+ src: appWithDatabaseActionsFolder,
+ dist: winCompat(`${root}dist/application/actions`)
+ },
+ tests: {
+ e2e: winCompat(`${root}e2e`),
+ unit: winCompat(`${root}test`)
+ },
+ root: `${root}`,
+ name: 'application'
+ }
+}
+
const legacyManifest = fullFakeRuntimeManifest(appActionsFolder, '__APP_PACKAGE__')
const applicationLegacyConfig = {
application: {
@@ -362,6 +429,18 @@ const expectedConfigs = {
},
root
},
+ 'app-with-database': {
+ all: { ...applicationWithDatabaseSingleConfig },
+ implements: [
+ 'application'
+ ],
+ includeIndex: appIncludeIndex,
+ packagejson: {
+ version: '1.0.0',
+ name: 'app-with-database'
+ },
+ root
+ },
'app-exc-nui': {
all: { ...excSingleConfig, ...nuiSingleConfig, ...applicationSingleConfig },
implements: [
diff --git a/test/index.test.js b/test/index.test.js
index 116ca01..040e8d9 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -46,6 +46,17 @@ describe('load config', () => {
expect(config).toEqual(mockConfig)
})
+ test('standalone app config with database', async () => {
+ global.loadFixtureApp('app-with-database')
+ config = await appConfig.load()
+ expect(config.all.application.database).toEqual({
+ 'auto-provision': true,
+ region: 'emea'
+ })
+ expect(config.all.application.app.hasBackend).toBe(true)
+ expect(config.all.application.app.hasFrontend).toBe(true)
+ })
+
test('not in an app', async () => {
global.loadFixtureApp('not-in-app')
await expect(appConfig.load()).rejects.toThrow(new Error('ENOENT: no such file or directory, open \'package.json\''))
@@ -1064,3 +1075,121 @@ describe('coalesce config', () => {
expect(coalesced.includeIndex['application.runtimeManifest.packages.my-app-package.actions.action.function']).toEqual({ file: 'app/myactions/action.config.yaml', key: 'function' })
})
})
+
+describe('database config', () => {
+ beforeEach(async () => {
+ mockAIOConfig.get.mockImplementation(k => global.fakeConfig.tvm)
+ process.chdir('/')
+ global.fakeFileSystem.clear()
+ libEnv.getCliEnv.mockReturnValue('prod')
+ })
+
+ test('valid database configuration', async () => {
+ global.fakeFileSystem.addJson({
+ '/package.json': '{"name": "test-app", "version": "1.0.0"}',
+ '/app.config.yaml': `
+application:
+ runtimeManifest:
+ database:
+ auto-provision: true
+ region: 'emea'
+ packages:
+ my-app-package:
+ actions:
+ action:
+ function: 'actions/hello.js'
+ web: true
+`
+ })
+ const config = await appConfig.load()
+ expect(config.all.application.database).toEqual({
+ 'auto-provision': true,
+ region: 'emea'
+ })
+ })
+
+ test('database configuration with auto-provision true', async () => {
+ global.fakeFileSystem.addJson({
+ '/package.json': '{"name": "test-app", "version": "1.0.0"}',
+ '/app.config.yaml': `
+application:
+ runtimeManifest:
+ database:
+ auto-provision: true
+ packages:
+ my-app-package:
+ actions:
+ action:
+ function: 'actions/hello.js'
+ web: true
+`
+ })
+ const config = await appConfig.load()
+ expect(config.all.application.database).toEqual({
+ 'auto-provision': true
+ })
+ })
+
+ test('database configuration with empty fields', async () => {
+ global.fakeFileSystem.addJson({
+ '/package.json': '{"name": "test-app", "version": "1.0.0"}',
+ '/app.config.yaml': `
+application:
+ runtimeManifest:
+ database: {}
+ packages:
+ my-app-package:
+ actions:
+ action:
+ function: 'actions/hello.js'
+ web: true
+`
+ })
+ await expect(appConfig.load()).rejects.toThrow('Missing or invalid keys in app.config.yaml:')
+ })
+
+ test('database configuration validation - valid', async () => {
+ const validConfig = {
+ application: {
+ runtimeManifest: {
+ database: {
+ 'auto-provision': true,
+ region: 'apac'
+ },
+ packages: {
+ 'my-app': {
+ actions: {
+ hello: {
+ function: 'hello.js'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ const validation = await appConfig.validate(validConfig)
+ expect(validation.valid).toBe(true)
+ expect(validation.errors).toBe(null)
+ })
+
+ test('invalid database configuration - invalid auto-provision type', async () => {
+ global.fakeFileSystem.addJson({
+ '/package.json': '{"name": "test-app", "version": "1.0.0"}',
+ '/app.config.yaml': `
+application:
+ runtimeManifest:
+ database:
+ auto-provision: 'invalid'
+ region: 'amer'
+ packages:
+ my-app-package:
+ actions:
+ action:
+ function: 'actions/hello.js'
+ web: true
+`
+ })
+ await expect(appConfig.load({})).rejects.toThrow('must be boolean')
+ })
+})