@adobe/helix-config 1.3.3 → 2.0.0
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/CHANGELOG.md +12 -0
- package/package.json +5 -1
- package/src/ConfigContext.d.ts +2 -2
- package/src/ConfigContext.js +3 -3
- package/src/S3Loader.d.ts +32 -0
- package/src/config-legacy.js +11 -10
- package/src/config-view.js +18 -15
- package/src/domain-view.js +10 -10
- package/src/index.d.ts +3 -0
- package/src/HelixStorage.ts +0 -47
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [2.0.0](https://github.com/adobe/helix-config/compare/v1.3.3...v2.0.0) (2024-03-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* refactor s3 loader abstraction ([#31](https://github.com/adobe/helix-config/issues/31)) ([086cce5](https://github.com/adobe/helix-config/commit/086cce51e76da932ed68acef095e262db0e50be5))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* replace HelixStorage with S3Loader
|
|
12
|
+
|
|
1
13
|
## [1.3.3](https://github.com/adobe/helix-config/compare/v1.3.2...v1.3.3) (2024-03-14)
|
|
2
14
|
|
|
3
15
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Helix Config",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
6
10
|
"type": "module",
|
|
7
11
|
"scripts": {
|
|
8
12
|
"test": "c8 mocha",
|
package/src/ConfigContext.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* OF ANY KIND; either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import {S3Loader} from "./S3Loader";
|
|
13
13
|
|
|
14
14
|
type Fetch = (url: string|Request, options?: RequestOptions) => Promise<Response>;
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ export declare enum ConfigScope {
|
|
|
23
23
|
export declare class ConfigContext {
|
|
24
24
|
withLog(log: Console): ConfigContext;
|
|
25
25
|
withEnv(env: object): ConfigContext;
|
|
26
|
-
|
|
26
|
+
withS3Loader(loader: S3Loader): ConfigContext;
|
|
27
27
|
withFetch(fetch: Fetch): ConfigContext;
|
|
28
28
|
}
|
|
29
29
|
|
package/src/ConfigContext.js
CHANGED
|
@@ -45,7 +45,7 @@ export class ConfigContext {
|
|
|
45
45
|
|
|
46
46
|
env = {};
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
loader = null;
|
|
49
49
|
|
|
50
50
|
fetch = null;
|
|
51
51
|
|
|
@@ -59,8 +59,8 @@ export class ConfigContext {
|
|
|
59
59
|
return this;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
this.
|
|
62
|
+
withS3Loader(loader) {
|
|
63
|
+
this.loader = loader;
|
|
64
64
|
return this;
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 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
|
+
import {PipelineResponse} from "./PipelineResponse";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* S3 Loader abstration used to load S3 objects.
|
|
17
|
+
*/
|
|
18
|
+
export declare interface S3Loader {
|
|
19
|
+
/**
|
|
20
|
+
* Loads a S3 object from the given bucket and key.
|
|
21
|
+
* @param {string} bucketId
|
|
22
|
+
* @param {string} key
|
|
23
|
+
*/
|
|
24
|
+
getObject(bucketId, key): Promise<PipelineResponse>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves the head metadata of a S3 object from the given bucket and key.
|
|
28
|
+
* @param {string} bucketId
|
|
29
|
+
* @param {string} key
|
|
30
|
+
*/
|
|
31
|
+
headObject(bucketId, key): Promise<PipelineResponse>;
|
|
32
|
+
}
|
package/src/config-legacy.js
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { SCOPE_PIPELINE } from './ConfigContext.js';
|
|
13
13
|
|
|
14
|
+
const HELIX_CODE_BUS = 'helix-code-bus';
|
|
15
|
+
|
|
16
|
+
const HELIX_CONTENT_BUS = 'helix-content-bus';
|
|
17
|
+
|
|
14
18
|
/**
|
|
15
19
|
* Retrieves the helix-config.json which is an aggregate from fstab.yaml and head.html.
|
|
16
20
|
* Note: it always uses the branch `main`.
|
|
@@ -20,16 +24,14 @@ import { SCOPE_PIPELINE } from './ConfigContext.js';
|
|
|
20
24
|
* @returns {Promise<HelixConfig|null>} the helix-config or {@code null} if optional and not found.
|
|
21
25
|
*/
|
|
22
26
|
async function fetchHelixConfig(ctx, rso) {
|
|
23
|
-
const codeBus = ctx.storage.codeBus();
|
|
24
27
|
const key = `${rso.org}/${rso.site}/main/helix-config.json`;
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
if (!data) {
|
|
28
|
+
const res = await ctx.loader.getObject(HELIX_CODE_BUS, key);
|
|
29
|
+
if (!res.body) {
|
|
28
30
|
return null;
|
|
29
31
|
}
|
|
30
|
-
const config =
|
|
32
|
+
const config = res.json();
|
|
31
33
|
// set contentbus id, if present in header
|
|
32
|
-
const cbid =
|
|
34
|
+
const cbid = res.headers.get('x-amz-meta-x-contentbus-id');
|
|
33
35
|
if (cbid && !config.content) {
|
|
34
36
|
// create the content section if not already present
|
|
35
37
|
config.content = {
|
|
@@ -57,13 +59,12 @@ async function fetchHelixConfig(ctx, rso) {
|
|
|
57
59
|
* @returns {Promise<ConfigAll|null>} the project configuration
|
|
58
60
|
*/
|
|
59
61
|
async function fetchConfigAll(ctx, contentBusId, partition) {
|
|
60
|
-
const contentBus = ctx.storage.contentBus();
|
|
61
62
|
const key = `${contentBusId}/${partition}/.helix/config-all.json`;
|
|
62
|
-
const
|
|
63
|
-
if (!
|
|
63
|
+
const res = await ctx.loader.getObject(HELIX_CONTENT_BUS, key);
|
|
64
|
+
if (!res.body) {
|
|
64
65
|
return null;
|
|
65
66
|
}
|
|
66
|
-
return
|
|
67
|
+
return res.json();
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
/**
|
package/src/config-view.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
import { ModifiersConfig } from '@adobe/helix-shared-config';
|
|
12
|
+
import { ModifiersConfig } from '@adobe/helix-shared-config/modifiers';
|
|
13
13
|
import { computeSurrogateKey } from '@adobe/helix-shared-utils';
|
|
14
14
|
import { PipelineResponse } from './PipelineResponse.js';
|
|
15
15
|
import { SCOPE_ADMIN, SCOPE_PIPELINE, SCOPE_DELIVERY } from './ConfigContext.js';
|
|
@@ -34,6 +34,12 @@ import { resolveLegacyConfig } from './config-legacy.js';
|
|
|
34
34
|
|
|
35
35
|
const METADATA_JSON = '/metadata.json';
|
|
36
36
|
|
|
37
|
+
const HELIX_CODE_BUS = 'helix-code-bus';
|
|
38
|
+
|
|
39
|
+
const HELIX_CONFIG_BUS = 'helix-config-bus';
|
|
40
|
+
|
|
41
|
+
const HELIX_CONTENT_BUS = 'helix-content-bus';
|
|
42
|
+
|
|
37
43
|
export function toArray(v) {
|
|
38
44
|
if (!v) {
|
|
39
45
|
return [];
|
|
@@ -77,7 +83,6 @@ export function getAccessConfig(access, partition) {
|
|
|
77
83
|
* @returns {Promise<{data: ModifierMap}|{}>} the metadata
|
|
78
84
|
*/
|
|
79
85
|
async function loadMetadata(ctx, config, partition) {
|
|
80
|
-
const contentBus = ctx.storage.contentBus();
|
|
81
86
|
const paths = config.metadata?.source ?? [];
|
|
82
87
|
if (!paths.length) {
|
|
83
88
|
paths.push(METADATA_JSON);
|
|
@@ -86,11 +91,11 @@ async function loadMetadata(ctx, config, partition) {
|
|
|
86
91
|
// generate the metadata-all.json first
|
|
87
92
|
const metadata = [];
|
|
88
93
|
for (const path of paths) {
|
|
89
|
-
const key =
|
|
94
|
+
const key = `${config.content.contentBusId}/${partition}${path}`;
|
|
90
95
|
// eslint-disable-next-line no-await-in-loop
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
const json =
|
|
96
|
+
const res = await ctx.loader.getObject(HELIX_CONTENT_BUS, key);
|
|
97
|
+
if (res.body) {
|
|
98
|
+
const json = res.json();
|
|
94
99
|
const data = json.data || json.default?.data;
|
|
95
100
|
if (data) {
|
|
96
101
|
metadata.push(...data);
|
|
@@ -109,12 +114,11 @@ async function loadMetadata(ctx, config, partition) {
|
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
async function loadHeadHtml(ctx, config, ref) {
|
|
112
|
-
const codeBus = ctx.storage.codeBus();
|
|
113
117
|
const key = `${config.code.owner}/${config.code.repo}/${ref}/head.html`;
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
118
|
+
const res = await ctx.loader.getObject(HELIX_CODE_BUS, key);
|
|
119
|
+
if (res.body) {
|
|
116
120
|
return {
|
|
117
|
-
html:
|
|
121
|
+
html: res.body,
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
return {};
|
|
@@ -143,17 +147,16 @@ function retainProperty(obj, prop) {
|
|
|
143
147
|
*/
|
|
144
148
|
async function resolveConfig(ctx, rso, scope) {
|
|
145
149
|
// try to load site config from config-bus
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
if (!buf) {
|
|
150
|
+
const key = `orgs/${rso.org}/sites/${rso.site}.json`;
|
|
151
|
+
const res = await ctx.loader.getObject(HELIX_CONFIG_BUS, key);
|
|
152
|
+
if (!res.body) {
|
|
150
153
|
if (scope !== SCOPE_ADMIN) {
|
|
151
154
|
return resolveLegacyConfig(ctx, rso, scope);
|
|
152
155
|
} else {
|
|
153
156
|
return null;
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
|
-
const config =
|
|
159
|
+
const config = res.json();
|
|
157
160
|
if (scope === SCOPE_PIPELINE) {
|
|
158
161
|
config.metadata = {
|
|
159
162
|
preview: await loadMetadata(ctx, config, 'preview'),
|
package/src/domain-view.js
CHANGED
|
@@ -12,10 +12,16 @@
|
|
|
12
12
|
import { PipelineResponse } from './PipelineResponse.js';
|
|
13
13
|
|
|
14
14
|
export async function getDomainResponse(ctx, domain) {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const res = await ctx.loader.headObject('helix-config-bus', `domains/${domain}`);
|
|
16
|
+
const location = res.headers.get('x-amz-meta-location');
|
|
17
|
+
if (res.status === 200 && location) {
|
|
18
|
+
return new PipelineResponse('', {
|
|
19
|
+
status: 200,
|
|
20
|
+
headers: {
|
|
21
|
+
location,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
19
25
|
return new PipelineResponse('', {
|
|
20
26
|
status: 404,
|
|
21
27
|
headers: {
|
|
@@ -23,10 +29,4 @@ export async function getDomainResponse(ctx, domain) {
|
|
|
23
29
|
},
|
|
24
30
|
});
|
|
25
31
|
}
|
|
26
|
-
return new PipelineResponse('', {
|
|
27
|
-
status: 200,
|
|
28
|
-
headers: {
|
|
29
|
-
Location: data.Metadata.location,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
32
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
import { PipelineResponse } from './PipelineResponse';
|
|
13
13
|
import { ConfigContext, ConfigScope } from "./ConfigContext";
|
|
14
14
|
|
|
15
|
+
export * from './PipelineResponse';
|
|
16
|
+
export * from './S3Loader';
|
|
17
|
+
|
|
15
18
|
export declare class ConfigRequestOptions {
|
|
16
19
|
scope: ConfigScope;
|
|
17
20
|
org: string;
|
package/src/HelixStorage.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2024 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
|
-
export declare interface Bucket {
|
|
13
|
-
/**
|
|
14
|
-
* Return an object contents.
|
|
15
|
-
*
|
|
16
|
-
* @param {string} key object key
|
|
17
|
-
* @param {object} [meta] output object to receive metadata if specified
|
|
18
|
-
* @returns {Promise<Buffer>}object contents as a Buffer or null if no found.
|
|
19
|
-
* @throws an error if the object could not be loaded due to an unexpected error.
|
|
20
|
-
*/
|
|
21
|
-
get(key:string, meta?:object): Promise<Buffer|null>
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Performs a head request
|
|
25
|
-
* @param key
|
|
26
|
-
* @returns the head metadata or null
|
|
27
|
-
*/
|
|
28
|
-
head(key:string): Promise<object|null>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export declare interface HelixStorage {
|
|
32
|
-
/**
|
|
33
|
-
* Returns a bucket with the given identifier.
|
|
34
|
-
* @param {string} bucketId
|
|
35
|
-
* @returns {Bucket} the s3 object or null if not found
|
|
36
|
-
* @throws {Error} if the s3 object cannot be retrieved
|
|
37
|
-
*/
|
|
38
|
-
bucket(bucketId:string): Bucket;
|
|
39
|
-
|
|
40
|
-
contentBus(): Bucket;
|
|
41
|
-
|
|
42
|
-
codeBus(): Bucket;
|
|
43
|
-
|
|
44
|
-
configBus(): Bucket;
|
|
45
|
-
|
|
46
|
-
mediaBus(): Bucket;
|
|
47
|
-
}
|