@adobe/helix-config-storage 2.12.1 → 2.12.2
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/.claude/settings.local.json +7 -0
- package/.env +0 -0
- package/CLAUDE.md +47 -0
- package/package.json +5 -4
- package/src/config-validator.js +2 -0
- package/src/schemas/cdn-prod-akamai.schema.json +5 -3
- package/src/schemas/cdn-prod-cloudflare.schema.json +5 -3
- package/src/schemas/cdn-prod-cloudfront.schema.json +5 -3
- package/src/schemas/cdn-prod-fastly.schema.json +5 -3
- package/src/schemas/cdn-prod-managed.schema.json +5 -3
- package/src/schemas/cdn.schema.json +16 -8
package/.env
ADDED
|
File without changes
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Run all tests with coverage
|
|
9
|
+
npm test
|
|
10
|
+
|
|
11
|
+
# Run a single test file
|
|
12
|
+
npx mocha --spec 'test/config-store.test.js'
|
|
13
|
+
|
|
14
|
+
# Lint (ESLint + JSON schema validation)
|
|
15
|
+
npm run lint
|
|
16
|
+
|
|
17
|
+
# Validate JSON schemas only
|
|
18
|
+
./validate-json-schemas.sh
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
This is a Node.js library for managing configuration storage for Adobe Helix (Edge Delivery Services) projects. It provides CRUD operations for org, site, and profile configuration objects stored in a content bus via `@adobe/helix-shared-storage`.
|
|
24
|
+
|
|
25
|
+
### Core Concepts
|
|
26
|
+
|
|
27
|
+
- **Config types**: `org`, `sites`, `profiles` — stored at `/orgs/{org}/{type}/{name}.json`
|
|
28
|
+
- **Fragments**: Support for updating nested subpaths (e.g., `/cdn/prod`, `/secrets/{id}`) via parameterized deep-path operations
|
|
29
|
+
- **Profile merging**: Site configs can inherit from profiles; `config-merge.js` handles atomic/object/array union merge strategies
|
|
30
|
+
- **Versioning**: Auto-incrementing version history stored alongside each config
|
|
31
|
+
- **Access control gates**: `withAllowAdmin(bool)` and `withAllowOps(bool)` on the store control what callers may modify
|
|
32
|
+
|
|
33
|
+
### Key Files
|
|
34
|
+
|
|
35
|
+
- `src/config-store.js` — Main `ConfigStore` class with create/read/update/remove/validate methods
|
|
36
|
+
- `src/fragment.js` — Fragment path parsing and application for nested updates
|
|
37
|
+
- `src/config-merge.js` — Profile/site merge logic (atomic vs. deep-merge vs. array-union per property)
|
|
38
|
+
- `src/config-validator.js` — AJV-based schema validation across 40+ JSON schemas in `src/schemas/`
|
|
39
|
+
- `src/config-versioning.js` — Version history management
|
|
40
|
+
- `src/utils.js` — Helpers for users, tokens, secrets, content/code source detection
|
|
41
|
+
|
|
42
|
+
### Patterns
|
|
43
|
+
|
|
44
|
+
- All operations accept a `ctx` object providing storage access (`HelixStorage.fromContext(ctx).configBus()`) and logging (`ctx.log`)
|
|
45
|
+
- Sensitive fields (secrets, tokens) are redacted on read — only metadata is returned
|
|
46
|
+
- Schema validation uses AJV with coercion and defaults enabled
|
|
47
|
+
- The `Fragment` class handles parameterized sub-paths; arrays and objects within configs use different merge strategies
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-config-storage",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.2",
|
|
4
4
|
"description": "Helix Config Storage",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -36,18 +36,18 @@
|
|
|
36
36
|
"reporter-options": "configFile=.mocha-multi.json"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@adobe/eslint-config-helix": "3.0.
|
|
39
|
+
"@adobe/eslint-config-helix": "3.0.22",
|
|
40
40
|
"@eslint/config-helpers": "0.5.2",
|
|
41
41
|
"@semantic-release/changelog": "6.0.3",
|
|
42
42
|
"@semantic-release/git": "10.0.1",
|
|
43
|
-
"@semantic-release/npm": "13.1.
|
|
43
|
+
"@semantic-release/npm": "13.1.5",
|
|
44
44
|
"ajv-cli": "5.0.0",
|
|
45
45
|
"c8": "11.0.0",
|
|
46
46
|
"eslint": "9.4.0",
|
|
47
47
|
"husky": "9.1.7",
|
|
48
48
|
"json-schema-to-typescript": "15.0.4",
|
|
49
49
|
"junit-report-builder": "5.1.1",
|
|
50
|
-
"lint-staged": "16.
|
|
50
|
+
"lint-staged": "16.3.1",
|
|
51
51
|
"mocha": "11.7.5",
|
|
52
52
|
"mocha-multi-reporters": "1.5.1",
|
|
53
53
|
"mocha-suppress-logs": "0.6.0",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"@adobe/helix-shared-string": "^2.1.0",
|
|
69
69
|
"@adobe/helix-shared-utils": "^3.0.2",
|
|
70
70
|
"ajv": "8.18.0",
|
|
71
|
+
"ajv-errors": "^3.0.0",
|
|
71
72
|
"ajv-formats": "3.0.1",
|
|
72
73
|
"jose": "6.1.3"
|
|
73
74
|
}
|
package/src/config-validator.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
import Ajv2019 from 'ajv/dist/2019.js';
|
|
13
|
+
import ajvErrors from 'ajv-errors';
|
|
13
14
|
import ajvFormats from 'ajv-formats';
|
|
14
15
|
import { ValidationError } from './ValidationError.js';
|
|
15
16
|
|
|
@@ -114,6 +115,7 @@ export async function validate(config, type) {
|
|
|
114
115
|
strict: false,
|
|
115
116
|
});
|
|
116
117
|
ajvFormats(ajv);
|
|
118
|
+
ajvErrors(ajv);
|
|
117
119
|
|
|
118
120
|
ajv.addSchema(SCHEMAS);
|
|
119
121
|
const res = ajv.validate(schema, config);
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"host": {
|
|
13
13
|
"description": "production host",
|
|
14
14
|
"type": "string",
|
|
15
|
-
"pattern": "
|
|
15
|
+
"pattern": "^$|^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
16
16
|
"not": {
|
|
17
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
-
|
|
17
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
+
},
|
|
19
|
+
"errorMessage": {
|
|
20
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
"route": {
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"host": {
|
|
13
13
|
"description": "production host",
|
|
14
14
|
"type": "string",
|
|
15
|
-
"pattern": "
|
|
15
|
+
"pattern": "^$|^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
16
16
|
"not": {
|
|
17
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
-
|
|
17
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
+
},
|
|
19
|
+
"errorMessage": {
|
|
20
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
"route": {
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"host": {
|
|
13
13
|
"description": "production host",
|
|
14
14
|
"type": "string",
|
|
15
|
-
"pattern": "
|
|
15
|
+
"pattern": "^$|^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
16
16
|
"not": {
|
|
17
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
-
|
|
17
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
+
},
|
|
19
|
+
"errorMessage": {
|
|
20
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
"route": {
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
"host": {
|
|
14
14
|
"description": "production host",
|
|
15
15
|
"type": "string",
|
|
16
|
-
"pattern": "
|
|
16
|
+
"pattern": "^$|^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
17
17
|
"not": {
|
|
18
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
19
|
-
|
|
18
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
19
|
+
},
|
|
20
|
+
"errorMessage": {
|
|
21
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
20
22
|
}
|
|
21
23
|
},
|
|
22
24
|
"route": {
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"host": {
|
|
13
13
|
"description": "production host",
|
|
14
14
|
"type": "string",
|
|
15
|
-
"pattern": "
|
|
15
|
+
"pattern": "^$|^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
16
16
|
"not": {
|
|
17
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
-
|
|
17
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
18
|
+
},
|
|
19
|
+
"errorMessage": {
|
|
20
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
"envId": {
|
|
@@ -31,8 +31,10 @@
|
|
|
31
31
|
"type": "string",
|
|
32
32
|
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.){1,3}[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$",
|
|
33
33
|
"not": {
|
|
34
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
35
|
-
|
|
34
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
35
|
+
},
|
|
36
|
+
"errorMessage": {
|
|
37
|
+
"not": "AEM endpoints are not allowed as /cdn/prod/host"
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
},
|
|
@@ -53,8 +55,10 @@
|
|
|
53
55
|
],
|
|
54
56
|
"type": "string",
|
|
55
57
|
"not": {
|
|
56
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
57
|
-
|
|
58
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
59
|
+
},
|
|
60
|
+
"errorMessage": {
|
|
61
|
+
"not": "AEM endpoints are not allowed as /cdn/live/host"
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
},
|
|
@@ -73,8 +77,10 @@
|
|
|
73
77
|
],
|
|
74
78
|
"type": "string",
|
|
75
79
|
"not": {
|
|
76
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
77
|
-
|
|
80
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
81
|
+
},
|
|
82
|
+
"errorMessage": {
|
|
83
|
+
"not": "AEM endpoints are not allowed as /cdn/preview/host"
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
},
|
|
@@ -93,8 +99,10 @@
|
|
|
93
99
|
],
|
|
94
100
|
"type": "string",
|
|
95
101
|
"not": {
|
|
96
|
-
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
97
|
-
|
|
102
|
+
"pattern": ".*--.*--.*\\.aem\\.(live|page|reviews|network)$"
|
|
103
|
+
},
|
|
104
|
+
"errorMessage": {
|
|
105
|
+
"not": "AEM endpoints are not allowed as /cdn/review/host"
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
},
|