@burojs/config 0.2.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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/index.cjs +563 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +557 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
import { parseDocument } from 'yaml';
|
|
2
|
+
|
|
3
|
+
// src/parse.ts
|
|
4
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
5
|
+
var FORBIDDEN_VALUE_CATEGORIES = /* @__PURE__ */ new Map([
|
|
6
|
+
["action", "action"],
|
|
7
|
+
["actions", "action"],
|
|
8
|
+
["provider", "provider"],
|
|
9
|
+
["providers", "provider"],
|
|
10
|
+
["mapper", "mapper"],
|
|
11
|
+
["mappers", "mapper"],
|
|
12
|
+
["service", "service"],
|
|
13
|
+
["services", "service"],
|
|
14
|
+
["credential", "credential"],
|
|
15
|
+
["credentials", "credential"],
|
|
16
|
+
["schema", "schema"],
|
|
17
|
+
["schemas", "schema"],
|
|
18
|
+
["component", "component"],
|
|
19
|
+
["components", "component"],
|
|
20
|
+
["attachment", "attachment"],
|
|
21
|
+
["attachments", "attachment"],
|
|
22
|
+
["validator", "validator"],
|
|
23
|
+
["validators", "validator"]
|
|
24
|
+
]);
|
|
25
|
+
var LAYER_KEYS = /* @__PURE__ */ new Set([
|
|
26
|
+
"id",
|
|
27
|
+
"priority",
|
|
28
|
+
"defaultNamespace",
|
|
29
|
+
"revision",
|
|
30
|
+
"declarations",
|
|
31
|
+
"transforms"
|
|
32
|
+
]);
|
|
33
|
+
var DECLARATION_KEYS = /* @__PURE__ */ new Set(["kind", "ref", "schemaVersion", "value"]);
|
|
34
|
+
var TRANSFORM_KEYS = /* @__PURE__ */ new Set(["id", "scope", "select", "operation"]);
|
|
35
|
+
var SELECTOR_KEYS = /* @__PURE__ */ new Set(["kinds", "namespaces", "layers", "refs", "excludeRefs", "tags"]);
|
|
36
|
+
var OPERATION_KEYS = {
|
|
37
|
+
merge: /* @__PURE__ */ new Set(["op", "value"]),
|
|
38
|
+
replace: /* @__PURE__ */ new Set(["op", "value", "ifMissing"]),
|
|
39
|
+
disable: /* @__PURE__ */ new Set(["op", "reason"]),
|
|
40
|
+
delete: /* @__PURE__ */ new Set(["op"])
|
|
41
|
+
};
|
|
42
|
+
var ATTACHMENT_TAG = "@burojs/core/trusted-attachment";
|
|
43
|
+
var Diagnostics = class {
|
|
44
|
+
constructor(limit) {
|
|
45
|
+
this.limit = limit;
|
|
46
|
+
}
|
|
47
|
+
limit;
|
|
48
|
+
values = [];
|
|
49
|
+
limited = false;
|
|
50
|
+
add(code) {
|
|
51
|
+
if (this.limited) return;
|
|
52
|
+
if (this.values.length + 1 < this.limit) {
|
|
53
|
+
this.values.push(Object.freeze({ code, message: messageFor(code) }));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.limited = true;
|
|
57
|
+
this.values.push(
|
|
58
|
+
Object.freeze({
|
|
59
|
+
code: "source.diagnostic-limit",
|
|
60
|
+
message: messageFor("source.diagnostic-limit")
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
function messageFor(code) {
|
|
66
|
+
switch (code) {
|
|
67
|
+
case "source.invalid-json":
|
|
68
|
+
return "The source is not valid JSON.";
|
|
69
|
+
case "source.invalid-yaml":
|
|
70
|
+
return "The source is not valid YAML.";
|
|
71
|
+
case "source.invalid-policy":
|
|
72
|
+
return "The source policy is invalid.";
|
|
73
|
+
case "source.byte-limit":
|
|
74
|
+
return "The source exceeds its byte limit.";
|
|
75
|
+
case "source.declaration-limit":
|
|
76
|
+
return "The source exceeds its declaration limit.";
|
|
77
|
+
case "source.depth-limit":
|
|
78
|
+
return "The source exceeds its nesting-depth limit.";
|
|
79
|
+
case "source.string-limit":
|
|
80
|
+
return "The source contains an overlong string.";
|
|
81
|
+
case "source.diagnostic-limit":
|
|
82
|
+
return "Additional source diagnostics were omitted.";
|
|
83
|
+
case "source.unknown-key":
|
|
84
|
+
return "The source contains an unknown key.";
|
|
85
|
+
case "source.reserved-key":
|
|
86
|
+
return "The source contains a reserved key.";
|
|
87
|
+
case "source.accessor":
|
|
88
|
+
return "The source must use data properties.";
|
|
89
|
+
case "source.cyclic-value":
|
|
90
|
+
return "The source must not contain cyclic values.";
|
|
91
|
+
case "source.invalid-layer":
|
|
92
|
+
return "The source layer is invalid.";
|
|
93
|
+
case "source.invalid-declaration":
|
|
94
|
+
return "The source declaration is invalid.";
|
|
95
|
+
case "source.invalid-transform":
|
|
96
|
+
return "The source transform is invalid.";
|
|
97
|
+
case "source.forbidden-kind":
|
|
98
|
+
return "The source requests a forbidden declaration kind.";
|
|
99
|
+
case "source.forbidden-namespace":
|
|
100
|
+
return "The source requests a forbidden namespace.";
|
|
101
|
+
case "source.forbidden-transform-op":
|
|
102
|
+
return "The source requests a forbidden transform operation.";
|
|
103
|
+
case "source.forbidden-transform-scope":
|
|
104
|
+
return "The source requests a forbidden transform scope.";
|
|
105
|
+
case "source.forbidden-capability":
|
|
106
|
+
return "The source requests a forbidden capability.";
|
|
107
|
+
case "source.forbidden-action":
|
|
108
|
+
return "The source requests a forbidden action binding.";
|
|
109
|
+
case "source.forbidden-provider":
|
|
110
|
+
return "The source requests a forbidden provider binding.";
|
|
111
|
+
case "source.forbidden-mapper":
|
|
112
|
+
return "The source requests a forbidden mapper binding.";
|
|
113
|
+
case "source.forbidden-service":
|
|
114
|
+
return "The source requests a forbidden service value.";
|
|
115
|
+
case "source.forbidden-credential":
|
|
116
|
+
return "The source requests a forbidden credential value.";
|
|
117
|
+
case "source.forbidden-schema":
|
|
118
|
+
return "The source requests a forbidden schema value.";
|
|
119
|
+
case "source.forbidden-component":
|
|
120
|
+
return "The source requests a forbidden component value.";
|
|
121
|
+
case "source.forbidden-attachment":
|
|
122
|
+
return "The source requests a forbidden attachment value.";
|
|
123
|
+
case "source.forbidden-validator":
|
|
124
|
+
return "The source requests a forbidden validator value.";
|
|
125
|
+
default:
|
|
126
|
+
return "The source is invalid.";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function validLimits(limits) {
|
|
130
|
+
return Object.values(limits).every((value) => Number.isSafeInteger(value) && value > 0);
|
|
131
|
+
}
|
|
132
|
+
function validCapabilities(value) {
|
|
133
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every(
|
|
134
|
+
(capabilities) => Array.isArray(capabilities) && capabilities.every((capability) => typeof capability === "string")
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
function validPolicy(policy) {
|
|
138
|
+
return policy !== null && typeof policy === "object" && Array.isArray(policy.allowedKinds) && Array.isArray(policy.allowedNamespaces) && Array.isArray(policy.allowedTransformOps) && (policy.maxTransformScope === "layer" || policy.maxTransformScope === "namespace" || policy.maxTransformScope === "application") && validCapabilities(policy.allowedCapabilities) && validLimits(policy.limits);
|
|
139
|
+
}
|
|
140
|
+
function failure(diagnostics) {
|
|
141
|
+
return { ok: false, diagnostics: Object.freeze(diagnostics.values) };
|
|
142
|
+
}
|
|
143
|
+
function plainObject(value) {
|
|
144
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
145
|
+
const prototype = Object.getPrototypeOf(value);
|
|
146
|
+
return prototype === Object.prototype || prototype === null;
|
|
147
|
+
}
|
|
148
|
+
function ownData(value, key) {
|
|
149
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
150
|
+
return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
|
|
151
|
+
}
|
|
152
|
+
function hasData(value, key) {
|
|
153
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
154
|
+
return descriptor !== void 0 && "value" in descriptor;
|
|
155
|
+
}
|
|
156
|
+
function clonePortable(value, limits, diagnostics) {
|
|
157
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
158
|
+
function copy(current, depth) {
|
|
159
|
+
if (depth > limits.maxDepth) {
|
|
160
|
+
diagnostics.add("source.depth-limit");
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
if (current === null || typeof current === "boolean" || typeof current === "number")
|
|
164
|
+
return current;
|
|
165
|
+
if (typeof current === "string") {
|
|
166
|
+
if ([...current].length > limits.maxStringLength) diagnostics.add("source.string-limit");
|
|
167
|
+
return current;
|
|
168
|
+
}
|
|
169
|
+
if (typeof current !== "object") {
|
|
170
|
+
diagnostics.add("source.invalid-layer");
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
if (ancestors.has(current)) {
|
|
174
|
+
diagnostics.add("source.cyclic-value");
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
ancestors.add(current);
|
|
178
|
+
if (Array.isArray(current)) {
|
|
179
|
+
const output2 = [];
|
|
180
|
+
for (const key of Reflect.ownKeys(current)) {
|
|
181
|
+
if (typeof key !== "string" || key !== "length" && !/^(0|[1-9]\d*)$/u.test(key)) {
|
|
182
|
+
diagnostics.add("source.invalid-layer");
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (key === "length") continue;
|
|
186
|
+
if (!hasData(current, key)) diagnostics.add("source.accessor");
|
|
187
|
+
}
|
|
188
|
+
const length = ownData(current, "length");
|
|
189
|
+
const arrayLength = typeof length === "number" && Number.isSafeInteger(length) && length >= 0 ? length : void 0;
|
|
190
|
+
if (arrayLength === void 0) diagnostics.add("source.invalid-layer");
|
|
191
|
+
else
|
|
192
|
+
for (let index = 0; index < arrayLength; index += 1) {
|
|
193
|
+
if (!hasData(current, String(index))) diagnostics.add("source.accessor");
|
|
194
|
+
output2.push(copy(ownData(current, String(index)), depth + 1));
|
|
195
|
+
}
|
|
196
|
+
ancestors.delete(current);
|
|
197
|
+
return Object.freeze(output2);
|
|
198
|
+
}
|
|
199
|
+
if (!plainObject(current)) diagnostics.add("source.invalid-layer");
|
|
200
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
201
|
+
for (const key of Reflect.ownKeys(current)) {
|
|
202
|
+
if (typeof key !== "string") {
|
|
203
|
+
diagnostics.add("source.invalid-layer");
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (RESERVED_KEYS.has(key)) diagnostics.add("source.reserved-key");
|
|
207
|
+
if ([...key].length > limits.maxStringLength) diagnostics.add("source.string-limit");
|
|
208
|
+
if (!hasData(current, key)) {
|
|
209
|
+
diagnostics.add("source.accessor");
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
output[key] = copy(ownData(current, key), depth + 1);
|
|
213
|
+
}
|
|
214
|
+
ancestors.delete(current);
|
|
215
|
+
return Object.freeze(output);
|
|
216
|
+
}
|
|
217
|
+
return copy(value, 0);
|
|
218
|
+
}
|
|
219
|
+
function unknownKeys(value, allowed, diagnostics) {
|
|
220
|
+
for (const key of Object.keys(value))
|
|
221
|
+
if (!allowed.has(key)) diagnostics.add("source.unknown-key");
|
|
222
|
+
}
|
|
223
|
+
function allowedNamespace(value, policy, diagnostics) {
|
|
224
|
+
if (typeof value !== "string" || !policy.allowedNamespaces.includes(value)) {
|
|
225
|
+
diagnostics.add("source.forbidden-namespace");
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
function namespaceFor(ref, defaultNamespace, diagnostics) {
|
|
231
|
+
if (typeof ref === "string") {
|
|
232
|
+
const separator = ref.indexOf(":");
|
|
233
|
+
return separator === -1 ? defaultNamespace : ref.slice(0, separator);
|
|
234
|
+
}
|
|
235
|
+
if (!plainObject(ref) || !hasData(ref, "id")) {
|
|
236
|
+
diagnostics.add("source.invalid-declaration");
|
|
237
|
+
return void 0;
|
|
238
|
+
}
|
|
239
|
+
for (const key of Object.keys(ref))
|
|
240
|
+
if (key !== "id" && key !== "namespace") diagnostics.add("source.unknown-key");
|
|
241
|
+
const namespace = hasData(ref, "namespace") ? ownData(ref, "namespace") : defaultNamespace;
|
|
242
|
+
if (typeof namespace !== "string") diagnostics.add("source.invalid-declaration");
|
|
243
|
+
return typeof namespace === "string" ? namespace : void 0;
|
|
244
|
+
}
|
|
245
|
+
function validateValue(value, kind, policy, diagnostics) {
|
|
246
|
+
if (value === null || typeof value !== "object") return;
|
|
247
|
+
if (Array.isArray(value)) {
|
|
248
|
+
for (const item of value) validateValue(item, kind, policy, diagnostics);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (!plainObject(value)) return;
|
|
252
|
+
if (value.$buro === ATTACHMENT_TAG) {
|
|
253
|
+
const capability = ownData(value, "capability");
|
|
254
|
+
if (typeof capability !== "string" || !policy.allowedCapabilities[kind]?.includes(capability)) {
|
|
255
|
+
diagnostics.add("source.forbidden-capability");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
for (const key of Object.keys(value)) {
|
|
259
|
+
const category = FORBIDDEN_VALUE_CATEGORIES.get(key);
|
|
260
|
+
if (category !== void 0) diagnostics.add(`source.forbidden-${category}`);
|
|
261
|
+
validateValue(ownData(value, key), kind, policy, diagnostics);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function scopeRank(scope) {
|
|
265
|
+
return scope === "layer" ? 0 : scope === "namespace" ? 1 : 2;
|
|
266
|
+
}
|
|
267
|
+
function transformOperation(value) {
|
|
268
|
+
if (!plainObject(value)) return void 0;
|
|
269
|
+
const operation = ownData(value, "op");
|
|
270
|
+
return operation === "merge" || operation === "replace" || operation === "disable" || operation === "delete" ? operation : void 0;
|
|
271
|
+
}
|
|
272
|
+
function validateSelectorRefs(value, defaultNamespace, policy, diagnostics) {
|
|
273
|
+
if (value === void 0) return;
|
|
274
|
+
if (!Array.isArray(value)) {
|
|
275
|
+
diagnostics.add("source.invalid-transform");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
for (const ref of value) {
|
|
279
|
+
const namespace = namespaceFor(ref, defaultNamespace, diagnostics);
|
|
280
|
+
if (namespace !== void 0) allowedNamespace(namespace, policy, diagnostics);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function validateTransforms(value, defaultNamespace, policy, diagnostics) {
|
|
284
|
+
if (value === void 0) return;
|
|
285
|
+
if (!Array.isArray(value)) {
|
|
286
|
+
diagnostics.add("source.invalid-transform");
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
for (const transform of value) {
|
|
290
|
+
if (!plainObject(transform)) {
|
|
291
|
+
diagnostics.add("source.invalid-transform");
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
unknownKeys(transform, TRANSFORM_KEYS, diagnostics);
|
|
295
|
+
const scope = ownData(transform, "scope") ?? "layer";
|
|
296
|
+
if (scope !== "layer" && scope !== "application") diagnostics.add("source.invalid-transform");
|
|
297
|
+
else if (scopeRank(scope) > scopeRank(policy.maxTransformScope))
|
|
298
|
+
diagnostics.add("source.forbidden-transform-scope");
|
|
299
|
+
const select = ownData(transform, "select");
|
|
300
|
+
if (!plainObject(select)) diagnostics.add("source.invalid-transform");
|
|
301
|
+
else {
|
|
302
|
+
unknownKeys(select, SELECTOR_KEYS, diagnostics);
|
|
303
|
+
const selectedKinds = ownData(select, "kinds");
|
|
304
|
+
if (selectedKinds !== void 0) {
|
|
305
|
+
if (!Array.isArray(selectedKinds)) diagnostics.add("source.invalid-transform");
|
|
306
|
+
else
|
|
307
|
+
for (const kind of selectedKinds) {
|
|
308
|
+
if (typeof kind !== "string") diagnostics.add("source.invalid-transform");
|
|
309
|
+
else if (!policy.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const selectedNamespaces = ownData(select, "namespaces");
|
|
313
|
+
if (selectedNamespaces !== void 0) {
|
|
314
|
+
if (!Array.isArray(selectedNamespaces)) diagnostics.add("source.invalid-transform");
|
|
315
|
+
else
|
|
316
|
+
for (const namespace of selectedNamespaces)
|
|
317
|
+
allowedNamespace(namespace, policy, diagnostics);
|
|
318
|
+
}
|
|
319
|
+
validateSelectorRefs(ownData(select, "refs"), defaultNamespace, policy, diagnostics);
|
|
320
|
+
validateSelectorRefs(ownData(select, "excludeRefs"), defaultNamespace, policy, diagnostics);
|
|
321
|
+
}
|
|
322
|
+
const operation = ownData(transform, "operation");
|
|
323
|
+
const op = transformOperation(operation);
|
|
324
|
+
const rawOp = plainObject(operation) ? ownData(operation, "op") : void 0;
|
|
325
|
+
if (typeof rawOp === "string" && op === void 0)
|
|
326
|
+
diagnostics.add("source.forbidden-transform-op");
|
|
327
|
+
else if (op === void 0) diagnostics.add("source.invalid-transform");
|
|
328
|
+
else {
|
|
329
|
+
if (!policy.allowedTransformOps.includes(op))
|
|
330
|
+
diagnostics.add("source.forbidden-transform-op");
|
|
331
|
+
if (plainObject(operation)) {
|
|
332
|
+
unknownKeys(operation, OPERATION_KEYS[op], diagnostics);
|
|
333
|
+
if (hasData(operation, "value"))
|
|
334
|
+
validateValue(ownData(operation, "value"), "", policy, diagnostics);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function validateLayerValue(value, policy) {
|
|
340
|
+
if (!validPolicy(policy)) {
|
|
341
|
+
return {
|
|
342
|
+
ok: false,
|
|
343
|
+
diagnostics: Object.freeze([
|
|
344
|
+
Object.freeze({
|
|
345
|
+
code: "source.invalid-policy",
|
|
346
|
+
message: messageFor("source.invalid-policy")
|
|
347
|
+
})
|
|
348
|
+
])
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);
|
|
352
|
+
const cloned = clonePortable(value, policy.limits, diagnostics);
|
|
353
|
+
if (diagnostics.values.length > 0) return failure(diagnostics);
|
|
354
|
+
if (!plainObject(cloned)) {
|
|
355
|
+
diagnostics.add("source.invalid-layer");
|
|
356
|
+
return failure(diagnostics);
|
|
357
|
+
}
|
|
358
|
+
unknownKeys(cloned, LAYER_KEYS, diagnostics);
|
|
359
|
+
const id = ownData(cloned, "id");
|
|
360
|
+
const priority = ownData(cloned, "priority");
|
|
361
|
+
const declarations = ownData(cloned, "declarations");
|
|
362
|
+
if (typeof id !== "string" || !Number.isSafeInteger(priority) || !Array.isArray(declarations)) {
|
|
363
|
+
diagnostics.add("source.invalid-layer");
|
|
364
|
+
return failure(diagnostics);
|
|
365
|
+
}
|
|
366
|
+
if (declarations.length > policy.limits.maxDeclarations)
|
|
367
|
+
diagnostics.add("source.declaration-limit");
|
|
368
|
+
const rawDefaultNamespace = ownData(cloned, "defaultNamespace");
|
|
369
|
+
const defaultNamespace = rawDefaultNamespace === void 0 ? "default" : rawDefaultNamespace;
|
|
370
|
+
if (typeof defaultNamespace !== "string") diagnostics.add("source.invalid-layer");
|
|
371
|
+
else allowedNamespace(defaultNamespace, policy, diagnostics);
|
|
372
|
+
for (const declaration of declarations) {
|
|
373
|
+
if (!plainObject(declaration)) {
|
|
374
|
+
diagnostics.add("source.invalid-declaration");
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
unknownKeys(declaration, DECLARATION_KEYS, diagnostics);
|
|
378
|
+
const kind = ownData(declaration, "kind");
|
|
379
|
+
if (typeof kind !== "string") diagnostics.add("source.invalid-declaration");
|
|
380
|
+
else if (!policy.allowedKinds.includes(kind)) diagnostics.add("source.forbidden-kind");
|
|
381
|
+
const namespace = namespaceFor(
|
|
382
|
+
ownData(declaration, "ref"),
|
|
383
|
+
typeof defaultNamespace === "string" ? defaultNamespace : "default",
|
|
384
|
+
diagnostics
|
|
385
|
+
);
|
|
386
|
+
if (namespace !== void 0) allowedNamespace(namespace, policy, diagnostics);
|
|
387
|
+
if (!Number.isSafeInteger(ownData(declaration, "schemaVersion")) || !hasData(declaration, "value")) {
|
|
388
|
+
diagnostics.add("source.invalid-declaration");
|
|
389
|
+
}
|
|
390
|
+
if (typeof kind === "string" && hasData(declaration, "value")) {
|
|
391
|
+
validateValue(ownData(declaration, "value"), kind, policy, diagnostics);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
validateTransforms(
|
|
395
|
+
ownData(cloned, "transforms"),
|
|
396
|
+
typeof defaultNamespace === "string" ? defaultNamespace : "default",
|
|
397
|
+
policy,
|
|
398
|
+
diagnostics
|
|
399
|
+
);
|
|
400
|
+
if (diagnostics.values.length > 0) return failure(diagnostics);
|
|
401
|
+
return { ok: true, value: cloned };
|
|
402
|
+
}
|
|
403
|
+
function byteLength(value) {
|
|
404
|
+
return new TextEncoder().encode(value).byteLength;
|
|
405
|
+
}
|
|
406
|
+
function parseSource(source, policy, format) {
|
|
407
|
+
if (!validPolicy(policy)) return validateLayerValue(null, policy);
|
|
408
|
+
const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);
|
|
409
|
+
if (byteLength(source) > policy.limits.maxBytes) {
|
|
410
|
+
diagnostics.add("source.byte-limit");
|
|
411
|
+
return failure(diagnostics);
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
if (format === "json") return validateLayerValue(JSON.parse(source), policy);
|
|
415
|
+
const document = parseDocument(source, { prettyErrors: false, strict: true, uniqueKeys: true });
|
|
416
|
+
if (document.errors.length > 0) {
|
|
417
|
+
diagnostics.add("source.invalid-yaml");
|
|
418
|
+
return failure(diagnostics);
|
|
419
|
+
}
|
|
420
|
+
return validateLayerValue(document.toJS({ maxAliasCount: 0 }), policy);
|
|
421
|
+
} catch {
|
|
422
|
+
diagnostics.add(format === "json" ? "source.invalid-json" : "source.invalid-yaml");
|
|
423
|
+
return failure(diagnostics);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
function parseJsonLayer(source, policy) {
|
|
427
|
+
return parseSource(source, policy, "json");
|
|
428
|
+
}
|
|
429
|
+
function parseYamlLayer(source, policy) {
|
|
430
|
+
return parseSource(source, policy, "yaml");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/adapter.ts
|
|
434
|
+
function diagnostic(code, message) {
|
|
435
|
+
return Object.freeze({ code, message });
|
|
436
|
+
}
|
|
437
|
+
function diagnosticLimit(policy) {
|
|
438
|
+
const candidate = policy?.limits?.maxDiagnostics;
|
|
439
|
+
return typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate > 0 ? candidate : 1;
|
|
440
|
+
}
|
|
441
|
+
function frozenPolicy(policy) {
|
|
442
|
+
const capabilities = /* @__PURE__ */ Object.create(null);
|
|
443
|
+
for (const [kind, values] of Object.entries(policy.allowedCapabilities)) {
|
|
444
|
+
capabilities[kind] = Object.freeze([...values]);
|
|
445
|
+
}
|
|
446
|
+
const limits = Object.freeze({ ...policy.limits });
|
|
447
|
+
return Object.freeze({
|
|
448
|
+
allowedKinds: Object.freeze([...policy.allowedKinds]),
|
|
449
|
+
allowedNamespaces: Object.freeze([...policy.allowedNamespaces]),
|
|
450
|
+
allowedTransformOps: Object.freeze([...policy.allowedTransformOps]),
|
|
451
|
+
maxTransformScope: policy.maxTransformScope,
|
|
452
|
+
allowedCapabilities: Object.freeze(capabilities),
|
|
453
|
+
limits
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
function copyDiagnostic(value) {
|
|
457
|
+
if (value !== null && typeof value === "object" && typeof value.code === "string" && typeof value.message === "string") {
|
|
458
|
+
return diagnostic(
|
|
459
|
+
value.code,
|
|
460
|
+
value.message
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
return diagnostic(
|
|
464
|
+
"source.invalid-adapter-diagnostic",
|
|
465
|
+
"The source adapter returned an invalid diagnostic."
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
function adaptRawConfig(input, adapter, policy) {
|
|
469
|
+
const policyValidation = validateLayerValue(null, policy);
|
|
470
|
+
if (!policyValidation.ok && policyValidation.diagnostics.some((entry) => entry.code === "source.invalid-policy")) {
|
|
471
|
+
return policyValidation;
|
|
472
|
+
}
|
|
473
|
+
const ownedPolicy = frozenPolicy(policy);
|
|
474
|
+
const diagnostics = [];
|
|
475
|
+
const maxDiagnostics = diagnosticLimit(ownedPolicy);
|
|
476
|
+
let limited = false;
|
|
477
|
+
const add = (value) => {
|
|
478
|
+
if (limited) return;
|
|
479
|
+
if (diagnostics.length + 1 < maxDiagnostics) {
|
|
480
|
+
diagnostics.push(value);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
limited = true;
|
|
484
|
+
diagnostics.push(
|
|
485
|
+
diagnostic("source.diagnostic-limit", "Additional source diagnostics were omitted.")
|
|
486
|
+
);
|
|
487
|
+
};
|
|
488
|
+
const context = Object.freeze({
|
|
489
|
+
policy: ownedPolicy,
|
|
490
|
+
limits: ownedPolicy.limits,
|
|
491
|
+
diagnose(code, message) {
|
|
492
|
+
add(copyDiagnostic({ code, message }));
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
const result = adapter.adapt(input, context);
|
|
496
|
+
if (result === null || typeof result !== "object") {
|
|
497
|
+
add(
|
|
498
|
+
diagnostic("source.invalid-adapter-result", "The source adapter returned an invalid result.")
|
|
499
|
+
);
|
|
500
|
+
} else if (result.diagnostics !== void 0) {
|
|
501
|
+
if (!Array.isArray(result.diagnostics)) {
|
|
502
|
+
add(
|
|
503
|
+
diagnostic(
|
|
504
|
+
"source.invalid-adapter-result",
|
|
505
|
+
"The source adapter returned an invalid result."
|
|
506
|
+
)
|
|
507
|
+
);
|
|
508
|
+
} else {
|
|
509
|
+
for (const entry of result.diagnostics) add(copyDiagnostic(entry));
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (diagnostics.length > 0) {
|
|
513
|
+
return { ok: false, diagnostics: Object.freeze(diagnostics) };
|
|
514
|
+
}
|
|
515
|
+
if (result === null || typeof result !== "object" || result.layer === void 0) {
|
|
516
|
+
return {
|
|
517
|
+
ok: false,
|
|
518
|
+
diagnostics: Object.freeze([
|
|
519
|
+
diagnostic(
|
|
520
|
+
"source.invalid-adapter-result",
|
|
521
|
+
"The source adapter did not return a declaration layer."
|
|
522
|
+
)
|
|
523
|
+
])
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
return validateLayerValue(result.layer, ownedPolicy);
|
|
527
|
+
}
|
|
528
|
+
var parseResultAdapter = Object.freeze({
|
|
529
|
+
adapt(input) {
|
|
530
|
+
return input.ok ? { layer: input.value } : { diagnostics: input.diagnostics };
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// src/runtime-source.ts
|
|
535
|
+
function adaptationFailure(diagnostics) {
|
|
536
|
+
return Object.freeze({
|
|
537
|
+
status: "rejected",
|
|
538
|
+
diagnostics: Object.freeze(
|
|
539
|
+
diagnostics.map((entry) => Object.freeze({ code: entry.code, message: entry.message }))
|
|
540
|
+
)
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
function createConfigRuntimeSource(id, fetchRaw, adapter, policy) {
|
|
544
|
+
return Object.freeze({
|
|
545
|
+
id,
|
|
546
|
+
async load(context) {
|
|
547
|
+
const raw = await fetchRaw(context);
|
|
548
|
+
const adapted = adaptRawConfig(raw, adapter, policy);
|
|
549
|
+
if (!adapted.ok) return adaptationFailure(adapted.diagnostics);
|
|
550
|
+
return adapted.value;
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export { adaptRawConfig, createConfigRuntimeSource, parseJsonLayer, parseResultAdapter, parseYamlLayer };
|
|
556
|
+
//# sourceMappingURL=index.js.map
|
|
557
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parse.ts","../src/adapter.ts","../src/runtime-source.ts"],"names":["output"],"mappings":"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","file":"index.js","sourcesContent":["import type { LayerInput } from '@burojs/core';\nimport { parseDocument } from 'yaml';\nimport type { SourceLimits, SourcePolicy, TransformOp } from './source-policy.js';\n\nconst RESERVED_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\nconst FORBIDDEN_VALUE_CATEGORIES: ReadonlyMap<string, string> = new Map([\n ['action', 'action'],\n ['actions', 'action'],\n ['provider', 'provider'],\n ['providers', 'provider'],\n ['mapper', 'mapper'],\n ['mappers', 'mapper'],\n ['service', 'service'],\n ['services', 'service'],\n ['credential', 'credential'],\n ['credentials', 'credential'],\n ['schema', 'schema'],\n ['schemas', 'schema'],\n ['component', 'component'],\n ['components', 'component'],\n ['attachment', 'attachment'],\n ['attachments', 'attachment'],\n ['validator', 'validator'],\n ['validators', 'validator'],\n] as const);\nconst LAYER_KEYS = new Set([\n 'id',\n 'priority',\n 'defaultNamespace',\n 'revision',\n 'declarations',\n 'transforms',\n]);\nconst DECLARATION_KEYS = new Set(['kind', 'ref', 'schemaVersion', 'value']);\nconst TRANSFORM_KEYS = new Set(['id', 'scope', 'select', 'operation']);\nconst SELECTOR_KEYS = new Set(['kinds', 'namespaces', 'layers', 'refs', 'excludeRefs', 'tags']);\nconst OPERATION_KEYS: Readonly<Record<TransformOp, ReadonlySet<string>>> = {\n merge: new Set(['op', 'value']),\n replace: new Set(['op', 'value', 'ifMissing']),\n disable: new Set(['op', 'reason']),\n delete: new Set(['op']),\n};\nconst ATTACHMENT_TAG = '@burojs/core/trusted-attachment';\n\nexport interface SourceDiagnostic {\n readonly code: string;\n readonly message: string;\n}\n\nexport type ParseResult =\n | { readonly ok: true; readonly value: LayerInput }\n | { readonly ok: false; readonly diagnostics: readonly SourceDiagnostic[] };\n\nclass Diagnostics {\n readonly values: SourceDiagnostic[] = [];\n private limited = false;\n\n constructor(private readonly limit: number) {}\n\n add(code: string): void {\n if (this.limited) return;\n if (this.values.length + 1 < this.limit) {\n this.values.push(Object.freeze({ code, message: messageFor(code) }));\n return;\n }\n this.limited = true;\n this.values.push(\n Object.freeze({\n code: 'source.diagnostic-limit',\n message: messageFor('source.diagnostic-limit'),\n }),\n );\n }\n}\n\nfunction messageFor(code: string): string {\n switch (code) {\n case 'source.invalid-json':\n return 'The source is not valid JSON.';\n case 'source.invalid-yaml':\n return 'The source is not valid YAML.';\n case 'source.invalid-policy':\n return 'The source policy is invalid.';\n case 'source.byte-limit':\n return 'The source exceeds its byte limit.';\n case 'source.declaration-limit':\n return 'The source exceeds its declaration limit.';\n case 'source.depth-limit':\n return 'The source exceeds its nesting-depth limit.';\n case 'source.string-limit':\n return 'The source contains an overlong string.';\n case 'source.diagnostic-limit':\n return 'Additional source diagnostics were omitted.';\n case 'source.unknown-key':\n return 'The source contains an unknown key.';\n case 'source.reserved-key':\n return 'The source contains a reserved key.';\n case 'source.accessor':\n return 'The source must use data properties.';\n case 'source.cyclic-value':\n return 'The source must not contain cyclic values.';\n case 'source.invalid-layer':\n return 'The source layer is invalid.';\n case 'source.invalid-declaration':\n return 'The source declaration is invalid.';\n case 'source.invalid-transform':\n return 'The source transform is invalid.';\n case 'source.forbidden-kind':\n return 'The source requests a forbidden declaration kind.';\n case 'source.forbidden-namespace':\n return 'The source requests a forbidden namespace.';\n case 'source.forbidden-transform-op':\n return 'The source requests a forbidden transform operation.';\n case 'source.forbidden-transform-scope':\n return 'The source requests a forbidden transform scope.';\n case 'source.forbidden-capability':\n return 'The source requests a forbidden capability.';\n case 'source.forbidden-action':\n return 'The source requests a forbidden action binding.';\n case 'source.forbidden-provider':\n return 'The source requests a forbidden provider binding.';\n case 'source.forbidden-mapper':\n return 'The source requests a forbidden mapper binding.';\n case 'source.forbidden-service':\n return 'The source requests a forbidden service value.';\n case 'source.forbidden-credential':\n return 'The source requests a forbidden credential value.';\n case 'source.forbidden-schema':\n return 'The source requests a forbidden schema value.';\n case 'source.forbidden-component':\n return 'The source requests a forbidden component value.';\n case 'source.forbidden-attachment':\n return 'The source requests a forbidden attachment value.';\n case 'source.forbidden-validator':\n return 'The source requests a forbidden validator value.';\n default:\n return 'The source is invalid.';\n }\n}\n\nfunction validLimits(limits: SourceLimits): boolean {\n return Object.values(limits).every((value) => Number.isSafeInteger(value) && value > 0);\n}\n\nfunction validCapabilities(value: unknown): value is Readonly<Record<string, readonly string[]>> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.values(value).every(\n (capabilities) =>\n Array.isArray(capabilities) &&\n capabilities.every((capability) => typeof capability === 'string'),\n )\n );\n}\n\nfunction validPolicy(policy: SourcePolicy): boolean {\n return (\n policy !== null &&\n typeof policy === 'object' &&\n Array.isArray(policy.allowedKinds) &&\n Array.isArray(policy.allowedNamespaces) &&\n Array.isArray(policy.allowedTransformOps) &&\n (policy.maxTransformScope === 'layer' ||\n policy.maxTransformScope === 'namespace' ||\n policy.maxTransformScope === 'application') &&\n validCapabilities(policy.allowedCapabilities) &&\n validLimits(policy.limits)\n );\n}\n\nfunction failure(diagnostics: Diagnostics): ParseResult {\n return { ok: false, diagnostics: Object.freeze(diagnostics.values) };\n}\n\nfunction plainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction ownData(value: object, key: string): unknown {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && 'value' in descriptor ? descriptor.value : undefined;\n}\n\nfunction hasData(value: object, key: string): boolean {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && 'value' in descriptor;\n}\n\nfunction clonePortable(value: unknown, limits: SourceLimits, diagnostics: Diagnostics): unknown {\n const ancestors = new WeakSet<object>();\n\n function copy(current: unknown, depth: number): unknown {\n if (depth > limits.maxDepth) {\n diagnostics.add('source.depth-limit');\n return null;\n }\n if (current === null || typeof current === 'boolean' || typeof current === 'number')\n return current;\n if (typeof current === 'string') {\n if ([...current].length > limits.maxStringLength) diagnostics.add('source.string-limit');\n return current;\n }\n if (typeof current !== 'object') {\n diagnostics.add('source.invalid-layer');\n return null;\n }\n if (ancestors.has(current)) {\n diagnostics.add('source.cyclic-value');\n return null;\n }\n ancestors.add(current);\n\n if (Array.isArray(current)) {\n const output: unknown[] = [];\n for (const key of Reflect.ownKeys(current)) {\n if (typeof key !== 'string' || (key !== 'length' && !/^(0|[1-9]\\d*)$/u.test(key))) {\n diagnostics.add('source.invalid-layer');\n continue;\n }\n if (key === 'length') continue;\n if (!hasData(current, key)) diagnostics.add('source.accessor');\n }\n const length = ownData(current, 'length');\n const arrayLength =\n typeof length === 'number' && Number.isSafeInteger(length) && length >= 0\n ? length\n : undefined;\n if (arrayLength === undefined) diagnostics.add('source.invalid-layer');\n else\n for (let index = 0; index < arrayLength; index += 1) {\n if (!hasData(current, String(index))) diagnostics.add('source.accessor');\n output.push(copy(ownData(current, String(index)), depth + 1));\n }\n ancestors.delete(current);\n return Object.freeze(output);\n }\n\n if (!plainObject(current)) diagnostics.add('source.invalid-layer');\n const output: Record<string, unknown> = Object.create(null);\n for (const key of Reflect.ownKeys(current)) {\n if (typeof key !== 'string') {\n diagnostics.add('source.invalid-layer');\n continue;\n }\n if (RESERVED_KEYS.has(key)) diagnostics.add('source.reserved-key');\n if ([...key].length > limits.maxStringLength) diagnostics.add('source.string-limit');\n if (!hasData(current, key)) {\n diagnostics.add('source.accessor');\n continue;\n }\n output[key] = copy(ownData(current, key), depth + 1);\n }\n ancestors.delete(current);\n return Object.freeze(output);\n }\n\n return copy(value, 0);\n}\n\nfunction unknownKeys(value: object, allowed: ReadonlySet<string>, diagnostics: Diagnostics): void {\n for (const key of Object.keys(value))\n if (!allowed.has(key)) diagnostics.add('source.unknown-key');\n}\n\nfunction allowedNamespace(value: unknown, policy: SourcePolicy, diagnostics: Diagnostics): boolean {\n if (typeof value !== 'string' || !policy.allowedNamespaces.includes(value)) {\n diagnostics.add('source.forbidden-namespace');\n return false;\n }\n return true;\n}\n\nfunction namespaceFor(\n ref: unknown,\n defaultNamespace: string,\n diagnostics: Diagnostics,\n): string | undefined {\n if (typeof ref === 'string') {\n const separator = ref.indexOf(':');\n return separator === -1 ? defaultNamespace : ref.slice(0, separator);\n }\n if (!plainObject(ref) || !hasData(ref, 'id')) {\n diagnostics.add('source.invalid-declaration');\n return undefined;\n }\n for (const key of Object.keys(ref))\n if (key !== 'id' && key !== 'namespace') diagnostics.add('source.unknown-key');\n const namespace = hasData(ref, 'namespace') ? ownData(ref, 'namespace') : defaultNamespace;\n if (typeof namespace !== 'string') diagnostics.add('source.invalid-declaration');\n return typeof namespace === 'string' ? namespace : undefined;\n}\n\nfunction validateValue(\n value: unknown,\n kind: string,\n policy: SourcePolicy,\n diagnostics: Diagnostics,\n): void {\n if (value === null || typeof value !== 'object') return;\n if (Array.isArray(value)) {\n for (const item of value) validateValue(item, kind, policy, diagnostics);\n return;\n }\n if (!plainObject(value)) return;\n if (value.$buro === ATTACHMENT_TAG) {\n const capability = ownData(value, 'capability');\n if (typeof capability !== 'string' || !policy.allowedCapabilities[kind]?.includes(capability)) {\n diagnostics.add('source.forbidden-capability');\n }\n }\n for (const key of Object.keys(value)) {\n const category = FORBIDDEN_VALUE_CATEGORIES.get(key);\n if (category !== undefined) diagnostics.add(`source.forbidden-${category}`);\n validateValue(ownData(value, key), kind, policy, diagnostics);\n }\n}\n\nfunction scopeRank(scope: SourcePolicy['maxTransformScope']): number {\n return scope === 'layer' ? 0 : scope === 'namespace' ? 1 : 2;\n}\n\nfunction transformOperation(value: unknown): TransformOp | undefined {\n if (!plainObject(value)) return undefined;\n const operation = ownData(value, 'op');\n return operation === 'merge' ||\n operation === 'replace' ||\n operation === 'disable' ||\n operation === 'delete'\n ? operation\n : undefined;\n}\n\nfunction validateSelectorRefs(\n value: unknown,\n defaultNamespace: string,\n policy: SourcePolicy,\n diagnostics: Diagnostics,\n): void {\n if (value === undefined) return;\n if (!Array.isArray(value)) {\n diagnostics.add('source.invalid-transform');\n return;\n }\n for (const ref of value) {\n const namespace = namespaceFor(ref, defaultNamespace, diagnostics);\n if (namespace !== undefined) allowedNamespace(namespace, policy, diagnostics);\n }\n}\n\nfunction validateTransforms(\n value: unknown,\n defaultNamespace: string,\n policy: SourcePolicy,\n diagnostics: Diagnostics,\n): void {\n if (value === undefined) return;\n if (!Array.isArray(value)) {\n diagnostics.add('source.invalid-transform');\n return;\n }\n for (const transform of value) {\n if (!plainObject(transform)) {\n diagnostics.add('source.invalid-transform');\n continue;\n }\n unknownKeys(transform, TRANSFORM_KEYS, diagnostics);\n const scope = ownData(transform, 'scope') ?? 'layer';\n if (scope !== 'layer' && scope !== 'application') diagnostics.add('source.invalid-transform');\n else if (scopeRank(scope) > scopeRank(policy.maxTransformScope))\n diagnostics.add('source.forbidden-transform-scope');\n const select = ownData(transform, 'select');\n if (!plainObject(select)) diagnostics.add('source.invalid-transform');\n else {\n unknownKeys(select, SELECTOR_KEYS, diagnostics);\n const selectedKinds = ownData(select, 'kinds');\n if (selectedKinds !== undefined) {\n if (!Array.isArray(selectedKinds)) diagnostics.add('source.invalid-transform');\n else\n for (const kind of selectedKinds) {\n if (typeof kind !== 'string') diagnostics.add('source.invalid-transform');\n else if (!policy.allowedKinds.includes(kind)) diagnostics.add('source.forbidden-kind');\n }\n }\n const selectedNamespaces = ownData(select, 'namespaces');\n if (selectedNamespaces !== undefined) {\n if (!Array.isArray(selectedNamespaces)) diagnostics.add('source.invalid-transform');\n else\n for (const namespace of selectedNamespaces)\n allowedNamespace(namespace, policy, diagnostics);\n }\n validateSelectorRefs(ownData(select, 'refs'), defaultNamespace, policy, diagnostics);\n validateSelectorRefs(ownData(select, 'excludeRefs'), defaultNamespace, policy, diagnostics);\n }\n const operation = ownData(transform, 'operation');\n const op = transformOperation(operation);\n const rawOp = plainObject(operation) ? ownData(operation, 'op') : undefined;\n if (typeof rawOp === 'string' && op === undefined)\n diagnostics.add('source.forbidden-transform-op');\n else if (op === undefined) diagnostics.add('source.invalid-transform');\n else {\n if (!policy.allowedTransformOps.includes(op))\n diagnostics.add('source.forbidden-transform-op');\n if (plainObject(operation)) {\n unknownKeys(operation, OPERATION_KEYS[op], diagnostics);\n if (hasData(operation, 'value'))\n validateValue(ownData(operation, 'value'), '', policy, diagnostics);\n }\n }\n }\n}\n\n/** Validates and clones a parser-produced value without retaining source-owned object references. */\nexport function validateLayerValue(value: unknown, policy: SourcePolicy): ParseResult {\n if (!validPolicy(policy)) {\n return {\n ok: false,\n diagnostics: Object.freeze([\n Object.freeze({\n code: 'source.invalid-policy',\n message: messageFor('source.invalid-policy'),\n }),\n ]),\n };\n }\n const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);\n const cloned = clonePortable(value, policy.limits, diagnostics);\n if (diagnostics.values.length > 0) return failure(diagnostics);\n if (!plainObject(cloned)) {\n diagnostics.add('source.invalid-layer');\n return failure(diagnostics);\n }\n unknownKeys(cloned, LAYER_KEYS, diagnostics);\n const id = ownData(cloned, 'id');\n const priority = ownData(cloned, 'priority');\n const declarations = ownData(cloned, 'declarations');\n if (typeof id !== 'string' || !Number.isSafeInteger(priority) || !Array.isArray(declarations)) {\n diagnostics.add('source.invalid-layer');\n return failure(diagnostics);\n }\n if (declarations.length > policy.limits.maxDeclarations)\n diagnostics.add('source.declaration-limit');\n const rawDefaultNamespace = ownData(cloned, 'defaultNamespace');\n const defaultNamespace = rawDefaultNamespace === undefined ? 'default' : rawDefaultNamespace;\n if (typeof defaultNamespace !== 'string') diagnostics.add('source.invalid-layer');\n else allowedNamespace(defaultNamespace, policy, diagnostics);\n for (const declaration of declarations) {\n if (!plainObject(declaration)) {\n diagnostics.add('source.invalid-declaration');\n continue;\n }\n unknownKeys(declaration, DECLARATION_KEYS, diagnostics);\n const kind = ownData(declaration, 'kind');\n if (typeof kind !== 'string') diagnostics.add('source.invalid-declaration');\n else if (!policy.allowedKinds.includes(kind)) diagnostics.add('source.forbidden-kind');\n const namespace = namespaceFor(\n ownData(declaration, 'ref'),\n typeof defaultNamespace === 'string' ? defaultNamespace : 'default',\n diagnostics,\n );\n if (namespace !== undefined) allowedNamespace(namespace, policy, diagnostics);\n if (\n !Number.isSafeInteger(ownData(declaration, 'schemaVersion')) ||\n !hasData(declaration, 'value')\n ) {\n diagnostics.add('source.invalid-declaration');\n }\n if (typeof kind === 'string' && hasData(declaration, 'value')) {\n validateValue(ownData(declaration, 'value'), kind, policy, diagnostics);\n }\n }\n validateTransforms(\n ownData(cloned, 'transforms'),\n typeof defaultNamespace === 'string' ? defaultNamespace : 'default',\n policy,\n diagnostics,\n );\n if (diagnostics.values.length > 0) return failure(diagnostics);\n return { ok: true, value: cloned as unknown as LayerInput };\n}\n\nfunction byteLength(value: string): number {\n return new TextEncoder().encode(value).byteLength;\n}\n\nfunction parseSource(source: string, policy: SourcePolicy, format: 'json' | 'yaml'): ParseResult {\n if (!validPolicy(policy)) return validateLayerValue(null, policy);\n const diagnostics = new Diagnostics(policy.limits.maxDiagnostics);\n if (byteLength(source) > policy.limits.maxBytes) {\n diagnostics.add('source.byte-limit');\n return failure(diagnostics);\n }\n try {\n if (format === 'json') return validateLayerValue(JSON.parse(source), policy);\n const document = parseDocument(source, { prettyErrors: false, strict: true, uniqueKeys: true });\n if (document.errors.length > 0) {\n diagnostics.add('source.invalid-yaml');\n return failure(diagnostics);\n }\n return validateLayerValue(document.toJS({ maxAliasCount: 0 }), policy);\n } catch {\n diagnostics.add(format === 'json' ? 'source.invalid-json' : 'source.invalid-yaml');\n return failure(diagnostics);\n }\n}\n\nexport function parseJsonLayer(source: string, policy: SourcePolicy): ParseResult {\n return parseSource(source, policy, 'json');\n}\n\nexport function parseYamlLayer(source: string, policy: SourcePolicy): ParseResult {\n return parseSource(source, policy, 'yaml');\n}\n","import type { LayerInput } from '@burojs/core';\nimport { type ParseResult, type SourceDiagnostic, validateLayerValue } from './parse.js';\nimport type { SourceLimits, SourcePolicy } from './source-policy.js';\n\n/** The portable parsed configuration form supplied by the built-in JSON/YAML readers. */\nexport type RawConfig = ParseResult;\n\n/** A framework-owned, inert declaration layer. Trusted attachments are intentionally excluded. */\nexport interface AdapterResult {\n readonly layer?: LayerInput;\n readonly diagnostics?: readonly SourceDiagnostic[];\n}\n\n/**\n * Immutable host-owned policy and diagnostic boundary supplied to an adapter.\n * Calling `diagnose` records a controlled diagnostic; it cannot publish or\n * otherwise mutate an application runtime.\n */\nexport interface AdapterContext {\n readonly policy: SourcePolicy;\n readonly limits: SourceLimits;\n diagnose(code: string, message: string): void;\n}\n\n/** Pure conversion from one raw source format into inert declarations. */\nexport interface SourceAdapter<TInput> {\n adapt(input: TInput, context: AdapterContext): AdapterResult;\n}\n\nfunction diagnostic(code: string, message: string): SourceDiagnostic {\n return Object.freeze({ code, message });\n}\n\nfunction diagnosticLimit(policy: SourcePolicy): number {\n const candidate = policy?.limits?.maxDiagnostics;\n return typeof candidate === 'number' && Number.isSafeInteger(candidate) && candidate > 0\n ? candidate\n : 1;\n}\n\nfunction frozenPolicy(policy: SourcePolicy): SourcePolicy {\n const capabilities: Record<string, readonly string[]> = Object.create(null);\n for (const [kind, values] of Object.entries(policy.allowedCapabilities)) {\n capabilities[kind] = Object.freeze([...values]);\n }\n const limits = Object.freeze({ ...policy.limits });\n return Object.freeze({\n allowedKinds: Object.freeze([...policy.allowedKinds]),\n allowedNamespaces: Object.freeze([...policy.allowedNamespaces]),\n allowedTransformOps: Object.freeze([...policy.allowedTransformOps]),\n maxTransformScope: policy.maxTransformScope,\n allowedCapabilities: Object.freeze(capabilities),\n limits,\n });\n}\n\nfunction copyDiagnostic(value: unknown): SourceDiagnostic {\n if (\n value !== null &&\n typeof value === 'object' &&\n typeof (value as { readonly code?: unknown }).code === 'string' &&\n typeof (value as { readonly message?: unknown }).message === 'string'\n ) {\n return diagnostic(\n (value as { readonly code: string }).code,\n (value as { readonly message: string }).message,\n );\n }\n return diagnostic(\n 'source.invalid-adapter-diagnostic',\n 'The source adapter returned an invalid diagnostic.',\n );\n}\n\n/**\n * Runs a pure adapter and applies the source policy again to its output before\n * it can reach a runtime. This is deliberately independent of `LayerRuntime`.\n */\nexport function adaptRawConfig<TInput>(\n input: TInput,\n adapter: SourceAdapter<TInput>,\n policy: SourcePolicy,\n): ParseResult {\n const policyValidation = validateLayerValue(null, policy);\n if (\n !policyValidation.ok &&\n policyValidation.diagnostics.some((entry) => entry.code === 'source.invalid-policy')\n ) {\n return policyValidation;\n }\n const ownedPolicy = frozenPolicy(policy);\n const diagnostics: SourceDiagnostic[] = [];\n const maxDiagnostics = diagnosticLimit(ownedPolicy);\n let limited = false;\n const add = (value: SourceDiagnostic): void => {\n if (limited) return;\n if (diagnostics.length + 1 < maxDiagnostics) {\n diagnostics.push(value);\n return;\n }\n limited = true;\n diagnostics.push(\n diagnostic('source.diagnostic-limit', 'Additional source diagnostics were omitted.'),\n );\n };\n const context: AdapterContext = Object.freeze({\n policy: ownedPolicy,\n limits: ownedPolicy.limits,\n diagnose(code: string, message: string) {\n add(copyDiagnostic({ code, message }));\n },\n });\n const result = adapter.adapt(input, context);\n if (result === null || typeof result !== 'object') {\n add(\n diagnostic('source.invalid-adapter-result', 'The source adapter returned an invalid result.'),\n );\n } else if (result.diagnostics !== undefined) {\n if (!Array.isArray(result.diagnostics)) {\n add(\n diagnostic(\n 'source.invalid-adapter-result',\n 'The source adapter returned an invalid result.',\n ),\n );\n } else {\n for (const entry of result.diagnostics) add(copyDiagnostic(entry));\n }\n }\n if (diagnostics.length > 0) {\n return { ok: false, diagnostics: Object.freeze(diagnostics) };\n }\n if (result === null || typeof result !== 'object' || result.layer === undefined) {\n return {\n ok: false,\n diagnostics: Object.freeze([\n diagnostic(\n 'source.invalid-adapter-result',\n 'The source adapter did not return a declaration layer.',\n ),\n ]),\n };\n }\n return validateLayerValue(result.layer, ownedPolicy);\n}\n\n/** Adapts the built-in JSON/YAML parse result without adding any executable data. */\nexport const parseResultAdapter: SourceAdapter<RawConfig> = Object.freeze({\n adapt(input: RawConfig) {\n return input.ok ? { layer: input.value } : { diagnostics: input.diagnostics };\n },\n});\n","import type { RuntimeSource, RuntimeSourceFailure, SourceLoadContext } from '@burojs/core';\nimport { type RawConfig, type SourceAdapter, adaptRawConfig } from './adapter.js';\nimport type { SourceDiagnostic } from './parse.js';\nimport type { SourcePolicy } from './source-policy.js';\n\nfunction adaptationFailure(diagnostics: readonly SourceDiagnostic[]): RuntimeSourceFailure {\n return Object.freeze({\n status: 'rejected',\n diagnostics: Object.freeze(\n diagnostics.map((entry) => Object.freeze({ code: entry.code, message: entry.message })),\n ),\n });\n}\n\n/**\n * Builds a normal core runtime source for inert configuration. Publication,\n * cancellation, epochs, and snapshot commits remain owned by `LayerRuntime`.\n */\nexport function createConfigRuntimeSource(\n id: string,\n fetchRaw: (context: SourceLoadContext) => Promise<RawConfig>,\n adapter: SourceAdapter<RawConfig>,\n policy: SourcePolicy,\n): RuntimeSource {\n return Object.freeze({\n id,\n async load(context: SourceLoadContext) {\n const raw = await fetchRaw(context);\n const adapted = adaptRawConfig(raw, adapter, policy);\n if (!adapted.ok) return adaptationFailure(adapted.diagnostics);\n return adapted.value;\n },\n });\n}\n"]}
|