@varde-flyt/vfac 0.12.0 → 0.13.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/dist/vfac.mjs +465 -22
- package/package.json +1 -1
package/dist/vfac.mjs
CHANGED
|
@@ -7928,13 +7928,33 @@ function renderOperation(operationId, data) {
|
|
|
7928
7928
|
);
|
|
7929
7929
|
}
|
|
7930
7930
|
}
|
|
7931
|
+
const product = failure["product"];
|
|
7932
|
+
const reportedSettings = [];
|
|
7933
|
+
if (Array.isArray(product)) {
|
|
7934
|
+
for (const entry of product) {
|
|
7935
|
+
const one = asRecord(entry);
|
|
7936
|
+
if (one === null) continue;
|
|
7937
|
+
const component = one["component"];
|
|
7938
|
+
const code = one["code"];
|
|
7939
|
+
if (typeof component !== "string" || typeof code !== "string") continue;
|
|
7940
|
+
if (component === "" || code === "") continue;
|
|
7941
|
+
const setting = one["setting"];
|
|
7942
|
+
if (typeof setting === "string" && setting !== "") {
|
|
7943
|
+
reportedSettings.push(setting);
|
|
7944
|
+
lines.push(` ${component} refused to start: ${code} (setting: ${setting})`);
|
|
7945
|
+
} else {
|
|
7946
|
+
lines.push(` ${component} refused to start: ${code}`);
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
}
|
|
7931
7950
|
const retryable = failure["retryable"];
|
|
7932
7951
|
if (typeof retryable === "boolean") {
|
|
7933
7952
|
const again = data["type"] === "PRODUCT_INSTANCE_UPGRADE" ? "`vfac lifecycle upgrade <pri_\u2026>`" : "`vfac lifecycle reconcile <pri_\u2026>`";
|
|
7934
7953
|
const changeIt = data["type"] === "PRODUCT_INSTANCE_UPGRADE" ? "" : ", or `vfac apply` a corrected manifest";
|
|
7935
7954
|
const cause2 = failure["cause"];
|
|
7955
|
+
const named = reportedSettings[0];
|
|
7936
7956
|
lines.push(
|
|
7937
|
-
retryable ? ` Another attempt can succeed: ${again}.` : cause2 === "unknown" ? ` The platform could not classify this, so there is nothing here to correct. Read the whole record with \`vfac get operation ${operationId} --output json\`, and quote that id if you ask for help. Repeating it unchanged fails the same way.` : ` Repeating this unchanged fails again \u2014 fix what the lines above name, then ${again}${changeIt}.`
|
|
7957
|
+
retryable ? ` Another attempt can succeed: ${again}.` : named !== void 0 ? ` Correct \`${named}\` in your manifest, then \`vfac apply\` it${data["type"] === "PRODUCT_INSTANCE_UPGRADE" ? ` and ${again}` : ""}. Repeating it unchanged fails the same way.` : cause2 === "unknown" ? ` The platform could not classify this, so there is nothing here to correct. Read the whole record with \`vfac get operation ${operationId} --output json\`, and quote that id if you ask for help. Repeating it unchanged fails the same way.` : ` Repeating this unchanged fails again \u2014 fix what the lines above name, then ${again}${changeIt}.`
|
|
7938
7958
|
);
|
|
7939
7959
|
}
|
|
7940
7960
|
}
|
|
@@ -12245,6 +12265,29 @@ var ValueConditionSchema = external_exports.object({
|
|
|
12245
12265
|
anyOf: external_exports.array(external_exports.string().min(1).max(200)).min(1).max(20),
|
|
12246
12266
|
anyRow: external_exports.boolean().optional()
|
|
12247
12267
|
}).strict();
|
|
12268
|
+
var ValueReferenceSchema = external_exports.object({
|
|
12269
|
+
/**
|
|
12270
|
+
* The setting whose VALUES form the allowed set — a canonical declaration
|
|
12271
|
+
* path, or a bare root key, which is the same string at depth 1.
|
|
12272
|
+
*/
|
|
12273
|
+
path: external_exports.string().min(1).max(400)
|
|
12274
|
+
}).strict();
|
|
12275
|
+
var RowCardinalitySchema = external_exports.object({
|
|
12276
|
+
/** A setting declared DIRECTLY on the row. */
|
|
12277
|
+
property: PropertyNameSchema,
|
|
12278
|
+
/** The answers that count toward the limit. Non-empty. */
|
|
12279
|
+
anyOf: external_exports.array(external_exports.string().min(1).max(200)).min(1).max(20),
|
|
12280
|
+
/**
|
|
12281
|
+
* How many rows may answer that way. Zero is meaningful and allowed — "no
|
|
12282
|
+
* row may, under this release" is a thing an upgrade needs to be able to
|
|
12283
|
+
* say.
|
|
12284
|
+
*/
|
|
12285
|
+
max: external_exports.number().int().min(0).max(99)
|
|
12286
|
+
}).strict();
|
|
12287
|
+
var RowRulesSchema = external_exports.object({
|
|
12288
|
+
unique: external_exports.array(PropertyNameSchema).min(1).max(MAX_CONFIGURATION_CHILDREN).optional(),
|
|
12289
|
+
atMost: external_exports.array(RowCardinalitySchema).min(1).max(10).optional()
|
|
12290
|
+
}).strict();
|
|
12248
12291
|
var TitleSchema = external_exports.string().min(2).max(80).describe("Customer-facing field label.");
|
|
12249
12292
|
var V1_LEAF_BOUNDS = {
|
|
12250
12293
|
help: 400,
|
|
@@ -12318,7 +12361,16 @@ function leafShapes(bounds) {
|
|
|
12318
12361
|
* what `requiredSecrets` reports, which is one answer with one reader.
|
|
12319
12362
|
* Opening it wider is a separate decision with its own blast radius.
|
|
12320
12363
|
*/
|
|
12321
|
-
"x-required-when": ValueConditionSchema.optional()
|
|
12364
|
+
"x-required-when": ValueConditionSchema.optional(),
|
|
12365
|
+
/**
|
|
12366
|
+
* The values this one must be chosen from — see {@link ValueReferenceSchema}.
|
|
12367
|
+
*
|
|
12368
|
+
* ON A STRING ONLY, and not on a secret: the platform never reads a
|
|
12369
|
+
* secret's value, so a membership test on one could never be evaluated.
|
|
12370
|
+
* The publish rules say so rather than leaving it to be discovered, the
|
|
12371
|
+
* same way they already do for a condition pointed at a secret.
|
|
12372
|
+
*/
|
|
12373
|
+
"x-value-in": ValueReferenceSchema.optional()
|
|
12322
12374
|
}).strict();
|
|
12323
12375
|
withJsonSchemaAnnex(string, SECRET_COUPLING_ANNEX);
|
|
12324
12376
|
const number = external_exports.object({
|
|
@@ -12329,14 +12381,23 @@ function leafShapes(bounds) {
|
|
|
12329
12381
|
/** Both bounds required — "numeric limits" in the guide is not optional. */
|
|
12330
12382
|
minimum: external_exports.number(),
|
|
12331
12383
|
maximum: external_exports.number(),
|
|
12332
|
-
default: external_exports.number().optional()
|
|
12384
|
+
default: external_exports.number().optional(),
|
|
12385
|
+
/**
|
|
12386
|
+
* WIDENED FROM SECRETS TO EVERY ROOT SETTING, which this shape's own
|
|
12387
|
+
* comment on the string leaf used to record as a known gap: "a
|
|
12388
|
+
* value-conditioned requirement for an ORDINARY setting is a real gap
|
|
12389
|
+
* too". It is the same keyword, the same evaluator and the same publish
|
|
12390
|
+
* rules; what changes is which settings may carry it.
|
|
12391
|
+
*/
|
|
12392
|
+
"x-required-when": ValueConditionSchema.optional()
|
|
12333
12393
|
}).strict();
|
|
12334
12394
|
const boolean = external_exports.object({
|
|
12335
12395
|
type: external_exports.literal("boolean"),
|
|
12336
12396
|
title: TitleSchema,
|
|
12337
12397
|
description: help.optional(),
|
|
12338
12398
|
group: ConfigurationGroupSchema,
|
|
12339
|
-
default: external_exports.boolean().optional()
|
|
12399
|
+
default: external_exports.boolean().optional(),
|
|
12400
|
+
"x-required-when": ValueConditionSchema.optional()
|
|
12340
12401
|
}).strict();
|
|
12341
12402
|
const items = external_exports.object({
|
|
12342
12403
|
type: external_exports.literal("string"),
|
|
@@ -12353,7 +12414,8 @@ function leafShapes(bounds) {
|
|
|
12353
12414
|
/** Required: an unbounded list is an unbounded write. */
|
|
12354
12415
|
maxItems: external_exports.number().int().min(1).max(100),
|
|
12355
12416
|
uniqueItems: external_exports.boolean().optional(),
|
|
12356
|
-
default: external_exports.array(external_exports.string().max(200)).max(100).optional()
|
|
12417
|
+
default: external_exports.array(external_exports.string().max(200)).max(100).optional(),
|
|
12418
|
+
"x-required-when": ValueConditionSchema.optional()
|
|
12357
12419
|
}).strict();
|
|
12358
12420
|
return { string, number, boolean, items, array };
|
|
12359
12421
|
}
|
|
@@ -12373,9 +12435,9 @@ var ConfigurationPropertySchema = external_exports.discriminatedUnion("type", [
|
|
|
12373
12435
|
var NestedStringPropertySchema = V2_LEAVES.string.omit({ "x-secret": true, writeOnly: true, "x-required-when": true }).extend({ group: ConfigurationGroupSchema.optional() });
|
|
12374
12436
|
var V2_NESTED_LEAVES = {
|
|
12375
12437
|
string: NestedStringPropertySchema,
|
|
12376
|
-
number: V2_LEAVES.number.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12377
|
-
boolean: V2_LEAVES.boolean.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12378
|
-
array: V2_LEAVES.array.extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12438
|
+
number: V2_LEAVES.number.omit({ "x-required-when": true }).extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12439
|
+
boolean: V2_LEAVES.boolean.omit({ "x-required-when": true }).extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12440
|
+
array: V2_LEAVES.array.omit({ "x-required-when": true }).extend({ group: ConfigurationGroupSchema.optional() }),
|
|
12379
12441
|
items: V2_LEAVES.items
|
|
12380
12442
|
};
|
|
12381
12443
|
function childBagShape(child) {
|
|
@@ -12419,7 +12481,23 @@ function propertyUnion(levelsBelow, leafSet) {
|
|
|
12419
12481
|
// discriminator, which is also what keeps a v1 document's
|
|
12420
12482
|
// `items: {type: 'string'}` reading exactly as it always did.
|
|
12421
12483
|
leafSet.array.extend({
|
|
12422
|
-
items: external_exports.discriminatedUnion("type", [V2_LEAVES.items, groupItems])
|
|
12484
|
+
items: external_exports.discriminatedUnion("type", [V2_LEAVES.items, groupItems]),
|
|
12485
|
+
/**
|
|
12486
|
+
* Rules over the ROWS of this list — see {@link RowRulesSchema}.
|
|
12487
|
+
*
|
|
12488
|
+
* HERE RATHER THAN ON THE LEAF SHAPE, and that placement is the whole
|
|
12489
|
+
* enforcement. `leafShapes().array` is also a v1 list and a last-level
|
|
12490
|
+
* list, both of which hold STRINGS: a rule naming a field of a row would
|
|
12491
|
+
* name nothing there, and `uniqueItems` is already the right keyword for
|
|
12492
|
+
* comparing whole scalar entries. This branch is the only one in the chain
|
|
12493
|
+
* where a list can hold groups, so declaring the keyword here makes "rows
|
|
12494
|
+
* have fields" a property of the shape rather than a rule to remember.
|
|
12495
|
+
*
|
|
12496
|
+
* The refinement still has to refuse a rule on a list of STRINGS, because
|
|
12497
|
+
* `items` is a discriminated union INSIDE this branch — the shape narrows
|
|
12498
|
+
* where a row can exist, not whether this particular list has one.
|
|
12499
|
+
*/
|
|
12500
|
+
"x-row-rules": RowRulesSchema.optional()
|
|
12423
12501
|
}),
|
|
12424
12502
|
/**
|
|
12425
12503
|
* A group of related settings.
|
|
@@ -13122,6 +13200,9 @@ function canonicalJson(value) {
|
|
|
13122
13200
|
}
|
|
13123
13201
|
|
|
13124
13202
|
// ../product-configuration/dist/configuration-tree.js
|
|
13203
|
+
function immediateContainer(node) {
|
|
13204
|
+
return node.containers[node.containers.length - 1] ?? null;
|
|
13205
|
+
}
|
|
13125
13206
|
function underList(node) {
|
|
13126
13207
|
return node.containers.some((container) => container.kind === "array");
|
|
13127
13208
|
}
|
|
@@ -13183,6 +13264,11 @@ function walkDeclarations(properties, ancestors, base, onLeaf, onContainer = ()
|
|
|
13183
13264
|
walkDeclarations(children.properties, [...ancestors, container], segments, onLeaf, onContainer);
|
|
13184
13265
|
}
|
|
13185
13266
|
}
|
|
13267
|
+
function declaredDefault(property) {
|
|
13268
|
+
if (property.type === "object")
|
|
13269
|
+
return void 0;
|
|
13270
|
+
return property.default;
|
|
13271
|
+
}
|
|
13186
13272
|
function leafAt(schema, path) {
|
|
13187
13273
|
const declaration = declarationPathOf(path);
|
|
13188
13274
|
return configurationLeaves(schema).find((leaf) => leaf.path === declaration) ?? null;
|
|
@@ -13195,6 +13281,29 @@ function declaresPath(schema, path) {
|
|
|
13195
13281
|
function isPlainObject(value) {
|
|
13196
13282
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13197
13283
|
}
|
|
13284
|
+
function expandDeclarationPath(configuration, declaration) {
|
|
13285
|
+
const out = [];
|
|
13286
|
+
const walk = (cursor, remaining, soFar) => {
|
|
13287
|
+
if (remaining.length === 0) {
|
|
13288
|
+
const path = configurationPath(...soFar);
|
|
13289
|
+
if (path !== null)
|
|
13290
|
+
out.push(path);
|
|
13291
|
+
return;
|
|
13292
|
+
}
|
|
13293
|
+
if (Array.isArray(cursor)) {
|
|
13294
|
+
cursor.forEach((element, index) => walk(element, remaining, [...soFar, index]));
|
|
13295
|
+
return;
|
|
13296
|
+
}
|
|
13297
|
+
if (!isPlainObject(cursor))
|
|
13298
|
+
return;
|
|
13299
|
+
const [head, ...rest] = remaining;
|
|
13300
|
+
if (head === void 0)
|
|
13301
|
+
return;
|
|
13302
|
+
walk(cursor[String(head)], rest, [...soFar, head]);
|
|
13303
|
+
};
|
|
13304
|
+
walk(configuration, segmentsOf(declaration), []);
|
|
13305
|
+
return out;
|
|
13306
|
+
}
|
|
13198
13307
|
function valueAt(configuration, path) {
|
|
13199
13308
|
let cursor = configuration;
|
|
13200
13309
|
for (const segment of segmentsOf(path)) {
|
|
@@ -13290,6 +13399,7 @@ function validateSubmittedConfiguration(schema, submitted, presence = {}) {
|
|
|
13290
13399
|
const secrets = {};
|
|
13291
13400
|
const configuration = validateObject({ properties: schema.properties, required: schema.required }, input, null, walk, { secrets, supplied });
|
|
13292
13401
|
drain(walk, crossFieldIssues(schema, supplied, presence, configuration));
|
|
13402
|
+
drain(walk, rowAndReferenceIssues(schema, presence, configuration));
|
|
13293
13403
|
if (walk.suppressed > 0) {
|
|
13294
13404
|
walk.issues.push({
|
|
13295
13405
|
field: "",
|
|
@@ -13533,6 +13643,106 @@ function crossFieldIssues(schema, supplied, presence, configuration = {}) {
|
|
|
13533
13643
|
}
|
|
13534
13644
|
return issues;
|
|
13535
13645
|
}
|
|
13646
|
+
function referenceOf(property) {
|
|
13647
|
+
return property?.["x-value-in"];
|
|
13648
|
+
}
|
|
13649
|
+
function rowRulesOf(property) {
|
|
13650
|
+
return property?.["x-row-rules"];
|
|
13651
|
+
}
|
|
13652
|
+
function comparableValue(value) {
|
|
13653
|
+
if (value === void 0 || value === null)
|
|
13654
|
+
return null;
|
|
13655
|
+
if (typeof value === "string")
|
|
13656
|
+
return value === "" ? null : JSON.stringify(value);
|
|
13657
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
13658
|
+
return JSON.stringify(value);
|
|
13659
|
+
return null;
|
|
13660
|
+
}
|
|
13661
|
+
function rowAndReferenceIssues(schema, presence, configuration) {
|
|
13662
|
+
const issues = [];
|
|
13663
|
+
const referenced = new Set(presence.referenced ?? []);
|
|
13664
|
+
for (const leaf of configurationLeaves(schema)) {
|
|
13665
|
+
const reference = referenceOf(leaf.property);
|
|
13666
|
+
if (reference === void 0)
|
|
13667
|
+
continue;
|
|
13668
|
+
const targetPath = parseConfigurationPath(reference.path);
|
|
13669
|
+
if (targetPath === null)
|
|
13670
|
+
continue;
|
|
13671
|
+
const allowed = new Set(valuesAt(configuration, targetPath).filter((value) => typeof value === "string"));
|
|
13672
|
+
for (const valuePath of expandDeclarationPath(configuration, leaf.path)) {
|
|
13673
|
+
if (referenced.has(valuePath))
|
|
13674
|
+
continue;
|
|
13675
|
+
const held = valueAt(configuration, valuePath);
|
|
13676
|
+
if (typeof held !== "string" || held === "")
|
|
13677
|
+
continue;
|
|
13678
|
+
if (allowed.has(held))
|
|
13679
|
+
continue;
|
|
13680
|
+
issues.push({
|
|
13681
|
+
field: valuePath,
|
|
13682
|
+
message: `This must be one of the values configured under ${labelOfPath(schema, targetPath)}. ` + (allowed.size === 0 ? "Nothing is configured there yet." : "No entry there currently holds this one.")
|
|
13683
|
+
});
|
|
13684
|
+
}
|
|
13685
|
+
}
|
|
13686
|
+
for (const container of configurationContainers(schema)) {
|
|
13687
|
+
if (container.kind !== "array")
|
|
13688
|
+
continue;
|
|
13689
|
+
const rules = rowRulesOf(container.property);
|
|
13690
|
+
if (rules === void 0)
|
|
13691
|
+
continue;
|
|
13692
|
+
for (const listPath of expandDeclarationPath(configuration, container.path)) {
|
|
13693
|
+
const rows = valueAt(configuration, listPath);
|
|
13694
|
+
if (!Array.isArray(rows))
|
|
13695
|
+
continue;
|
|
13696
|
+
const fieldOf = (index, name) => configurationPath(...pathSegments(listPath), index, name) ?? listPath;
|
|
13697
|
+
for (const name of rules.unique ?? []) {
|
|
13698
|
+
const firstAt = /* @__PURE__ */ new Map();
|
|
13699
|
+
rows.forEach((row, index) => {
|
|
13700
|
+
const held = comparableValue(isPlainObject2(row) ? row[name] : void 0);
|
|
13701
|
+
if (held === null)
|
|
13702
|
+
return;
|
|
13703
|
+
const earlier = firstAt.get(held);
|
|
13704
|
+
if (earlier === void 0) {
|
|
13705
|
+
firstAt.set(held, index);
|
|
13706
|
+
return;
|
|
13707
|
+
}
|
|
13708
|
+
issues.push({
|
|
13709
|
+
field: fieldOf(index, name),
|
|
13710
|
+
message: `${labelOfChild(container, name)} must be different in every entry; entry ${earlier + 1} already uses this one.`
|
|
13711
|
+
});
|
|
13712
|
+
});
|
|
13713
|
+
}
|
|
13714
|
+
for (const rule of rules.atMost ?? []) {
|
|
13715
|
+
let counted = 0;
|
|
13716
|
+
rows.forEach((row, index) => {
|
|
13717
|
+
const held = isPlainObject2(row) ? row[rule.property] : void 0;
|
|
13718
|
+
if (typeof held !== "string" || !rule.anyOf.includes(held))
|
|
13719
|
+
return;
|
|
13720
|
+
counted += 1;
|
|
13721
|
+
if (counted <= rule.max)
|
|
13722
|
+
return;
|
|
13723
|
+
issues.push({
|
|
13724
|
+
field: fieldOf(index, rule.property),
|
|
13725
|
+
message: rule.max === 0 ? `No entry may be set to this.` : `At most ${rule.max} ${rule.max === 1 ? "entry" : "entries"} may be set to this, and ${counted - 1} already ${counted - 1 === 1 ? "is" : "are"}.`
|
|
13726
|
+
});
|
|
13727
|
+
});
|
|
13728
|
+
}
|
|
13729
|
+
}
|
|
13730
|
+
}
|
|
13731
|
+
return issues;
|
|
13732
|
+
}
|
|
13733
|
+
function labelOfPath(schema, path) {
|
|
13734
|
+
const leaf = leafAt(schema, path);
|
|
13735
|
+
const titleOf = (node) => node?.property.title;
|
|
13736
|
+
const field = titleOf(leaf) ?? printableConfigurationPath(path);
|
|
13737
|
+
const container = leaf?.containers[0];
|
|
13738
|
+
const outer = container === void 0 ? void 0 : titleOf(container);
|
|
13739
|
+
return outer === void 0 ? `"${field}"` : `"${field}" in "${outer}"`;
|
|
13740
|
+
}
|
|
13741
|
+
function labelOfChild(container, name) {
|
|
13742
|
+
const items = container.property.items;
|
|
13743
|
+
const title = items?.properties?.[name]?.title;
|
|
13744
|
+
return title === void 0 ? `"${name}"` : `"${title}"`;
|
|
13745
|
+
}
|
|
13536
13746
|
function conditionOf(property) {
|
|
13537
13747
|
return property?.["x-required-when"];
|
|
13538
13748
|
}
|
|
@@ -13541,19 +13751,45 @@ function labelOf(schema, name) {
|
|
|
13541
13751
|
return property?.title === void 0 ? `"${name}"` : `"${property.title}"`;
|
|
13542
13752
|
}
|
|
13543
13753
|
function withoutCrossFieldRules(schema) {
|
|
13544
|
-
const
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
13549
|
-
}));
|
|
13550
|
-
return withoutCrossFieldRules({ ...schema, properties });
|
|
13551
|
-
}
|
|
13552
|
-
if (schema.dependentRequired === void 0)
|
|
13553
|
-
return schema;
|
|
13554
|
-
const { dependentRequired: _removed, ...rest } = schema;
|
|
13754
|
+
const properties = withoutPropertyRules(schema.properties);
|
|
13755
|
+
const stripped = properties === null ? schema : { ...schema, properties };
|
|
13756
|
+
if (stripped.dependentRequired === void 0)
|
|
13757
|
+
return stripped;
|
|
13758
|
+
const { dependentRequired: _removed, ...rest } = stripped;
|
|
13555
13759
|
return rest;
|
|
13556
13760
|
}
|
|
13761
|
+
var PROPERTY_RULE_KEYWORDS = ["x-required-when", "x-value-in", "x-row-rules"];
|
|
13762
|
+
function withoutPropertyRules(properties) {
|
|
13763
|
+
let out = null;
|
|
13764
|
+
const edit = (name) => {
|
|
13765
|
+
out ??= { ...properties };
|
|
13766
|
+
const copy = { ...out[name] };
|
|
13767
|
+
out[name] = copy;
|
|
13768
|
+
return copy;
|
|
13769
|
+
};
|
|
13770
|
+
for (const [name, property] of Object.entries(properties)) {
|
|
13771
|
+
if (!isPlainObject2(property))
|
|
13772
|
+
continue;
|
|
13773
|
+
for (const keyword of PROPERTY_RULE_KEYWORDS) {
|
|
13774
|
+
if (property[keyword] === void 0)
|
|
13775
|
+
continue;
|
|
13776
|
+
delete edit(name)[keyword];
|
|
13777
|
+
}
|
|
13778
|
+
const children = out?.[name] ?? property;
|
|
13779
|
+
if (isPlainObject2(children["properties"])) {
|
|
13780
|
+
const bare = withoutPropertyRules(children["properties"]);
|
|
13781
|
+
if (bare !== null)
|
|
13782
|
+
edit(name)["properties"] = bare;
|
|
13783
|
+
}
|
|
13784
|
+
const items = children["items"];
|
|
13785
|
+
if (isPlainObject2(items) && isPlainObject2(items["properties"])) {
|
|
13786
|
+
const bare = withoutPropertyRules(items["properties"]);
|
|
13787
|
+
if (bare !== null)
|
|
13788
|
+
edit(name)["items"] = { ...items, properties: bare };
|
|
13789
|
+
}
|
|
13790
|
+
}
|
|
13791
|
+
return out;
|
|
13792
|
+
}
|
|
13557
13793
|
function defaultOf(property) {
|
|
13558
13794
|
switch (property.type) {
|
|
13559
13795
|
case "string":
|
|
@@ -14760,11 +14996,19 @@ function checkProductDefinition(definition, ctx) {
|
|
|
14760
14996
|
if (condition === void 0)
|
|
14761
14997
|
continue;
|
|
14762
14998
|
const at = ["configuration", "properties", name, "x-required-when"];
|
|
14763
|
-
if (
|
|
14999
|
+
if ((definition.configuration.required ?? []).includes(name)) {
|
|
15000
|
+
ctx.addIssue({
|
|
15001
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15002
|
+
path: [...at],
|
|
15003
|
+
message: `"${name}" is already required, so "x-required-when" can only narrow a rule that is already unconditional. Drop one: \`required\` is always, \`x-required-when\` is the condition.`
|
|
15004
|
+
});
|
|
15005
|
+
continue;
|
|
15006
|
+
}
|
|
15007
|
+
if (declaredDefault(property) !== void 0) {
|
|
14764
15008
|
ctx.addIssue({
|
|
14765
15009
|
code: external_exports.ZodIssueCode.custom,
|
|
14766
15010
|
path: [...at],
|
|
14767
|
-
message: `"${name}"
|
|
15011
|
+
message: `"${name}" declares a default, so it is never absent and this condition could never make it required. Remove the default, or the condition.`
|
|
14768
15012
|
});
|
|
14769
15013
|
continue;
|
|
14770
15014
|
}
|
|
@@ -14840,6 +15084,8 @@ function checkProductDefinition(definition, ctx) {
|
|
|
14840
15084
|
});
|
|
14841
15085
|
}
|
|
14842
15086
|
}
|
|
15087
|
+
checkValueReferences(definition.configuration, ctx);
|
|
15088
|
+
checkRowRules(definition.configuration, ctx);
|
|
14843
15089
|
const provides = definition.serviceInterfaces?.provides ?? [];
|
|
14844
15090
|
const provideKeys = provides.map((provide) => provide.key);
|
|
14845
15091
|
const duplicateProvideKeys = provideKeys.filter((key, i) => provideKeys.indexOf(key) !== i);
|
|
@@ -14951,6 +15197,203 @@ function checkProductDefinition(definition, ctx) {
|
|
|
14951
15197
|
});
|
|
14952
15198
|
}
|
|
14953
15199
|
}
|
|
15200
|
+
function declarationIssuePath(node) {
|
|
15201
|
+
const out = ["configuration"];
|
|
15202
|
+
for (const container of node.containers) {
|
|
15203
|
+
out.push("properties", container.name);
|
|
15204
|
+
if (container.kind === "array")
|
|
15205
|
+
out.push("items");
|
|
15206
|
+
}
|
|
15207
|
+
out.push("properties", node.name);
|
|
15208
|
+
return out;
|
|
15209
|
+
}
|
|
15210
|
+
function directChildren(leaves, container) {
|
|
15211
|
+
return leaves.filter((leaf) => immediateContainer(leaf)?.path === container.path);
|
|
15212
|
+
}
|
|
15213
|
+
function valuesOutsideSpace(configuration, leaf, values) {
|
|
15214
|
+
const single = withoutCrossFieldRules({
|
|
15215
|
+
...configuration,
|
|
15216
|
+
properties: { [leaf.name]: leaf.property },
|
|
15217
|
+
required: [leaf.name]
|
|
15218
|
+
});
|
|
15219
|
+
return values.filter((value) => !validateSubmittedConfiguration(single, { [leaf.name]: value }).ok);
|
|
15220
|
+
}
|
|
15221
|
+
function checkValueReferences(configuration, ctx) {
|
|
15222
|
+
const leaves = configurationLeaves(configuration);
|
|
15223
|
+
for (const leaf of leaves) {
|
|
15224
|
+
const reference = leaf.property["x-value-in"];
|
|
15225
|
+
if (reference === void 0)
|
|
15226
|
+
continue;
|
|
15227
|
+
const at = [...declarationIssuePath(leaf), "x-value-in"];
|
|
15228
|
+
const here = printableConfigurationPath(leaf.path);
|
|
15229
|
+
if (isSecretProperty(leaf.property)) {
|
|
15230
|
+
ctx.addIssue({
|
|
15231
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15232
|
+
path: at,
|
|
15233
|
+
message: `"${here}" is a secret. The platform never reads a secret's value, so it could never check one against a set of values.`
|
|
15234
|
+
});
|
|
15235
|
+
continue;
|
|
15236
|
+
}
|
|
15237
|
+
if (leaf.property.enum !== void 0) {
|
|
15238
|
+
ctx.addIssue({
|
|
15239
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15240
|
+
path: at,
|
|
15241
|
+
message: `"${here}" already fixes its values with "enum". A setting takes its values from the contract or from another setting, not from both.`
|
|
15242
|
+
});
|
|
15243
|
+
continue;
|
|
15244
|
+
}
|
|
15245
|
+
if (declaredDefault(leaf.property) !== void 0) {
|
|
15246
|
+
ctx.addIssue({
|
|
15247
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15248
|
+
path: at,
|
|
15249
|
+
message: `"${here}" declares a default, which would be written into every row and then refused until the setting it points at happens to hold the same value. Remove the default.`
|
|
15250
|
+
});
|
|
15251
|
+
continue;
|
|
15252
|
+
}
|
|
15253
|
+
const parsed = parseConfigurationPath(reference.path);
|
|
15254
|
+
const target = parsed === null ? null : leafAt(configuration, parsed);
|
|
15255
|
+
if (target === null) {
|
|
15256
|
+
const isGroup = parsed !== null && declaresPath(configuration, parsed);
|
|
15257
|
+
ctx.addIssue({
|
|
15258
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15259
|
+
path: [...at, "path"],
|
|
15260
|
+
message: isGroup ? `"${reference.path}" is a group of settings, which holds no value to choose from. Name one setting inside it.` : `"${reference.path}" is not a declared customer configuration property.`
|
|
15261
|
+
});
|
|
15262
|
+
continue;
|
|
15263
|
+
}
|
|
15264
|
+
if (target.path === leaf.path) {
|
|
15265
|
+
ctx.addIssue({
|
|
15266
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15267
|
+
path: [...at, "path"],
|
|
15268
|
+
message: `"${here}" cannot take its values from itself.`
|
|
15269
|
+
});
|
|
15270
|
+
continue;
|
|
15271
|
+
}
|
|
15272
|
+
if (target.property.type !== "string") {
|
|
15273
|
+
ctx.addIssue({
|
|
15274
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15275
|
+
path: [...at, "path"],
|
|
15276
|
+
message: `"${reference.path}" is a ${target.property.type} setting; a reference compares string values.`
|
|
15277
|
+
});
|
|
15278
|
+
continue;
|
|
15279
|
+
}
|
|
15280
|
+
if (isSecretProperty(target.property)) {
|
|
15281
|
+
ctx.addIssue({
|
|
15282
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15283
|
+
path: [...at, "path"],
|
|
15284
|
+
message: `"${reference.path}" is a secret. The platform never reads a secret's value, so it could never be the set a reference is checked against.`
|
|
15285
|
+
});
|
|
15286
|
+
continue;
|
|
15287
|
+
}
|
|
15288
|
+
}
|
|
15289
|
+
}
|
|
15290
|
+
function checkRowRules(configuration, ctx) {
|
|
15291
|
+
const leaves = configurationLeaves(configuration);
|
|
15292
|
+
for (const leaf of leaves) {
|
|
15293
|
+
if (leaf.property["x-row-rules"] === void 0)
|
|
15294
|
+
continue;
|
|
15295
|
+
ctx.addIssue({
|
|
15296
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15297
|
+
path: [...declarationIssuePath(leaf), "x-row-rules"],
|
|
15298
|
+
message: `"${printableConfigurationPath(leaf.path)}" is a list of text entries, whose rows have no fields to name. Use "uniqueItems" to compare whole entries, or declare "items" as a group.`
|
|
15299
|
+
});
|
|
15300
|
+
}
|
|
15301
|
+
for (const container of configurationContainers(configuration)) {
|
|
15302
|
+
const rules = container.property["x-row-rules"];
|
|
15303
|
+
if (rules === void 0)
|
|
15304
|
+
continue;
|
|
15305
|
+
const at = [...declarationIssuePath(container), "x-row-rules"];
|
|
15306
|
+
const here = printableConfigurationPath(container.path);
|
|
15307
|
+
if (rules.unique === void 0 && rules.atMost === void 0) {
|
|
15308
|
+
ctx.addIssue({
|
|
15309
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15310
|
+
path: at,
|
|
15311
|
+
message: `"${here}" declares "x-row-rules" with no rule in it. Declare "unique", "atMost", or both.`
|
|
15312
|
+
});
|
|
15313
|
+
continue;
|
|
15314
|
+
}
|
|
15315
|
+
const children = directChildren(leaves, container);
|
|
15316
|
+
const childAt = (name) => children.find((child) => child.name === name);
|
|
15317
|
+
const maxItems = container.property.maxItems;
|
|
15318
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15319
|
+
(rules.unique ?? []).forEach((name, index) => {
|
|
15320
|
+
if (seen.has(name)) {
|
|
15321
|
+
ctx.addIssue({
|
|
15322
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15323
|
+
path: [...at, "unique", index],
|
|
15324
|
+
message: `"${name}" is named twice.`
|
|
15325
|
+
});
|
|
15326
|
+
return;
|
|
15327
|
+
}
|
|
15328
|
+
seen.add(name);
|
|
15329
|
+
const child = childAt(name);
|
|
15330
|
+
if (child === void 0) {
|
|
15331
|
+
ctx.addIssue({
|
|
15332
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15333
|
+
path: [...at, "unique", index],
|
|
15334
|
+
message: `"${name}" is not a setting declared on a row of "${here}".`
|
|
15335
|
+
});
|
|
15336
|
+
return;
|
|
15337
|
+
}
|
|
15338
|
+
if (child.property.type === "array") {
|
|
15339
|
+
ctx.addIssue({
|
|
15340
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15341
|
+
path: [...at, "unique", index],
|
|
15342
|
+
message: `"${name}" is a list, which holds no single value to compare across rows.`
|
|
15343
|
+
});
|
|
15344
|
+
}
|
|
15345
|
+
if (child.property.type === "boolean") {
|
|
15346
|
+
ctx.addIssue({
|
|
15347
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15348
|
+
path: [...at, "unique", index],
|
|
15349
|
+
message: `"${name}" is a true/false setting, so requiring it to be unique would cap "${here}" at two rows rather than make anything distinct. Use "atMost" to limit how many rows may answer one way.`
|
|
15350
|
+
});
|
|
15351
|
+
}
|
|
15352
|
+
});
|
|
15353
|
+
(rules.atMost ?? []).forEach((rule, index) => {
|
|
15354
|
+
const ruleAt = [...at, "atMost", index];
|
|
15355
|
+
const child = childAt(rule.property);
|
|
15356
|
+
if (child === void 0) {
|
|
15357
|
+
ctx.addIssue({
|
|
15358
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15359
|
+
path: [...ruleAt, "property"],
|
|
15360
|
+
message: `"${rule.property}" is not a setting declared on a row of "${here}".`
|
|
15361
|
+
});
|
|
15362
|
+
return;
|
|
15363
|
+
}
|
|
15364
|
+
if (child.property.type !== "string") {
|
|
15365
|
+
ctx.addIssue({
|
|
15366
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15367
|
+
path: [...ruleAt, "property"],
|
|
15368
|
+
message: `"${rule.property}" is a ${child.property.type} setting; a row rule compares string values.`
|
|
15369
|
+
});
|
|
15370
|
+
return;
|
|
15371
|
+
}
|
|
15372
|
+
if (new Set(rule.anyOf).size !== rule.anyOf.length) {
|
|
15373
|
+
ctx.addIssue({
|
|
15374
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15375
|
+
path: [...ruleAt, "anyOf"],
|
|
15376
|
+
message: "Repeated values in `anyOf`."
|
|
15377
|
+
});
|
|
15378
|
+
}
|
|
15379
|
+
if (maxItems !== void 0 && rule.max >= maxItems) {
|
|
15380
|
+
ctx.addIssue({
|
|
15381
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15382
|
+
path: [...ruleAt, "max"],
|
|
15383
|
+
message: `"${here}" holds at most ${maxItems} rows, so a limit of ${rule.max} could never be exceeded. Lower it, or remove the rule.`
|
|
15384
|
+
});
|
|
15385
|
+
}
|
|
15386
|
+
const outside = valuesOutsideSpace(configuration, child, rule.anyOf);
|
|
15387
|
+
if (outside.length > 0) {
|
|
15388
|
+
ctx.addIssue({
|
|
15389
|
+
code: external_exports.ZodIssueCode.custom,
|
|
15390
|
+
path: [...ruleAt, "anyOf"],
|
|
15391
|
+
message: `"${rule.property}" never accepts ${outside.map((value) => `"${value}"`).join(", ")}, so this rule could never count a row.`
|
|
15392
|
+
});
|
|
15393
|
+
}
|
|
15394
|
+
});
|
|
15395
|
+
}
|
|
15396
|
+
}
|
|
14954
15397
|
|
|
14955
15398
|
// ../product-contracts/dist/announcements.js
|
|
14956
15399
|
var ANNOUNCED_PRODUCTS = Object.freeze([
|