configuration-management 0.1.3 → 0.1.6

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 ADDED
@@ -0,0 +1,216 @@
1
+ # configuration-management
2
+
3
+ Schema-driven system configuration for **Adobe Commerce** and **Adobe App Builder** sync applications.
4
+
5
+ Mirrors Magento's `core_config_data` model: scoped configuration (`default` / `websites` / `stores`) stored in **Adobe App Builder Database (ABDB)** with AES-256-GCM encryption for sensitive fields.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install configuration-management
11
+ ```
12
+
13
+ Your App Builder project must also have Adobe I/O runtime dependencies installed (peer dependencies):
14
+
15
+ ```bash
16
+ npm install @adobe/aio-lib-core-auth @adobe/aio-lib-db @adobe/aio-lib-ims @adobe/aio-sdk dotenv
17
+ ```
18
+
19
+ For the React Admin UI, also install Spectrum and React peers:
20
+
21
+ ```bash
22
+ npm install react react-dom @adobe/react-spectrum @adobe/uix-guest @adobe/exc-app react-router-dom react-error-boundary @spectrum-icons/workflow
23
+ ```
24
+
25
+ ## Quick start
26
+
27
+ Read a config value from ABDB inside an App Builder action:
28
+
29
+ ```js
30
+ const { getConfig } = require('configuration-management')
31
+
32
+ async function main (params) {
33
+ const apiUrl = await getConfig('sync_general/api/url', params, {
34
+ scope: 'websites',
35
+ scopeCode: 'base'
36
+ })
37
+ // ...
38
+ }
39
+ ```
40
+
41
+ ## API
42
+
43
+ ### Config resolution
44
+
45
+ | Export | Description |
46
+ |--------|-------------|
47
+ | `getConfig(path, params, options)` | Read a value with Magento-style scope inheritance |
48
+ | `clearAbdbConfigCache()` | Clear the in-process lookup cache |
49
+
50
+ ### ABDB helpers (`configuration-management/abdb`)
51
+
52
+ | Export | Description |
53
+ |--------|-------------|
54
+ | `getClient(params, options)` | Connect to ABDB using IMS credentials from action params |
55
+ | `withDbClient(params, fn, options)` | Run work with auto-close |
56
+ | `findOne`, `insertOne`, `updateOne`, … | Mongo-style collection helpers |
57
+
58
+ ### Scope / path model (`configuration-management/shared`)
59
+
60
+ | Export | Description |
61
+ |--------|-------------|
62
+ | `toStateKey(scope, scopeId, path)` | Encode `section/group/field` as ABDB document `_id` |
63
+ | `buildInheritanceChain(scope, scopeId, parentWebsiteId)` | Magento-style fallback chain |
64
+ | `isValidPath`, `normalizeScope`, `normalizeScopeId` | Validation helpers |
65
+
66
+ ### Encryption (`configuration-management/crypto`)
67
+
68
+ | Export | Description |
69
+ |--------|-------------|
70
+ | `encrypt(plaintext, params)` | AES-256-GCM encrypt for at-rest storage |
71
+ | `decrypt(ciphertext, params)` | Decrypt stored values |
72
+ | `isEncrypted(value)` | Detect `enc:v1:` wire format |
73
+
74
+ ### Commerce REST (`configuration-management/oauth1a`)
75
+
76
+ | Export | Description |
77
+ |--------|-------------|
78
+ | `getCommerceOauthClient(options, logger)` | OAuth 1.0a client for Adobe Commerce REST API |
79
+
80
+ ### React Admin UI (`configuration-management/web`)
81
+
82
+ Spectrum-based Commerce Admin extension UI for schema-driven system configuration.
83
+
84
+ ```js
85
+ import React from 'react'
86
+ import { createRoot } from 'react-dom/client'
87
+ import {
88
+ ConfigurationManagementApp,
89
+ configureWeb
90
+ } from 'configuration-management/web'
91
+ import actionUrls from './config.json'
92
+ import 'configuration-management/web/styles.css'
93
+
94
+ configureWeb({ actionUrls })
95
+
96
+ createRoot(document.getElementById('root')).render(
97
+ React.createElement(ConfigurationManagementApp, { runtime, ims })
98
+ )
99
+ ```
100
+
101
+ The web UI is **pre-built** in the package (`web/dist/index.js`), so no Parcel
102
+ `includeNodeModules` or webpack aliases are required in your host `package.json`.
103
+
104
+ | Export | Description |
105
+ |--------|-------------|
106
+ | `ConfigurationManagementApp` | Full app shell (router + Spectrum provider + UIX registration) |
107
+ | `SystemConfig` | Dynamic config form UI |
108
+ | `SystemConfigSchemaEditor` | Schema designer |
109
+ | `useSystemConfig`, `useSystemConfigSchema` | Data hooks |
110
+ | `configureWeb({ actionUrls, extensionId, actionKeys })` | Wire deploy-time action URLs before render |
111
+
112
+ Styles: `import 'configuration-management/web/styles.css'`
113
+
114
+ ### App Builder actions (`configuration-management/actions`)
115
+
116
+ OpenWhisk runtime actions and the Commerce Admin extension manifest ship with the package.
117
+
118
+ #### Automatic wiring on `npm install`
119
+
120
+ The package runs a **postinstall** script that:
121
+
122
+ 1. Patches your project's `app.config.yaml` (if present) with:
123
+
124
+ ```yaml
125
+ extensions:
126
+ commerce/backend-ui/1:
127
+ $include: node_modules/configuration-management/actions/configurations/ext.config.yaml
128
+ ```
129
+
130
+ 2. Scaffolds a minimal `web-src/` bootstrap (if missing or previously auto-generated):
131
+
132
+ ```
133
+ web-src/
134
+ ├── index.html
135
+ └── src/
136
+ ├── index.js ← imports ConfigurationManagementApp from the package
137
+ ├── exc-runtime.js
138
+ └── config.json ← created empty; filled by aio app deploy
139
+ ```
140
+
141
+ Custom `web-src` files are left untouched unless they were created by a prior install
142
+ (files containing the `configuration-management: auto-generated bootstrap` marker, or
143
+ an older bootstrap that imports `configuration-management/web`).
144
+
145
+ - Run `npm install` from your App Builder project root (where `app.config.yaml` lives).
146
+ - Do not use `npm install --ignore-scripts` (that skips postinstall).
147
+
148
+ Opt out for a single install:
149
+
150
+ ```bash
151
+ CONFIGURATION_MANAGEMENT_SKIP_SETUP=1 npm install configuration-management
152
+ ```
153
+
154
+ Re-run manually anytime:
155
+
156
+ ```bash
157
+ npx configuration-management-setup
158
+ ```
159
+
160
+ #### Manual wiring
161
+
162
+ If you prefer to edit `app.config.yaml` yourself:
163
+
164
+ ```yaml
165
+ extensions:
166
+ commerce/backend-ui/1:
167
+ $include: node_modules/configuration-management/actions/configurations/ext.config.yaml
168
+ ```
169
+
170
+ The bundled `ext.config.yaml` declares all actions under the `ConfigurationManagement` package
171
+ (`system-config-list`, `system-config-save`, `system-config-schema`, `export-config`,
172
+ `import-config`, `commerce-rest-get`, `sync-store-mappings-from-commerce`) plus admin menu
173
+ `registration`. It expects a `web-src/` folder at your project root for the UI shell.
174
+
175
+ **Minimal host project layout:**
176
+
177
+ ```
178
+ my-app/
179
+ ├── app.config.yaml ← $include ext.config from node_modules (above)
180
+ ├── web-src/
181
+ │ ├── index.html
182
+ │ └── src/
183
+ │ ├── index.js ← import ConfigurationManagementApp + configureWeb
184
+ │ └── config.json ← generated by aio app deploy
185
+ ├── .env
186
+ └── package.json ← depends on configuration-management
187
+ ```
188
+
189
+ Action helper utilities are also exported for custom actions:
190
+
191
+ ```js
192
+ const { errorResponse, checkMissingRequestInputs } = require('configuration-management/actions/utils')
193
+ ```
194
+
195
+ ## Environment / action inputs
196
+
197
+ | Variable | Purpose |
198
+ |----------|---------|
199
+ | `AIO_DB_REGION` | ABDB region (`amer`, `emea`, …) |
200
+ | `OAUTH_CLIENT_ID`, `OAUTH_CLIENT_SECRET`, `OAUTH_ORG_ID`, `OAUTH_SCOPES` | IMS credentials for ABDB |
201
+ | `SYSTEM_CONFIG_CRYPT_KEY` | Preferred encryption key (fallback: `OAUTH_CLIENT_SECRET`) |
202
+ | `COMMERCE_BASE_URL`, `COMMERCE_CONSUMER_*`, `COMMERCE_ACCESS_TOKEN*` | Commerce REST (for scope code resolution) |
203
+
204
+ ## Storage model
205
+
206
+ Documents in the `system_config_data` collection:
207
+
208
+ ```
209
+ { _id, scope, scope_id, path, value, createdAt, updatedAt }
210
+ ```
211
+
212
+ Config paths use the format `section/group/field` (e.g. `sync_general/api/url`).
213
+
214
+ ## License
215
+
216
+ Apache-2.0
@@ -0,0 +1,151 @@
1
+ operations:
2
+ view:
3
+ - type: web
4
+ impl: index.html
5
+ # Action sources live alongside this manifest (same directory).
6
+ actions: .
7
+ # Host App Builder apps override `web` to point at their UI shell (see README).
8
+ web: ../../../../web-src
9
+ runtimeManifest:
10
+ packages:
11
+ admin-ui-sdk:
12
+ license: Apache-2.0
13
+ actions:
14
+ registration:
15
+ function: registration/index.js
16
+ web: 'yes'
17
+ runtime: 'nodejs:20'
18
+ inputs:
19
+ LOG_LEVEL: debug
20
+ annotations:
21
+ require-adobe-auth: true
22
+ final: true
23
+ ConfigurationManagement:
24
+ license: Apache-2.0
25
+ actions:
26
+ commerce-rest-get:
27
+ function: commerce/index.js
28
+ web: 'yes'
29
+ runtime: 'nodejs:20'
30
+ inputs:
31
+ LOG_LEVEL: debug
32
+ COMMERCE_BASE_URL: $COMMERCE_BASE_URL
33
+ COMMERCE_CONSUMER_KEY: $COMMERCE_CONSUMER_KEY
34
+ COMMERCE_CONSUMER_SECRET: $COMMERCE_CONSUMER_SECRET
35
+ COMMERCE_ACCESS_TOKEN: $COMMERCE_ACCESS_TOKEN
36
+ COMMERCE_ACCESS_TOKEN_SECRET: $COMMERCE_ACCESS_TOKEN_SECRET
37
+ annotations:
38
+ require-adobe-auth: false
39
+ final: true
40
+ system-config-list:
41
+ function: system-config-list/index.js
42
+ web: 'yes'
43
+ runtime: 'nodejs:20'
44
+ inputs:
45
+ LOG_LEVEL: debug
46
+ SYSTEM_CONFIG_CRYPT_KEY: $SYSTEM_CONFIG_CRYPT_KEY
47
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
48
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
49
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
50
+ OAUTH_SCOPES: $OAUTH_SCOPES
51
+ AIO_DB_REGION: $AIO_DB_REGION
52
+ annotations:
53
+ require-adobe-auth: false
54
+ include-ims-credentials: true
55
+ final: true
56
+ system-config-save:
57
+ function: system-config-save/index.js
58
+ web: 'yes'
59
+ runtime: 'nodejs:20'
60
+ inputs:
61
+ LOG_LEVEL: debug
62
+ SYSTEM_CONFIG_CRYPT_KEY: $SYSTEM_CONFIG_CRYPT_KEY
63
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
64
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
65
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
66
+ OAUTH_SCOPES: $OAUTH_SCOPES
67
+ AIO_DB_REGION: $AIO_DB_REGION
68
+ annotations:
69
+ require-adobe-auth: false
70
+ include-ims-credentials: true
71
+ final: true
72
+ system-config-schema:
73
+ function: system-config-schema/index.js
74
+ web: 'yes'
75
+ runtime: 'nodejs:20'
76
+ inputs:
77
+ LOG_LEVEL: debug
78
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
79
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
80
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
81
+ OAUTH_SCOPES: $OAUTH_SCOPES
82
+ AIO_DB_REGION: $AIO_DB_REGION
83
+ annotations:
84
+ require-adobe-auth: false
85
+ include-ims-credentials: true
86
+ final: true
87
+ export-config:
88
+ function: export-config/index.js
89
+ web: 'yes'
90
+ runtime: 'nodejs:20'
91
+ inputs:
92
+ LOG_LEVEL: debug
93
+ SYSTEM_CONFIG_CRYPT_KEY: $SYSTEM_CONFIG_CRYPT_KEY
94
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
95
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
96
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
97
+ OAUTH_SCOPES: $OAUTH_SCOPES
98
+ AIO_DB_REGION: $AIO_DB_REGION
99
+ COMMERCE_BASE_URL: $COMMERCE_BASE_URL
100
+ COMMERCE_CONSUMER_KEY: $COMMERCE_CONSUMER_KEY
101
+ COMMERCE_CONSUMER_SECRET: $COMMERCE_CONSUMER_SECRET
102
+ COMMERCE_ACCESS_TOKEN: $COMMERCE_ACCESS_TOKEN
103
+ COMMERCE_ACCESS_TOKEN_SECRET: $COMMERCE_ACCESS_TOKEN_SECRET
104
+ annotations:
105
+ require-adobe-auth: false
106
+ include-ims-credentials: true
107
+ final: true
108
+ import-config:
109
+ function: import-config/index.js
110
+ web: 'yes'
111
+ runtime: 'nodejs:20'
112
+ limits:
113
+ timeout: 300000
114
+ memory: 512
115
+ inputs:
116
+ LOG_LEVEL: debug
117
+ SYSTEM_CONFIG_CRYPT_KEY: $SYSTEM_CONFIG_CRYPT_KEY
118
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
119
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
120
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
121
+ OAUTH_SCOPES: $OAUTH_SCOPES
122
+ AIO_DB_REGION: $AIO_DB_REGION
123
+ COMMERCE_BASE_URL: $COMMERCE_BASE_URL
124
+ COMMERCE_CONSUMER_KEY: $COMMERCE_CONSUMER_KEY
125
+ COMMERCE_CONSUMER_SECRET: $COMMERCE_CONSUMER_SECRET
126
+ COMMERCE_ACCESS_TOKEN: $COMMERCE_ACCESS_TOKEN
127
+ COMMERCE_ACCESS_TOKEN_SECRET: $COMMERCE_ACCESS_TOKEN_SECRET
128
+ annotations:
129
+ require-adobe-auth: false
130
+ include-ims-credentials: true
131
+ final: true
132
+ sync-store-mappings-from-commerce:
133
+ function: sync-store-mappings-from-commerce/index.js
134
+ web: 'yes'
135
+ runtime: 'nodejs:20'
136
+ inputs:
137
+ LOG_LEVEL: debug
138
+ OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID
139
+ OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET
140
+ OAUTH_ORG_ID: $OAUTH_ORG_ID
141
+ OAUTH_SCOPES: $OAUTH_SCOPES
142
+ AIO_DB_REGION: $AIO_DB_REGION
143
+ COMMERCE_BASE_URL: $COMMERCE_BASE_URL
144
+ COMMERCE_CONSUMER_KEY: $COMMERCE_CONSUMER_KEY
145
+ COMMERCE_CONSUMER_SECRET: $COMMERCE_CONSUMER_SECRET
146
+ COMMERCE_ACCESS_TOKEN: $COMMERCE_ACCESS_TOKEN
147
+ COMMERCE_ACCESS_TOKEN_SECRET: $COMMERCE_ACCESS_TOKEN_SECRET
148
+ annotations:
149
+ require-adobe-auth: false
150
+ include-ims-credentials: true
151
+ final: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configuration-management",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "Schema-driven system configuration for Adobe Commerce App Builder sync apps. Magento-style scoped config in Adobe App Builder Database (ABDB) with encryption, Commerce REST helpers, and React Admin UI.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Adobe Inc.",
@@ -16,10 +16,12 @@
16
16
  ],
17
17
  "main": "./src/index.js",
18
18
  "bin": {
19
- "configuration-management-setup": "./scripts/setup-app-config.js"
19
+ "configuration-management-setup": "./scripts/setup.js"
20
20
  },
21
21
  "scripts": {
22
- "postinstall": "node ./scripts/setup-app-config.js"
22
+ "build": "node ./scripts/build-web.js",
23
+ "prepublishOnly": "node ./scripts/build-web.js",
24
+ "postinstall": "node ./scripts/build-web.js && node ./scripts/setup.js"
23
25
  },
24
26
  "exports": {
25
27
  ".": "./src/index.js",
@@ -28,10 +30,10 @@
28
30
  "./crypto": "./src/system-config-crypto.js",
29
31
  "./shared": "./src/system-config-shared.js",
30
32
  "./oauth1a": "./src/oauth1a.js",
31
- "./web": "./web/index.js",
32
- "./web/index.js": "./web/index.js",
33
- "./web/src/styles/index.css": "./web/src/styles/index.css",
33
+ "./web": "./web/dist/index.js",
34
+ "./web/index.js": "./web/dist/index.js",
34
35
  "./web/styles.css": "./web/src/styles/index.css",
36
+ "./web/src/styles/index.css": "./web/src/styles/index.css",
35
37
  "./actions/utils": "./actions/utils.js",
36
38
  "./actions/ext.config.yaml": "./actions/configurations/ext.config.yaml"
37
39
  },
@@ -61,6 +63,7 @@
61
63
  "react-router-dom": "^6.8.1"
62
64
  },
63
65
  "dependencies": {
66
+ "esbuild": "^0.25.12",
64
67
  "got": "^11.8.5",
65
68
  "oauth-1.0a": "^2.2.6"
66
69
  },
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ Copyright 2025 Adobe. All rights reserved.
4
+ Licensed under the Apache License, Version 2.0
5
+ */
6
+
7
+ const fs = require('fs')
8
+ const path = require('path')
9
+
10
+ async function main () {
11
+ let esbuild
12
+ try {
13
+ esbuild = require('esbuild')
14
+ } catch {
15
+ console.error('[configuration-management] esbuild is required to build the web UI. Run npm install in the package directory.')
16
+ process.exit(1)
17
+ }
18
+
19
+ const pkgRoot = path.join(__dirname, '..')
20
+ const entry = path.join(pkgRoot, 'web/src/index.js')
21
+ const outdir = path.join(pkgRoot, 'web/dist')
22
+ const outfile = path.join(outdir, 'index.js')
23
+
24
+ fs.mkdirSync(outdir, { recursive: true })
25
+
26
+ await esbuild.build({
27
+ entryPoints: [entry],
28
+ bundle: true,
29
+ format: 'esm',
30
+ platform: 'browser',
31
+ outfile,
32
+ packages: 'external',
33
+ jsx: 'automatic',
34
+ loader: { '.js': 'jsx' },
35
+ target: ['chrome79', 'firefox85', 'safari13'],
36
+ logLevel: 'info'
37
+ })
38
+
39
+ console.log('[configuration-management] built web/dist/index.js')
40
+ }
41
+
42
+ if (require.main === module) {
43
+ main().catch((err) => {
44
+ console.error('[configuration-management] build-web failed:', err.message)
45
+ process.exit(1)
46
+ })
47
+ }
48
+
49
+ module.exports = { main }