@adobe/helix-config 3.6.2 → 3.7.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 CHANGED
@@ -1,3 +1,17 @@
1
+ # [3.7.0](https://github.com/adobe/helix-config/compare/v3.6.3...v3.7.0) (2024-07-17)
2
+
3
+
4
+ ### Features
5
+
6
+ * add more meaningful errors ([#136](https://github.com/adobe/helix-config/issues/136)) ([04bc71c](https://github.com/adobe/helix-config/commit/04bc71c1d95489f383bdbcedaaefd78cdfd13818)), closes [#116](https://github.com/adobe/helix-config/issues/116) [#130](https://github.com/adobe/helix-config/issues/130)
7
+
8
+ ## [3.6.3](https://github.com/adobe/helix-config/compare/v3.6.2...v3.6.3) (2024-07-17)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency @adobe/helix-shared-storage to v1.0.3 ([57786d2](https://github.com/adobe/helix-config/commit/57786d222a5a6161957c5c57aa149b74000aea36))
14
+
1
15
  ## [3.6.2](https://github.com/adobe/helix-config/compare/v3.6.1...v3.6.2) (2024-07-13)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-config",
3
- "version": "3.6.2",
3
+ "version": "3.7.0",
4
4
  "description": "Helix Config",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -62,7 +62,7 @@
62
62
  "@adobe/fetch": "4.1.8",
63
63
  "@adobe/helix-shared-config": "10.6.4",
64
64
  "@adobe/helix-shared-git": "3.0.12",
65
- "@adobe/helix-shared-storage": "1.0.2",
65
+ "@adobe/helix-shared-storage": "1.0.3",
66
66
  "@adobe/helix-shared-utils": "3.0.2",
67
67
  "ajv": "8.17.1",
68
68
  "ajv-formats": "3.0.1",
@@ -0,0 +1,12 @@
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
+ module.exports = require('./cdn-prod-akamai.schema.json');
@@ -0,0 +1,55 @@
1
+ {
2
+ "meta:license": [
3
+ "Copyright 2023 Adobe. All rights reserved.",
4
+ "This file is licensed to you under the Apache License, Version 2.0 (the \"License\");",
5
+ "you may not use this file except in compliance with the License. You may obtain a copy",
6
+ "of the License at http://www.apache.org/licenses/LICENSE-2.0",
7
+ "",
8
+ "Unless required by applicable law or agreed to in writing, software distributed under",
9
+ "the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS",
10
+ "OF ANY KIND, either express or implied. See the License for the specific language",
11
+ "governing permissions and limitations under the License."
12
+ ],
13
+ "$id": "https://ns.adobe.com/helix/config/cdn/prod/akamai",
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "title": "Akamai CDN Config",
16
+ "type": "object",
17
+ "properties": {
18
+ "type": {
19
+ "type": "string",
20
+ "const": "akamai"
21
+ },
22
+ "host": {
23
+ "description": "production host",
24
+ "type": "string"
25
+ },
26
+ "route": {
27
+ "description": "Routes on the CDN that are rendered with Franklin",
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ },
33
+ "endpoint": {
34
+ "type": "string"
35
+ },
36
+ "clientSecret": {
37
+ "type": "string"
38
+ },
39
+ "clientToken": {
40
+ "type": "string"
41
+ },
42
+ "accessToken": {
43
+ "type": "string"
44
+ }
45
+ },
46
+ "required": [
47
+ "type",
48
+ "host",
49
+ "endpoint",
50
+ "clientSecret",
51
+ "clientToken",
52
+ "accessToken"
53
+ ],
54
+ "additionalProperties": false
55
+ }
@@ -0,0 +1,12 @@
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
+ module.exports = require('./cdn-prod-cloudflare.schema.json');
@@ -0,0 +1,51 @@
1
+ {
2
+ "meta:license": [
3
+ "Copyright 2023 Adobe. All rights reserved.",
4
+ "This file is licensed to you under the Apache License, Version 2.0 (the \"License\");",
5
+ "you may not use this file except in compliance with the License. You may obtain a copy",
6
+ "of the License at http://www.apache.org/licenses/LICENSE-2.0",
7
+ "",
8
+ "Unless required by applicable law or agreed to in writing, software distributed under",
9
+ "the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS",
10
+ "OF ANY KIND, either express or implied. See the License for the specific language",
11
+ "governing permissions and limitations under the License."
12
+ ],
13
+ "$id": "https://ns.adobe.com/helix/config/cdn/prod/cloudflare",
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "title": "Cloudflare CDN Config",
16
+ "type": "object",
17
+ "properties": {
18
+ "type": {
19
+ "type": "string",
20
+ "const": "cloudflare"
21
+ },
22
+ "host": {
23
+ "description": "production host",
24
+ "type": "string"
25
+ },
26
+ "route": {
27
+ "description": "Routes on the CDN that are rendered with Franklin",
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ },
33
+ "plan": {
34
+ "type": "string"
35
+ },
36
+ "zoneId": {
37
+ "type": "string"
38
+ },
39
+ "apiToken": {
40
+ "type": "string"
41
+ }
42
+ },
43
+ "required": [
44
+ "type",
45
+ "host",
46
+ "plan",
47
+ "zoneId",
48
+ "apiToken"
49
+ ],
50
+ "additionalProperties": false
51
+ }
@@ -0,0 +1,12 @@
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
+ module.exports = require('./cdn-prod-cloudfront.schema.json');
@@ -0,0 +1,51 @@
1
+ {
2
+ "meta:license": [
3
+ "Copyright 2023 Adobe. All rights reserved.",
4
+ "This file is licensed to you under the Apache License, Version 2.0 (the \"License\");",
5
+ "you may not use this file except in compliance with the License. You may obtain a copy",
6
+ "of the License at http://www.apache.org/licenses/LICENSE-2.0",
7
+ "",
8
+ "Unless required by applicable law or agreed to in writing, software distributed under",
9
+ "the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS",
10
+ "OF ANY KIND, either express or implied. See the License for the specific language",
11
+ "governing permissions and limitations under the License."
12
+ ],
13
+ "$id": "https://ns.adobe.com/helix/config/cdn/prod/cloudfront",
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "title": "Cloudfront CDN Config",
16
+ "type": "object",
17
+ "properties": {
18
+ "type": {
19
+ "type": "string",
20
+ "const": "cloudfront"
21
+ },
22
+ "host": {
23
+ "description": "production host",
24
+ "type": "string"
25
+ },
26
+ "route": {
27
+ "description": "Routes on the CDN that are rendered with Franklin",
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ },
33
+ "distributionId": {
34
+ "type": "string"
35
+ },
36
+ "accessKeyId": {
37
+ "type": "string"
38
+ },
39
+ "secretAccessKey": {
40
+ "type": "string"
41
+ }
42
+ },
43
+ "required": [
44
+ "type",
45
+ "host",
46
+ "distributionId",
47
+ "accessKeyId",
48
+ "secretAccessKey"
49
+ ],
50
+ "additionalProperties": false
51
+ }
@@ -0,0 +1,12 @@
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
+ module.exports = require('./cdn-prod-fastly.schema.json');
@@ -0,0 +1,50 @@
1
+ {
2
+ "meta:license": [
3
+ "Copyright 2023 Adobe. All rights reserved.",
4
+ "This file is licensed to you under the Apache License, Version 2.0 (the \"License\");",
5
+ "you may not use this file except in compliance with the License. You may obtain a copy",
6
+ "of the License at http://www.apache.org/licenses/LICENSE-2.0",
7
+ "",
8
+ "Unless required by applicable law or agreed to in writing, software distributed under",
9
+ "the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS",
10
+ "OF ANY KIND, either express or implied. See the License for the specific language",
11
+ "governing permissions and limitations under the License."
12
+ ],
13
+ "$id": "https://ns.adobe.com/helix/config/cdn/prod/fastly",
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "title": "Fastly CDN Config",
16
+ "type": "object",
17
+ "description": "Production CDN configuration for Fastly",
18
+ "properties": {
19
+ "type": {
20
+ "type": "string",
21
+ "const": "fastly"
22
+ },
23
+ "host": {
24
+ "description": "production host",
25
+ "type": "string"
26
+ },
27
+ "route": {
28
+ "description": "Routes on the CDN that are rendered with Franklin",
29
+ "type": "array",
30
+ "items": {
31
+ "type": "string"
32
+ }
33
+ },
34
+ "serviceId": {
35
+ "description": "The Fastly Service ID",
36
+ "type": "string"
37
+ },
38
+ "authToken": {
39
+ "description": "A Fastly token for purging",
40
+ "type": "string"
41
+ }
42
+ },
43
+ "required": [
44
+ "type",
45
+ "host",
46
+ "serviceId",
47
+ "authToken"
48
+ ],
49
+ "additionalProperties": false
50
+ }
@@ -0,0 +1,12 @@
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
+ module.exports = require('./cdn-prod-managed.schema.json');
@@ -0,0 +1,39 @@
1
+ {
2
+ "meta:license": [
3
+ "Copyright 2023 Adobe. All rights reserved.",
4
+ "This file is licensed to you under the Apache License, Version 2.0 (the \"License\");",
5
+ "you may not use this file except in compliance with the License. You may obtain a copy",
6
+ "of the License at http://www.apache.org/licenses/LICENSE-2.0",
7
+ "",
8
+ "Unless required by applicable law or agreed to in writing, software distributed under",
9
+ "the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS",
10
+ "OF ANY KIND, either express or implied. See the License for the specific language",
11
+ "governing permissions and limitations under the License."
12
+ ],
13
+ "$id": "https://ns.adobe.com/helix/config/cdn/prod/managed",
14
+ "$schema": "http://json-schema.org/draft-07/schema#",
15
+ "title": "Managed CDN Config",
16
+ "type": "object",
17
+ "properties": {
18
+ "type": {
19
+ "type": "string",
20
+ "const": "managed"
21
+ },
22
+ "host": {
23
+ "description": "production host",
24
+ "type": "string"
25
+ },
26
+ "route": {
27
+ "description": "Routes on the CDN that are rendered with Franklin",
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ }
33
+ },
34
+ "required": [
35
+ "type",
36
+ "host"
37
+ ],
38
+ "additionalProperties": false
39
+ }
@@ -18,189 +18,19 @@
18
18
  "prod": {
19
19
  "oneOf": [
20
20
  {
21
- "type": "object",
22
- "title": "FastlyConfig",
23
- "description": "Production CDN configuration for Fastly",
24
- "properties": {
25
- "type": {
26
- "type": "string",
27
- "const": "fastly"
28
- },
29
- "host": {
30
- "description": "production host",
31
- "type": "string"
32
- },
33
- "route": {
34
- "description": "Routes on the CDN that are rendered with Franklin",
35
- "type": "array",
36
- "items": {
37
- "type": "string"
38
- }
39
- },
40
- "serviceId": {
41
- "description": "The Fastly Service ID",
42
- "type": "string"
43
- },
44
- "authToken": {
45
- "description": "A Fastly token for purging",
46
- "type": "string"
47
- }
48
- },
49
- "required": [
50
- "type",
51
- "host",
52
- "serviceId",
53
- "authToken"
54
- ],
55
- "additionalProperties": false
21
+ "$ref": "https://ns.adobe.com/helix/config/cdn/prod/fastly"
56
22
  },
57
23
  {
58
- "type": "object",
59
- "title": "AkamaiConfig",
60
- "properties": {
61
- "type": {
62
- "type": "string",
63
- "const": "akamai"
64
- },
65
- "host": {
66
- "description": "production host",
67
- "type": "string"
68
- },
69
- "route": {
70
- "description": "Routes on the CDN that are rendered with Franklin",
71
- "type": "array",
72
- "items": {
73
- "type": "string"
74
- }
75
- },
76
- "endpoint": {
77
- "type": "string"
78
- },
79
- "clientSecret": {
80
- "type": "string"
81
- },
82
- "clientToken": {
83
- "type": "string"
84
- },
85
- "accessToken": {
86
- "type": "string"
87
- }
88
- },
89
- "required": [
90
- "type",
91
- "host",
92
- "endpoint",
93
- "clientSecret",
94
- "clientToken",
95
- "accessToken"
96
- ],
97
- "additionalProperties": false
24
+ "$ref": "https://ns.adobe.com/helix/config/cdn/prod/cloudflare"
98
25
  },
99
26
  {
100
- "type": "object",
101
- "title": "CloudflareConfig",
102
- "properties": {
103
- "type": {
104
- "type": "string",
105
- "const": "cloudflare"
106
- },
107
- "host": {
108
- "description": "production host",
109
- "type": "string"
110
- },
111
- "route": {
112
- "description": "Routes on the CDN that are rendered with Franklin",
113
- "type": "array",
114
- "items": {
115
- "type": "string"
116
- }
117
- },
118
- "origin": {
119
- "type": "string"
120
- },
121
- "plan": {
122
- "type": "string"
123
- },
124
- "zoneId": {
125
- "type": "string"
126
- },
127
- "apiToken": {
128
- "type": "string"
129
- }
130
- },
131
- "required": [
132
- "type",
133
- "host",
134
- "origin",
135
- "plan",
136
- "zoneId",
137
- "apiToken"
138
- ],
139
- "additionalProperties": false
27
+ "$ref": "https://ns.adobe.com/helix/config/cdn/prod/akamai"
140
28
  },
141
29
  {
142
- "type": "object",
143
- "title": "ManagedConfig",
144
- "properties": {
145
- "type": {
146
- "type": "string",
147
- "const": "managed"
148
- },
149
- "host": {
150
- "description": "production host",
151
- "type": "string"
152
- },
153
- "route": {
154
- "description": "Routes on the CDN that are rendered with Franklin",
155
- "type": "array",
156
- "items": {
157
- "type": "string"
158
- }
159
- }
160
- },
161
- "required": [
162
- "type",
163
- "host"
164
- ],
165
- "additionalProperties": false
30
+ "$ref": "https://ns.adobe.com/helix/config/cdn/prod/managed"
166
31
  },
167
32
  {
168
- "type": "object",
169
- "title": "CloudfrontConfig",
170
- "properties": {
171
- "type": {
172
- "type": "string",
173
- "const": "cloudfront"
174
- },
175
- "host": {
176
- "description": "production host",
177
- "type": "string"
178
- },
179
- "route": {
180
- "description": "Routes on the CDN that are rendered with Franklin",
181
- "type": "array",
182
- "items": {
183
- "type": "string"
184
- }
185
- },
186
- "distributionId": {
187
- "type": "string"
188
- },
189
- "accessKeyId": {
190
- "type": "string"
191
- },
192
- "secretAccessKey": {
193
- "type": "string"
194
- }
195
- },
196
- "required": [
197
- "type",
198
- "host",
199
- "distributionId",
200
- "accessKeyId",
201
- "secretAccessKey"
202
- ],
203
- "additionalProperties": false
33
+ "$ref": "https://ns.adobe.com/helix/config/cdn/prod/cloudfront"
204
34
  },
205
35
  {
206
36
  "type": "object",
@@ -249,8 +79,5 @@
249
79
  "additionalProperties": false
250
80
  }
251
81
  },
252
- "required": [
253
- "prod"
254
- ],
255
82
  "additionalProperties": false
256
83
  }
@@ -12,7 +12,7 @@
12
12
  ],
13
13
  "$schema": "http://json-schema.org/draft-07/schema#",
14
14
  "$id": "https://ns.adobe.com/helix/config/code",
15
- "title": "Code Bus",
15
+ "title": "Code source",
16
16
  "type": "object",
17
17
  "description": "Defines the code bus location and source.",
18
18
  "properties": {
@@ -13,7 +13,7 @@
13
13
  "$schema": "http://json-schema.org/draft-07/schema#",
14
14
  "$id": "https://ns.adobe.com/helix/config/content",
15
15
  "type": "object",
16
- "title": "Content Bus",
16
+ "title": "Content source",
17
17
  "description": "Defines the content bus location and source.",
18
18
  "properties": {
19
19
  "title": { "$ref": "https://ns.adobe.com/helix/config/common#/definitions/title" },
@@ -9,38 +9,87 @@
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
- /* eslint-disable max-classes-per-file */
13
12
 
14
- export class ValidationError extends Error {
15
- constructor(
16
- msg,
17
- errors = [],
18
- mapError = ValidationError.mapError,
19
- prettyname = ValidationError.prettyname,
20
- ) {
21
- const detail = errors.map((e) => mapError(e, prettyname)).join('\n');
22
- super(`Invalid configuration:
23
- ${detail}
24
-
25
- ${msg}`);
26
- this._errors = errors;
13
+ /* eslint-disable no-continue,no-param-reassign */
14
+
15
+ function removeByPrefix(byPath, prefix) {
16
+ Object.keys(byPath).forEach((path) => {
17
+ if (path.startsWith(prefix)) {
18
+ delete byPath[path];
19
+ }
20
+ });
21
+ }
22
+
23
+ function handleContentSource(byPath, msg) {
24
+ if (byPath['/content/source']) {
25
+ const type = byPath['/content/source']?.[0]?.data?.type;
26
+ if (!['onedrive', 'google', 'markup'].includes(type)) {
27
+ msg.push('/content/source/type must be one of [onedrive, google, markup]');
28
+ removeByPrefix(byPath, '/content/source');
29
+ return;
30
+ }
31
+
32
+ // remove other content source errors
33
+ delete byPath['/content/source'];
34
+ delete byPath['/content/source/type'];
27
35
  }
36
+ }
28
37
 
29
- static prettyname(path, schema) {
30
- /* c8 ignore next */
31
- return path ? `${schema.title || schema.$id} ${path}` : `${schema.title || schema.$id}`;
38
+ function handleCDNProd(byPath, msg) {
39
+ const cdnErrors = byPath['/cdn/prod'];
40
+ if (cdnErrors) {
41
+ const type = byPath['/cdn/prod']?.[0]?.data?.type;
42
+ if (type && !['fastly', 'cloudflare', 'akamai', 'managed', 'cloudfront'].includes(type)) {
43
+ msg.push('/cdn/prod/type must be one of [fastly, cloudflare, akamai, managed, cloudfront]');
44
+ removeByPrefix(byPath, '/cdn/prod');
45
+ return;
46
+ }
47
+ delete byPath['/cdn/prod/type'];
48
+ // if the type is specified, filter errors from other schemas
49
+ if (type) {
50
+ byPath[`/cdn/prod['${type}']`] = cdnErrors.filter(({ parentSchema }) => parentSchema?.$id?.endsWith(type));
51
+ delete byPath['/cdn/prod'];
52
+ }
32
53
  }
54
+ }
33
55
 
34
- static mapError({
35
- keyword, dataPath, message, data, params, parentSchema,
36
- }, prettyname) {
37
- /* c8 ignore next 7 */
38
- if (keyword === 'additionalProperties') {
39
- return `${prettyname(dataPath, parentSchema)} has unknown property '${params.additionalProperty}'`;
56
+ export class ValidationError extends Error {
57
+ constructor(msg, errors = []) {
58
+ super(ValidationError.generateErrorDetail(errors));
59
+ this._errors = errors;
60
+ }
61
+
62
+ static generateErrorDetail(ajvErrors) {
63
+ const msg = [];
64
+ // group errors by instance
65
+ const byPath = {};
66
+ for (const error of ajvErrors) {
67
+ const id = error.instancePath || 'data';
68
+ if (!byPath[id]) {
69
+ byPath[id] = [];
70
+ }
71
+ byPath[id].push(error);
40
72
  }
41
- if (keyword === 'required') {
42
- return `${prettyname(dataPath, parentSchema)} ${message}`;
73
+
74
+ // handle special locations
75
+ handleContentSource(byPath, msg);
76
+ handleCDNProd(byPath, msg);
77
+
78
+ for (const [id, errors] of Object.entries(byPath)) {
79
+ // create required properties message
80
+ const reqErrors = errors.filter((e) => e.keyword === 'required');
81
+ if (reqErrors.length) {
82
+ msg.push(`${id} must have required properties: [${reqErrors.map((e) => e.params.missingProperty).join(', ')}]`);
83
+ }
84
+
85
+ // create other errors
86
+ const otherErrors = errors.filter((e) => e.keyword !== 'required');
87
+ // make unique messages
88
+ const uniqueErrors = new Set(otherErrors.map((e) => e.message));
89
+ if (uniqueErrors.size) {
90
+ msg.push(`${id} ${Array.from(uniqueErrors).join(', ')}`);
91
+ }
43
92
  }
44
- return `${prettyname(dataPath, parentSchema)} ${message}: ${keyword}(${JSON.stringify(data)}, ${JSON.stringify(params)})`;
93
+ return msg.join('; ');
45
94
  }
46
95
  }
@@ -17,6 +17,11 @@ import accessAdminSchema from '../schemas/access-admin.schema.cjs';
17
17
  import accessSchema from '../schemas/access.schema.cjs';
18
18
  import accessSiteSchema from '../schemas/access-site.schema.cjs';
19
19
  import cdnSchema from '../schemas/cdn.schema.cjs';
20
+ import cdnProdFastlySchema from '../schemas/cdn-prod-fastly.schema.cjs';
21
+ import cdnProdCloudflareSchema from '../schemas/cdn-prod-cloudflare.schema.cjs';
22
+ import cdnProdAkamaiSchema from '../schemas/cdn-prod-akamai.schema.cjs';
23
+ import cdnProdManagedSchema from '../schemas/cdn-prod-managed.schema.cjs';
24
+ import cdnProdCloudfrontSchema from '../schemas/cdn-prod-cloudfront.schema.cjs';
20
25
  import commonSchema from '../schemas/common.schema.cjs';
21
26
  import codeSchema from '../schemas/code.schema.cjs';
22
27
  import contentSchema from '../schemas/content.schema.cjs';
@@ -65,6 +70,11 @@ export const SCHEMAS = [
65
70
  tokensSchema,
66
71
  userSchema,
67
72
  usersSchema,
73
+ cdnProdFastlySchema,
74
+ cdnProdCloudflareSchema,
75
+ cdnProdAkamaiSchema,
76
+ cdnProdManagedSchema,
77
+ cdnProdCloudfrontSchema,
68
78
  ];
69
79
 
70
80
  const SCHEMA_TYPES = {
@@ -80,6 +90,11 @@ const SCHEMA_TYPES = {
80
90
  * @returns {object} The validated configuration
81
91
  */
82
92
  export async function validate(config, type) {
93
+ const schema = SCHEMA_TYPES[type];
94
+ if (!schema) {
95
+ throw new Error(`no such type: ${type}`);
96
+ }
97
+
83
98
  const ajv = new Ajv({
84
99
  allErrors: true,
85
100
  verbose: true,
@@ -90,7 +105,7 @@ export async function validate(config, type) {
90
105
  ajvFormats(ajv);
91
106
 
92
107
  ajv.addSchema(SCHEMAS);
93
- const res = ajv.validate(SCHEMA_TYPES[type], config);
108
+ const res = ajv.validate(schema, config);
94
109
  if (res) {
95
110
  return res;
96
111
  }
@@ -22,8 +22,8 @@ export interface HelixProfileConfig {
22
22
  * description for clarity. has no influence on the configuration.
23
23
  */
24
24
  description?: string;
25
- content?: ContentBus;
26
- code?: CodeBus;
25
+ content?: ContentSource;
26
+ code?: CodeSource;
27
27
  folders?: Folders;
28
28
  headers?: HelixHeadersConfig;
29
29
  cdn?: CDNConfig;
@@ -36,7 +36,7 @@ export interface HelixProfileConfig {
36
36
  /**
37
37
  * Defines the content bus location and source.
38
38
  */
39
- export interface ContentBus {
39
+ export interface ContentSource {
40
40
  /**
41
41
  * human readable title. has no influence on the configuration.
42
42
  */
@@ -73,7 +73,7 @@ export interface MarkupContentSource {
73
73
  /**
74
74
  * Defines the code bus location and source.
75
75
  */
76
- export interface CodeBus {
76
+ export interface CodeSource {
77
77
  /**
78
78
  * human readable title. has no influence on the configuration.
79
79
  */
@@ -109,7 +109,7 @@ export interface KeyValuePair {
109
109
  value: string;
110
110
  }
111
111
  export interface CDNConfig {
112
- prod: FastlyConfig | AkamaiConfig | CloudflareConfig | ManagedConfig | CloudfrontConfig | EmptyConfig;
112
+ prod?: FastlyCDNConfig | CloudflareCDNConfig | AkamaiCDNConfig | ManagedCDNConfig | CloudfrontCDNConfig | EmptyConfig;
113
113
  live?: {
114
114
  /**
115
115
  * Sidekick config to override the default preview host. it supports parameters $owner and $repo
@@ -126,7 +126,7 @@ export interface CDNConfig {
126
126
  /**
127
127
  * Production CDN configuration for Fastly
128
128
  */
129
- export interface FastlyConfig {
129
+ export interface FastlyCDNConfig {
130
130
  type: 'fastly';
131
131
  /**
132
132
  * production host
@@ -145,8 +145,8 @@ export interface FastlyConfig {
145
145
  */
146
146
  authToken: string;
147
147
  }
148
- export interface AkamaiConfig {
149
- type: 'akamai';
148
+ export interface CloudflareCDNConfig {
149
+ type: 'cloudflare';
150
150
  /**
151
151
  * production host
152
152
  */
@@ -155,13 +155,12 @@ export interface AkamaiConfig {
155
155
  * Routes on the CDN that are rendered with Franklin
156
156
  */
157
157
  route?: string[];
158
- endpoint: string;
159
- clientSecret: string;
160
- clientToken: string;
161
- accessToken: string;
158
+ plan: string;
159
+ zoneId: string;
160
+ apiToken: string;
162
161
  }
163
- export interface CloudflareConfig {
164
- type: 'cloudflare';
162
+ export interface AkamaiCDNConfig {
163
+ type: 'akamai';
165
164
  /**
166
165
  * production host
167
166
  */
@@ -170,12 +169,12 @@ export interface CloudflareConfig {
170
169
  * Routes on the CDN that are rendered with Franklin
171
170
  */
172
171
  route?: string[];
173
- origin: string;
174
- plan: string;
175
- zoneId: string;
176
- apiToken: string;
172
+ endpoint: string;
173
+ clientSecret: string;
174
+ clientToken: string;
175
+ accessToken: string;
177
176
  }
178
- export interface ManagedConfig {
177
+ export interface ManagedCDNConfig {
179
178
  type: 'managed';
180
179
  /**
181
180
  * production host
@@ -186,7 +185,7 @@ export interface ManagedConfig {
186
185
  */
187
186
  route?: string[];
188
187
  }
189
- export interface CloudfrontConfig {
188
+ export interface CloudfrontCDNConfig {
190
189
  type: 'cloudfront';
191
190
  /**
192
191
  * production host
@@ -26,8 +26,8 @@ export interface HelixSiteConfig {
26
26
  * description for clarity. has no influence on the configuration.
27
27
  */
28
28
  description?: string;
29
- content: ContentBus;
30
- code: CodeBus;
29
+ content: ContentSource;
30
+ code: CodeSource;
31
31
  folders?: Folders;
32
32
  headers?: HelixHeadersConfig;
33
33
  cdn?: CDNConfig;
@@ -44,7 +44,7 @@ export interface HelixSiteConfig {
44
44
  /**
45
45
  * Defines the content bus location and source.
46
46
  */
47
- export interface ContentBus {
47
+ export interface ContentSource {
48
48
  /**
49
49
  * human readable title. has no influence on the configuration.
50
50
  */
@@ -81,7 +81,7 @@ export interface MarkupContentSource {
81
81
  /**
82
82
  * Defines the code bus location and source.
83
83
  */
84
- export interface CodeBus {
84
+ export interface CodeSource {
85
85
  /**
86
86
  * human readable title. has no influence on the configuration.
87
87
  */
@@ -117,7 +117,7 @@ export interface KeyValuePair {
117
117
  value: string;
118
118
  }
119
119
  export interface CDNConfig {
120
- prod: FastlyConfig | AkamaiConfig | CloudflareConfig | ManagedConfig | CloudfrontConfig | EmptyConfig;
120
+ prod?: FastlyCDNConfig | CloudflareCDNConfig | AkamaiCDNConfig | ManagedCDNConfig | CloudfrontCDNConfig | EmptyConfig;
121
121
  live?: {
122
122
  /**
123
123
  * Sidekick config to override the default preview host. it supports parameters $owner and $repo
@@ -134,7 +134,7 @@ export interface CDNConfig {
134
134
  /**
135
135
  * Production CDN configuration for Fastly
136
136
  */
137
- export interface FastlyConfig {
137
+ export interface FastlyCDNConfig {
138
138
  type: 'fastly';
139
139
  /**
140
140
  * production host
@@ -153,8 +153,8 @@ export interface FastlyConfig {
153
153
  */
154
154
  authToken: string;
155
155
  }
156
- export interface AkamaiConfig {
157
- type: 'akamai';
156
+ export interface CloudflareCDNConfig {
157
+ type: 'cloudflare';
158
158
  /**
159
159
  * production host
160
160
  */
@@ -163,13 +163,12 @@ export interface AkamaiConfig {
163
163
  * Routes on the CDN that are rendered with Franklin
164
164
  */
165
165
  route?: string[];
166
- endpoint: string;
167
- clientSecret: string;
168
- clientToken: string;
169
- accessToken: string;
166
+ plan: string;
167
+ zoneId: string;
168
+ apiToken: string;
170
169
  }
171
- export interface CloudflareConfig {
172
- type: 'cloudflare';
170
+ export interface AkamaiCDNConfig {
171
+ type: 'akamai';
173
172
  /**
174
173
  * production host
175
174
  */
@@ -178,12 +177,12 @@ export interface CloudflareConfig {
178
177
  * Routes on the CDN that are rendered with Franklin
179
178
  */
180
179
  route?: string[];
181
- origin: string;
182
- plan: string;
183
- zoneId: string;
184
- apiToken: string;
180
+ endpoint: string;
181
+ clientSecret: string;
182
+ clientToken: string;
183
+ accessToken: string;
185
184
  }
186
- export interface ManagedConfig {
185
+ export interface ManagedCDNConfig {
187
186
  type: 'managed';
188
187
  /**
189
188
  * production host
@@ -194,7 +193,7 @@ export interface ManagedConfig {
194
193
  */
195
194
  route?: string[];
196
195
  }
197
- export interface CloudfrontConfig {
196
+ export interface CloudfrontCDNConfig {
198
197
  type: 'cloudfront';
199
198
  /**
200
199
  * production host