@adobe/aio-lib-db 0.1.0-beta.2 → 0.1.0-beta.4
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 +6 -1
- package/lib/DbBase.js +10 -1
- package/lib/api/db.js +13 -1
- package/package.json +3 -1
- package/utils/ejsonHandler.js +4 -0
- package/utils/manifestUtils.js +141 -0
package/README.md
CHANGED
|
@@ -39,7 +39,12 @@ __OW_API_KEY=user:password
|
|
|
39
39
|
|
|
40
40
|
### Basic Usage
|
|
41
41
|
|
|
42
|
-
> When calling `libDb.init()`, you can pass `{ region: '<region>>' }` to specify the region where your database is provisioned.
|
|
42
|
+
> When calling `libDb.init()`, you can pass `{ region: '<region>>' }` to specify the region where your database is provisioned, or if region is defined in `app.config.yaml` of aio app, then `libDb.init()` will initialize in specified region.
|
|
43
|
+
>
|
|
44
|
+
> **Note:** region defined in `app.config.yaml` holds preference over passed in config param.
|
|
45
|
+
>
|
|
46
|
+
> If region is not specified in any of the above ways, it falls back to default.
|
|
47
|
+
>
|
|
43
48
|
> Valid regions are `amer` (default), `emea`, and `apac`.
|
|
44
49
|
|
|
45
50
|
```javascript
|
package/lib/DbBase.js
CHANGED
|
@@ -14,6 +14,7 @@ const { pingApi, provisionStatusApi, provisionRequestApi, deleteDatabaseApi } =
|
|
|
14
14
|
const DbClient = require('./DbClient')
|
|
15
15
|
const DbError = require("./DbError")
|
|
16
16
|
const { getAxiosClient } = require("../utils/axiosUtils")
|
|
17
|
+
const { getRegionFromAppConfig } = require("../utils/manifestUtils")
|
|
17
18
|
const {
|
|
18
19
|
ALLOWED_REGIONS, STAGE_ENV, STAGE_ENDPOINT, PROD_ENDPOINT_RUNTIME, PROD_ENDPOINT_EXTERNAL
|
|
19
20
|
} = require("./constants")
|
|
@@ -86,7 +87,15 @@ class DbBase {
|
|
|
86
87
|
static async init(config = {}) {
|
|
87
88
|
const namespace = config.namespace || process.env.__OW_NAMESPACE
|
|
88
89
|
const apikey = config.apikey || process.env.__OW_API_KEY
|
|
89
|
-
|
|
90
|
+
let aioAppRegion = null
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
aioAppRegion = getRegionFromAppConfig(process.cwd())
|
|
94
|
+
} catch (e) {
|
|
95
|
+
throw new DbError(`Error reading region from app config: ${e.message}`)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const region = aioAppRegion || config.region || ALLOWED_REGIONS[getCliEnv()].at(0)
|
|
90
99
|
return new DbBase(region, namespace, apikey)
|
|
91
100
|
}
|
|
92
101
|
|
package/lib/api/db.js
CHANGED
|
@@ -10,6 +10,8 @@ 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
|
const { apiPost, apiGet } = require("../../utils/apiRequest")
|
|
13
|
+
const { writeRegionToAppConfig } = require("../../utils/manifestUtils")
|
|
14
|
+
const logger = require('@adobe/aio-lib-core-logging')('@adobe/aio-lib-db', { provider: 'debug' })
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Make a post request to the App Builder Database Service db API and return the result
|
|
@@ -46,7 +48,17 @@ async function getDbApi(db, endpoint) {
|
|
|
46
48
|
* @throws {DbError}
|
|
47
49
|
*/
|
|
48
50
|
async function provisionRequest(db) {
|
|
49
|
-
|
|
51
|
+
const response = await postDbApi(db, db.axiosClient, 'provision/request')
|
|
52
|
+
|
|
53
|
+
// Update app.config.yaml with the region after successful provision request
|
|
54
|
+
try {
|
|
55
|
+
writeRegionToAppConfig(process.cwd(), db.region)
|
|
56
|
+
logger.info(`Updated app.config.yaml with region: ${db.region}`)
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.warn(`Failed to update app.config.yaml: ${error.message}`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return response
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/aio-lib-db",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.4",
|
|
4
4
|
"description": "An abstraction on top of Document DB storage",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
],
|
|
17
17
|
"contributors": [],
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@adobe/aio-lib-core-logging": "^3.0.2",
|
|
19
20
|
"@adobe/aio-lib-env": "^3.0.1",
|
|
20
21
|
"axios": "^1.8.4",
|
|
21
22
|
"bson": "^6.10.3",
|
|
22
23
|
"dotenv": "^17.0.0",
|
|
23
24
|
"http-cookie-agent": "^6.0.8",
|
|
25
|
+
"js-yaml": "^4.1.0",
|
|
24
26
|
"tough-cookie": "^5.1.2"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
package/utils/ejsonHandler.js
CHANGED
|
@@ -35,6 +35,10 @@ function transformBsonPrimitives(obj) {
|
|
|
35
35
|
})
|
|
36
36
|
}
|
|
37
37
|
else if (typeof obj === 'object') {
|
|
38
|
+
// If the type was recognized by the parser, any properties should also have been handled so return it as-is
|
|
39
|
+
const objName = obj?.constructor?.name
|
|
40
|
+
if (objName && objName !== 'Object') return obj
|
|
41
|
+
|
|
38
42
|
const mapped = {}
|
|
39
43
|
Object.keys(obj).forEach((key) => {
|
|
40
44
|
mapped[key] = transformBsonPrimitives(obj[key])
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2025 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
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
const fs = require('fs')
|
|
13
|
+
const path = require('path')
|
|
14
|
+
const yaml = require('js-yaml')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Walk upwards from startDir looking for the filename. Returns the absolute
|
|
19
|
+
* path to the first match or null if none found.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} startDir - Starting directory for search
|
|
22
|
+
* @param {string} filename - Filename to search for
|
|
23
|
+
* @returns {string|null} Absolute path to file or null if not found
|
|
24
|
+
*/
|
|
25
|
+
function getFilePath(startDir, filename) {
|
|
26
|
+
if (!startDir || typeof startDir !== 'string') return null
|
|
27
|
+
if (!filename || typeof filename !== 'string') return null
|
|
28
|
+
|
|
29
|
+
let dir = path.resolve(startDir)
|
|
30
|
+
const root = path.parse(dir).root
|
|
31
|
+
while (true) {
|
|
32
|
+
const manifestPath = path.join(dir, filename)
|
|
33
|
+
if (fs.existsSync(manifestPath)) return manifestPath
|
|
34
|
+
if (dir === root) break
|
|
35
|
+
dir = path.dirname(dir)
|
|
36
|
+
}
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Read and parse YAML configuration file
|
|
42
|
+
*
|
|
43
|
+
* @param {string} filePath - Path to YAML file
|
|
44
|
+
* @returns {Object} Parsed YAML content or empty object if file doesn't exist
|
|
45
|
+
*/
|
|
46
|
+
function readYamlConfig(filePath) {
|
|
47
|
+
if (!fs.existsSync(filePath)) return {}
|
|
48
|
+
const content = fs.readFileSync(filePath, 'utf8')
|
|
49
|
+
return yaml.load(content)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Read `app.config.yaml` (if present) and return the `runtimeManifest` object
|
|
54
|
+
* or null if not found.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} startDir - Starting directory to search from
|
|
57
|
+
* @returns {Object|null} Runtime manifest object or null if not found
|
|
58
|
+
*/
|
|
59
|
+
function getRuntimeManifestFromAppConfig(startDir) {
|
|
60
|
+
const APP_CONFIG_FILE = 'app.config.yaml'
|
|
61
|
+
const appConfigPath = getFilePath(startDir, APP_CONFIG_FILE)
|
|
62
|
+
if (!appConfigPath) return null
|
|
63
|
+
const parsed = readYamlConfig(appConfigPath)
|
|
64
|
+
|
|
65
|
+
// Return runtimeManifest from application.runtimeManifest
|
|
66
|
+
return parsed?.application?.runtimeManifest || null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Extract region from app config manifest
|
|
71
|
+
*
|
|
72
|
+
* @param {string} startDir - Starting directory to search from
|
|
73
|
+
* @returns {string|null} Region string or null if not found
|
|
74
|
+
*/
|
|
75
|
+
function getRegionFromAppConfig(startDir) {
|
|
76
|
+
const runtimeManifest = getRuntimeManifestFromAppConfig(startDir)
|
|
77
|
+
return runtimeManifest?.database?.region || null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Write database configuration to existing app.config.yaml
|
|
82
|
+
*
|
|
83
|
+
* @param {string} startDir - Starting directory to search from
|
|
84
|
+
* @param {string} region - Database region
|
|
85
|
+
* @returns {boolean} True if region was written, false if file not found
|
|
86
|
+
* @throws {Error} If file operations fail (read/write/parse errors)
|
|
87
|
+
*/
|
|
88
|
+
function writeRegionToAppConfig(startDir, region) {
|
|
89
|
+
const APP_CONFIG_FILE = 'app.config.yaml'
|
|
90
|
+
const appConfigPath = getFilePath(startDir, APP_CONFIG_FILE)
|
|
91
|
+
|
|
92
|
+
// Return false if no app.config.yaml exists
|
|
93
|
+
if (!appConfigPath) {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Read existing config
|
|
98
|
+
const existingConfig = readYamlConfig(appConfigPath)
|
|
99
|
+
|
|
100
|
+
// Get current auto-provision value from runtimeManifest.database
|
|
101
|
+
const currentAutoProv = existingConfig?.application?.runtimeManifest?.database?.['auto-provision']
|
|
102
|
+
|
|
103
|
+
// Determine auto-provision value:
|
|
104
|
+
// - If true, keep it true
|
|
105
|
+
// - If false or not present, set to false
|
|
106
|
+
const autoProvision = currentAutoProv === true ? true : false
|
|
107
|
+
|
|
108
|
+
// Ensure nested structure exists and add region + auto-provision inside runtimeManifest
|
|
109
|
+
const config = {
|
|
110
|
+
...existingConfig,
|
|
111
|
+
application: {
|
|
112
|
+
...existingConfig?.application,
|
|
113
|
+
runtimeManifest: {
|
|
114
|
+
...existingConfig?.application?.runtimeManifest,
|
|
115
|
+
database: {
|
|
116
|
+
...existingConfig?.application?.runtimeManifest?.database,
|
|
117
|
+
'auto-provision': autoProvision,
|
|
118
|
+
region: region
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Write updated config back to file
|
|
125
|
+
const yamlContent = yaml.dump(config, {
|
|
126
|
+
defaultFlowStyle: false,
|
|
127
|
+
lineWidth: -1
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
fs.writeFileSync(appConfigPath, yamlContent, 'utf8')
|
|
131
|
+
return true
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
getFilePath,
|
|
137
|
+
readYamlConfig,
|
|
138
|
+
getRuntimeManifestFromAppConfig,
|
|
139
|
+
getRegionFromAppConfig,
|
|
140
|
+
writeRegionToAppConfig
|
|
141
|
+
}
|