@burojs/config 0.4.0 → 0.5.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/README.md +52 -17
- package/dist/index.cjs +153 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -44
- package/dist/index.d.ts +50 -44
- package/dist/index.js +152 -137
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
|
+
import { DEFAULT_COMPILER_LIMITS, normalizeLayerGrants } from "@burojs/core";
|
|
2
|
+
import { blacklistedKeyCategory, createParsedLayer, isReservedSegment, scopeRank } from "@burojs/core/internal";
|
|
1
3
|
import { parseDocument } from "yaml";
|
|
4
|
+
//#region src/source-policy.ts
|
|
5
|
+
const MAX_SOURCE_DEPTH = DEFAULT_COMPILER_LIMITS.maxPortableDepth;
|
|
6
|
+
const SCREEN_SOURCE_LIMITS = Object.freeze({
|
|
7
|
+
maxBytes: 256e3,
|
|
8
|
+
maxDeclarations: 64,
|
|
9
|
+
maxDepth: MAX_SOURCE_DEPTH,
|
|
10
|
+
maxNodes: 5e3,
|
|
11
|
+
maxStringLength: 4096,
|
|
12
|
+
maxDiagnostics: 32
|
|
13
|
+
});
|
|
14
|
+
//#endregion
|
|
2
15
|
//#region src/parse.ts
|
|
3
|
-
const RESERVED_KEYS = new Set([
|
|
4
|
-
"__proto__",
|
|
5
|
-
"prototype",
|
|
6
|
-
"constructor"
|
|
7
|
-
]);
|
|
8
|
-
const FORBIDDEN_VALUE_CATEGORIES = new Map([
|
|
9
|
-
["action", "action"],
|
|
10
|
-
["actions", "action"],
|
|
11
|
-
["provider", "provider"],
|
|
12
|
-
["providers", "provider"],
|
|
13
|
-
["mapper", "mapper"],
|
|
14
|
-
["mappers", "mapper"],
|
|
15
|
-
["service", "service"],
|
|
16
|
-
["services", "service"],
|
|
17
|
-
["credential", "credential"],
|
|
18
|
-
["credentials", "credential"],
|
|
19
|
-
["schema", "schema"],
|
|
20
|
-
["schemas", "schema"],
|
|
21
|
-
["component", "component"],
|
|
22
|
-
["components", "component"],
|
|
23
|
-
["attachment", "attachment"],
|
|
24
|
-
["attachments", "attachment"],
|
|
25
|
-
["validator", "validator"],
|
|
26
|
-
["validators", "validator"]
|
|
27
|
-
]);
|
|
28
16
|
const LAYER_KEYS = new Set([
|
|
29
17
|
"id",
|
|
30
18
|
"priority",
|
|
@@ -95,6 +83,7 @@ function messageFor(code) {
|
|
|
95
83
|
case "source.byte-limit": return "The source exceeds its byte limit.";
|
|
96
84
|
case "source.declaration-limit": return "The source exceeds its declaration limit.";
|
|
97
85
|
case "source.depth-limit": return "The source exceeds its nesting-depth limit.";
|
|
86
|
+
case "source.node-limit": return "The source exceeds its value-count limit.";
|
|
98
87
|
case "source.string-limit": return "The source contains an overlong string.";
|
|
99
88
|
case "source.diagnostic-limit": return "Additional source diagnostics were omitted.";
|
|
100
89
|
case "source.unknown-key": return "The source contains an unknown key.";
|
|
@@ -109,7 +98,7 @@ function messageFor(code) {
|
|
|
109
98
|
case "source.forbidden-transform-op": return "The source requests a forbidden transform operation.";
|
|
110
99
|
case "source.forbidden-transform-scope": return "The source requests a forbidden transform scope.";
|
|
111
100
|
case "source.forbidden-capability": return "The source requests a forbidden capability.";
|
|
112
|
-
case "source.forbidden-action": return "The source requests a forbidden action binding.";
|
|
101
|
+
case "source.forbidden-action": return "The source requests a forbidden action binding; a resource's flows are written under toolbar.";
|
|
113
102
|
case "source.forbidden-provider": return "The source requests a forbidden provider binding.";
|
|
114
103
|
case "source.forbidden-mapper": return "The source requests a forbidden mapper binding.";
|
|
115
104
|
case "source.forbidden-service": return "The source requests a forbidden service value.";
|
|
@@ -121,14 +110,68 @@ function messageFor(code) {
|
|
|
121
110
|
default: return "The source is invalid.";
|
|
122
111
|
}
|
|
123
112
|
}
|
|
113
|
+
const LIMIT_KEYS = [
|
|
114
|
+
"maxBytes",
|
|
115
|
+
"maxDeclarations",
|
|
116
|
+
"maxDepth",
|
|
117
|
+
"maxNodes",
|
|
118
|
+
"maxStringLength",
|
|
119
|
+
"maxDiagnostics"
|
|
120
|
+
];
|
|
121
|
+
const LIMIT_KEY_SET = new Set(LIMIT_KEYS);
|
|
124
122
|
function validLimits(limits) {
|
|
125
|
-
return Object.
|
|
123
|
+
return plainObject(limits) && Object.keys(limits).every((key) => LIMIT_KEY_SET.has(key)) && LIMIT_KEYS.every((key) => Number.isSafeInteger(limits[key]) && limits[key] > 0);
|
|
126
124
|
}
|
|
127
125
|
function validCapabilities(value) {
|
|
128
126
|
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((capabilities) => Array.isArray(capabilities) && capabilities.every((capability) => typeof capability === "string"));
|
|
129
127
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
128
|
+
function grantsError(policy) {
|
|
129
|
+
try {
|
|
130
|
+
normalizeLayerGrants(policy.grants);
|
|
131
|
+
return;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
return error instanceof TypeError ? error.message : "";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function policyDiagnostic(policy) {
|
|
137
|
+
const generic = messageFor("source.invalid-policy");
|
|
138
|
+
const stray = strayPolicyKey(policy);
|
|
139
|
+
if (stray !== void 0) return Object.freeze({
|
|
140
|
+
code: "source.invalid-policy",
|
|
141
|
+
message: `The source policy is invalid: it carries ${stray} at the top level; a policy is { grants, allowedCapabilities, limits }, with every grant field inside grants.`
|
|
142
|
+
});
|
|
143
|
+
if (!validPolicyShape(policy)) return Object.freeze({
|
|
144
|
+
code: "source.invalid-policy",
|
|
145
|
+
message: generic
|
|
146
|
+
});
|
|
147
|
+
const reason = grantsError(policy);
|
|
148
|
+
if (reason === void 0) return void 0;
|
|
149
|
+
return Object.freeze({
|
|
150
|
+
code: "source.invalid-policy",
|
|
151
|
+
message: reason === "" ? generic : `The source policy is invalid: ${reason}`
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
const POLICY_KEYS = new Set([
|
|
155
|
+
"grants",
|
|
156
|
+
"allowedCapabilities",
|
|
157
|
+
"limits"
|
|
158
|
+
]);
|
|
159
|
+
function strayPolicyKey(policy) {
|
|
160
|
+
return plainObject(policy) ? Object.keys(policy).find((key) => !POLICY_KEYS.has(key)) : void 0;
|
|
161
|
+
}
|
|
162
|
+
function validPolicyShape(policy) {
|
|
163
|
+
return plainObject(policy) && plainObject(policy.grants) && validCapabilities(policy.allowedCapabilities) && validLimits(policy.limits);
|
|
164
|
+
}
|
|
165
|
+
function ownedPolicy(policy) {
|
|
166
|
+
const invalid = policyDiagnostic(policy);
|
|
167
|
+
if (invalid !== void 0) throw new TypeError(invalid.message);
|
|
168
|
+
const capabilities = Object.create(null);
|
|
169
|
+
for (const [kind, values] of Object.entries(policy.allowedCapabilities)) capabilities[kind] = Object.freeze([...values]);
|
|
170
|
+
return Object.freeze({
|
|
171
|
+
grants: normalizeLayerGrants(policy.grants),
|
|
172
|
+
allowedCapabilities: Object.freeze(capabilities),
|
|
173
|
+
limits: Object.freeze({ ...policy.limits })
|
|
174
|
+
});
|
|
132
175
|
}
|
|
133
176
|
function failure(diagnostics) {
|
|
134
177
|
return {
|
|
@@ -149,10 +192,37 @@ function hasData(value, key) {
|
|
|
149
192
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
150
193
|
return descriptor !== void 0 && "value" in descriptor;
|
|
151
194
|
}
|
|
195
|
+
const MAX_ENVELOPE_DEPTH = 8;
|
|
196
|
+
function childRole(role, key) {
|
|
197
|
+
switch (role) {
|
|
198
|
+
case "root": return key === "declarations" ? "declarations" : key === "transforms" ? "transforms" : "envelope";
|
|
199
|
+
case "declarations": return "declaration";
|
|
200
|
+
case "transforms": return "transform";
|
|
201
|
+
case "declaration": return key === "value" ? "value" : "envelope";
|
|
202
|
+
case "transform": return key === "operation" ? "operation" : "envelope";
|
|
203
|
+
case "operation": return key === "value" ? "value" : "envelope";
|
|
204
|
+
default: return role;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
152
207
|
function clonePortable(value, limits, diagnostics) {
|
|
153
208
|
const ancestors = new WeakSet();
|
|
154
|
-
|
|
155
|
-
|
|
209
|
+
const maxDepth = Math.min(limits.maxDepth, MAX_SOURCE_DEPTH);
|
|
210
|
+
let nodes = 0;
|
|
211
|
+
let nodesExceeded = false;
|
|
212
|
+
function overNodeBudget(children) {
|
|
213
|
+
if (children <= limits.maxNodes - nodes) return false;
|
|
214
|
+
if (!nodesExceeded) diagnostics.add("source.node-limit");
|
|
215
|
+
nodesExceeded = true;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
function copy(current, depth, role) {
|
|
219
|
+
nodes += 1;
|
|
220
|
+
if (nodes > limits.maxNodes) {
|
|
221
|
+
if (!nodesExceeded) diagnostics.add("source.node-limit");
|
|
222
|
+
nodesExceeded = true;
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
if (depth > (role === "value" ? maxDepth : MAX_ENVELOPE_DEPTH)) {
|
|
156
226
|
diagnostics.add("source.depth-limit");
|
|
157
227
|
return null;
|
|
158
228
|
}
|
|
@@ -172,6 +242,12 @@ function clonePortable(value, limits, diagnostics) {
|
|
|
172
242
|
ancestors.add(current);
|
|
173
243
|
if (Array.isArray(current)) {
|
|
174
244
|
const output = [];
|
|
245
|
+
const length = ownData(current, "length");
|
|
246
|
+
const arrayLength = typeof length === "number" && Number.isSafeInteger(length) && length >= 0 ? length : void 0;
|
|
247
|
+
if (arrayLength !== void 0 && overNodeBudget(arrayLength)) {
|
|
248
|
+
ancestors.delete(current);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
175
251
|
for (const key of Reflect.ownKeys(current)) {
|
|
176
252
|
if (typeof key !== "string" || key !== "length" && !/^(0|[1-9]\d*)$/u.test(key)) {
|
|
177
253
|
diagnostics.add("source.invalid-layer");
|
|
@@ -180,41 +256,47 @@ function clonePortable(value, limits, diagnostics) {
|
|
|
180
256
|
if (key === "length") continue;
|
|
181
257
|
if (!hasData(current, key)) diagnostics.add("source.accessor");
|
|
182
258
|
}
|
|
183
|
-
const length = ownData(current, "length");
|
|
184
|
-
const arrayLength = typeof length === "number" && Number.isSafeInteger(length) && length >= 0 ? length : void 0;
|
|
185
259
|
if (arrayLength === void 0) diagnostics.add("source.invalid-layer");
|
|
186
|
-
else for (let index = 0; index < arrayLength; index += 1) {
|
|
260
|
+
else for (let index = 0; index < arrayLength && !nodesExceeded; index += 1) {
|
|
187
261
|
if (!hasData(current, String(index))) diagnostics.add("source.accessor");
|
|
188
|
-
output.push(copy(ownData(current, String(index)), depth + 1));
|
|
262
|
+
output.push(copy(ownData(current, String(index)), depth + 1, childRole(role, void 0)));
|
|
189
263
|
}
|
|
190
264
|
ancestors.delete(current);
|
|
191
265
|
return Object.freeze(output);
|
|
192
266
|
}
|
|
193
267
|
if (!plainObject(current)) diagnostics.add("source.invalid-layer");
|
|
194
268
|
const output = Object.create(null);
|
|
195
|
-
|
|
269
|
+
const keys = Reflect.ownKeys(current);
|
|
270
|
+
if (overNodeBudget(keys.length)) {
|
|
271
|
+
ancestors.delete(current);
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
for (const key of keys) {
|
|
275
|
+
if (nodesExceeded) break;
|
|
196
276
|
if (typeof key !== "string") {
|
|
197
277
|
diagnostics.add("source.invalid-layer");
|
|
198
278
|
continue;
|
|
199
279
|
}
|
|
200
|
-
if (
|
|
280
|
+
if (isReservedSegment(key)) diagnostics.add("source.reserved-key");
|
|
201
281
|
if ([...key].length > limits.maxStringLength) diagnostics.add("source.string-limit");
|
|
202
282
|
if (!hasData(current, key)) {
|
|
203
283
|
diagnostics.add("source.accessor");
|
|
204
284
|
continue;
|
|
205
285
|
}
|
|
206
|
-
|
|
286
|
+
const next = childRole(role, key);
|
|
287
|
+
const nextDepth = next === "value" && role !== "value" ? 0 : depth + 1;
|
|
288
|
+
output[key] = copy(ownData(current, key), nextDepth, next);
|
|
207
289
|
}
|
|
208
290
|
ancestors.delete(current);
|
|
209
291
|
return Object.freeze(output);
|
|
210
292
|
}
|
|
211
|
-
return copy(value, 0);
|
|
293
|
+
return copy(value, 0, "root");
|
|
212
294
|
}
|
|
213
295
|
function unknownKeys(value, allowed, diagnostics) {
|
|
214
296
|
for (const key of Object.keys(value)) if (!allowed.has(key)) diagnostics.add("source.unknown-key");
|
|
215
297
|
}
|
|
216
298
|
function allowedNamespace(value, policy, diagnostics) {
|
|
217
|
-
if (typeof value !== "string" || !policy.allowedNamespaces.includes(value)) {
|
|
299
|
+
if (typeof value !== "string" || !policy.grants.allowedNamespaces.includes(value)) {
|
|
218
300
|
diagnostics.add("source.forbidden-namespace");
|
|
219
301
|
return false;
|
|
220
302
|
}
|
|
@@ -243,17 +325,15 @@ function validateValue(value, kind, policy, diagnostics) {
|
|
|
243
325
|
if (!plainObject(value)) return;
|
|
244
326
|
if (value.$buro === ATTACHMENT_TAG) {
|
|
245
327
|
const capability = ownData(value, "capability");
|
|
246
|
-
|
|
328
|
+
const allowed = Object.hasOwn(policy.allowedCapabilities, kind) ? policy.allowedCapabilities[kind] : void 0;
|
|
329
|
+
if (typeof capability !== "string" || !allowed?.includes(capability)) diagnostics.add("source.forbidden-capability");
|
|
247
330
|
}
|
|
248
331
|
for (const key of Object.keys(value)) {
|
|
249
|
-
const category =
|
|
332
|
+
const category = blacklistedKeyCategory(key);
|
|
250
333
|
if (category !== void 0) diagnostics.add(`source.forbidden-${category}`);
|
|
251
334
|
validateValue(ownData(value, key), kind, policy, diagnostics);
|
|
252
335
|
}
|
|
253
336
|
}
|
|
254
|
-
function scopeRank(scope) {
|
|
255
|
-
return scope === "layer" ? 0 : scope === "namespace" ? 1 : 2;
|
|
256
|
-
}
|
|
257
337
|
function transformOperation(value) {
|
|
258
338
|
if (!plainObject(value)) return void 0;
|
|
259
339
|
const operation = ownData(value, "op");
|
|
@@ -284,7 +364,7 @@ function validateTransforms(value, defaultNamespace, policy, diagnostics) {
|
|
|
284
364
|
unknownKeys(transform, TRANSFORM_KEYS, diagnostics);
|
|
285
365
|
const scope = ownData(transform, "scope") ?? "layer";
|
|
286
366
|
if (scope !== "layer" && scope !== "application") diagnostics.add("source.invalid-transform");
|
|
287
|
-
else if (scopeRank(scope) > scopeRank(policy.maxTransformScope)) diagnostics.add("source.forbidden-transform-scope");
|
|
367
|
+
else if (scopeRank(scope) > scopeRank(policy.grants.maxTransformScope)) diagnostics.add("source.forbidden-transform-scope");
|
|
288
368
|
const select = ownData(transform, "select");
|
|
289
369
|
if (!plainObject(select)) diagnostics.add("source.invalid-transform");
|
|
290
370
|
else {
|
|
@@ -293,7 +373,7 @@ function validateTransforms(value, defaultNamespace, policy, diagnostics) {
|
|
|
293
373
|
if (selectedKinds !== void 0) {
|
|
294
374
|
if (!Array.isArray(selectedKinds)) diagnostics.add("source.invalid-transform");
|
|
295
375
|
else for (const kind of selectedKinds) if (typeof kind !== "string") diagnostics.add("source.invalid-transform");
|
|
296
|
-
else if (!policy.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
376
|
+
else if (!policy.grants.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
297
377
|
}
|
|
298
378
|
const selectedNamespaces = ownData(select, "namespaces");
|
|
299
379
|
if (selectedNamespaces !== void 0) {
|
|
@@ -308,7 +388,7 @@ function validateTransforms(value, defaultNamespace, policy, diagnostics) {
|
|
|
308
388
|
if (typeof (plainObject(operation) ? ownData(operation, "op") : void 0) === "string" && op === void 0) diagnostics.add("source.forbidden-transform-op");
|
|
309
389
|
else if (op === void 0) diagnostics.add("source.invalid-transform");
|
|
310
390
|
else {
|
|
311
|
-
if (!policy.allowedTransformOps.includes(op)) diagnostics.add("source.forbidden-transform-op");
|
|
391
|
+
if (!policy.grants.allowedTransformOps.includes(op)) diagnostics.add("source.forbidden-transform-op");
|
|
312
392
|
if (plainObject(operation)) {
|
|
313
393
|
unknownKeys(operation, OPERATION_KEYS[op], diagnostics);
|
|
314
394
|
if (hasData(operation, "value")) validateValue(ownData(operation, "value"), "", policy, diagnostics);
|
|
@@ -317,12 +397,10 @@ function validateTransforms(value, defaultNamespace, policy, diagnostics) {
|
|
|
317
397
|
}
|
|
318
398
|
}
|
|
319
399
|
function validateLayerValue(value, policy) {
|
|
320
|
-
|
|
400
|
+
const invalidPolicy = policyDiagnostic(policy);
|
|
401
|
+
if (invalidPolicy !== void 0) return {
|
|
321
402
|
ok: false,
|
|
322
|
-
diagnostics: Object.freeze([
|
|
323
|
-
code: "source.invalid-policy",
|
|
324
|
-
message: messageFor("source.invalid-policy")
|
|
325
|
-
})])
|
|
403
|
+
diagnostics: Object.freeze([invalidPolicy])
|
|
326
404
|
};
|
|
327
405
|
const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);
|
|
328
406
|
const cloned = clonePortable(value, policy.limits, diagnostics);
|
|
@@ -352,7 +430,7 @@ function validateLayerValue(value, policy) {
|
|
|
352
430
|
unknownKeys(declaration, DECLARATION_KEYS, diagnostics);
|
|
353
431
|
const kind = ownData(declaration, "kind");
|
|
354
432
|
if (typeof kind !== "string") diagnostics.add("source.invalid-declaration");
|
|
355
|
-
else if (!policy.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
433
|
+
else if (!policy.grants.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
356
434
|
const namespace = namespaceFor(ownData(declaration, "ref"), typeof defaultNamespace === "string" ? defaultNamespace : "default", diagnostics);
|
|
357
435
|
if (namespace !== void 0) allowedNamespace(namespace, policy, diagnostics);
|
|
358
436
|
if (!Number.isSafeInteger(ownData(declaration, "schemaVersion")) || !hasData(declaration, "value")) diagnostics.add("source.invalid-declaration");
|
|
@@ -362,14 +440,14 @@ function validateLayerValue(value, policy) {
|
|
|
362
440
|
if (diagnostics.values.length > 0) return failure(diagnostics);
|
|
363
441
|
return {
|
|
364
442
|
ok: true,
|
|
365
|
-
value: cloned
|
|
443
|
+
value: createParsedLayer(cloned, normalizeLayerGrants(policy.grants))
|
|
366
444
|
};
|
|
367
445
|
}
|
|
368
446
|
function byteLength(value) {
|
|
369
447
|
return new TextEncoder().encode(value).byteLength;
|
|
370
448
|
}
|
|
371
449
|
function parseSource(source, policy, format) {
|
|
372
|
-
if (
|
|
450
|
+
if (policyDiagnostic(policy) !== void 0) return validateLayerValue(null, policy);
|
|
373
451
|
const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);
|
|
374
452
|
if (byteLength(source) > policy.limits.maxBytes) {
|
|
375
453
|
diagnostics.add("source.byte-limit");
|
|
@@ -399,82 +477,12 @@ function parseYamlLayer(source, policy) {
|
|
|
399
477
|
return parseSource(source, policy, "yaml");
|
|
400
478
|
}
|
|
401
479
|
//#endregion
|
|
402
|
-
//#region src/adapter.ts
|
|
403
|
-
function diagnostic(code, message) {
|
|
404
|
-
return Object.freeze({
|
|
405
|
-
code,
|
|
406
|
-
message
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
function diagnosticLimit(policy) {
|
|
410
|
-
const candidate = policy?.limits?.maxDiagnostics;
|
|
411
|
-
return typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate > 0 ? candidate : 1;
|
|
412
|
-
}
|
|
413
|
-
function frozenPolicy(policy) {
|
|
414
|
-
const capabilities = Object.create(null);
|
|
415
|
-
for (const [kind, values] of Object.entries(policy.allowedCapabilities)) capabilities[kind] = Object.freeze([...values]);
|
|
416
|
-
const limits = Object.freeze({ ...policy.limits });
|
|
417
|
-
return Object.freeze({
|
|
418
|
-
allowedKinds: Object.freeze([...policy.allowedKinds]),
|
|
419
|
-
allowedNamespaces: Object.freeze([...policy.allowedNamespaces]),
|
|
420
|
-
allowedTransformOps: Object.freeze([...policy.allowedTransformOps]),
|
|
421
|
-
maxTransformScope: policy.maxTransformScope,
|
|
422
|
-
allowedCapabilities: Object.freeze(capabilities),
|
|
423
|
-
limits
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
function copyDiagnostic(value) {
|
|
427
|
-
if (value !== null && typeof value === "object" && typeof value.code === "string" && typeof value.message === "string") return diagnostic(value.code, value.message);
|
|
428
|
-
return diagnostic("source.invalid-adapter-diagnostic", "The source adapter returned an invalid diagnostic.");
|
|
429
|
-
}
|
|
430
|
-
function adaptRawConfig(input, adapter, policy) {
|
|
431
|
-
const policyValidation = validateLayerValue(null, policy);
|
|
432
|
-
if (!policyValidation.ok && policyValidation.diagnostics.some((entry) => entry.code === "source.invalid-policy")) return policyValidation;
|
|
433
|
-
const ownedPolicy = frozenPolicy(policy);
|
|
434
|
-
const diagnostics = [];
|
|
435
|
-
const maxDiagnostics = diagnosticLimit(ownedPolicy);
|
|
436
|
-
let limited = false;
|
|
437
|
-
const add = (value) => {
|
|
438
|
-
if (limited) return;
|
|
439
|
-
if (diagnostics.length + 1 < maxDiagnostics) {
|
|
440
|
-
diagnostics.push(value);
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
limited = true;
|
|
444
|
-
diagnostics.push(diagnostic("source.diagnostic-limit", "Additional source diagnostics were omitted."));
|
|
445
|
-
};
|
|
446
|
-
const context = Object.freeze({
|
|
447
|
-
policy: ownedPolicy,
|
|
448
|
-
limits: ownedPolicy.limits,
|
|
449
|
-
diagnose(code, message) {
|
|
450
|
-
add(copyDiagnostic({
|
|
451
|
-
code,
|
|
452
|
-
message
|
|
453
|
-
}));
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
const result = adapter.adapt(input, context);
|
|
457
|
-
if (result === null || typeof result !== "object") add(diagnostic("source.invalid-adapter-result", "The source adapter returned an invalid result."));
|
|
458
|
-
else if (result.diagnostics !== void 0) {
|
|
459
|
-
if (!Array.isArray(result.diagnostics)) add(diagnostic("source.invalid-adapter-result", "The source adapter returned an invalid result."));
|
|
460
|
-
else for (const entry of result.diagnostics) add(copyDiagnostic(entry));
|
|
461
|
-
}
|
|
462
|
-
if (diagnostics.length > 0) return {
|
|
463
|
-
ok: false,
|
|
464
|
-
diagnostics: Object.freeze(diagnostics)
|
|
465
|
-
};
|
|
466
|
-
if (result === null || typeof result !== "object" || result.layer === void 0) return {
|
|
467
|
-
ok: false,
|
|
468
|
-
diagnostics: Object.freeze([diagnostic("source.invalid-adapter-result", "The source adapter did not return a declaration layer.")])
|
|
469
|
-
};
|
|
470
|
-
return validateLayerValue(result.layer, ownedPolicy);
|
|
471
|
-
}
|
|
472
|
-
const parseResultAdapter = Object.freeze({ adapt(input) {
|
|
473
|
-
return input.ok ? { layer: input.value } : { diagnostics: input.diagnostics };
|
|
474
|
-
} });
|
|
475
|
-
//#endregion
|
|
476
480
|
//#region src/runtime-source.ts
|
|
477
|
-
|
|
481
|
+
const INVALID_FORMAT = Object.freeze({
|
|
482
|
+
code: "source.invalid-format",
|
|
483
|
+
message: "The source format must be json or yaml."
|
|
484
|
+
});
|
|
485
|
+
function rejection(diagnostics) {
|
|
478
486
|
return Object.freeze({
|
|
479
487
|
status: "rejected",
|
|
480
488
|
diagnostics: Object.freeze(diagnostics.map((entry) => Object.freeze({
|
|
@@ -483,17 +491,24 @@ function adaptationFailure(diagnostics) {
|
|
|
483
491
|
})))
|
|
484
492
|
});
|
|
485
493
|
}
|
|
486
|
-
function createConfigRuntimeSource(id,
|
|
487
|
-
|
|
494
|
+
function createConfigRuntimeSource(id, options) {
|
|
495
|
+
const policy = ownedPolicy(options.policy);
|
|
496
|
+
const { load } = options;
|
|
497
|
+
const source = Object.freeze({
|
|
488
498
|
id,
|
|
489
499
|
async load(context) {
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
return
|
|
500
|
+
const raw = await load(context);
|
|
501
|
+
const parsed = raw.format === "json" ? parseJsonLayer(raw.text, policy) : raw.format === "yaml" ? parseYamlLayer(raw.text, policy) : void 0;
|
|
502
|
+
if (parsed === void 0) return rejection([INVALID_FORMAT]);
|
|
503
|
+
return parsed.ok ? parsed.value : rejection(parsed.diagnostics);
|
|
493
504
|
}
|
|
494
505
|
});
|
|
506
|
+
return Object.freeze({
|
|
507
|
+
source,
|
|
508
|
+
trust: policy.grants
|
|
509
|
+
});
|
|
495
510
|
}
|
|
496
511
|
//#endregion
|
|
497
|
-
export {
|
|
512
|
+
export { MAX_SOURCE_DEPTH, SCREEN_SOURCE_LIMITS, createConfigRuntimeSource, parseJsonLayer, parseYamlLayer };
|
|
498
513
|
|
|
499
514
|
//# sourceMappingURL=index.js.map
|