versionary 0.20.2 → 0.21.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/release/artifact-rules.js +82 -31
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const toml_1 = __importDefault(require("@iarna/toml"));
|
|
10
10
|
const yaml_1 = __importDefault(require("yaml"));
|
|
11
|
+
const WILDCARD = Symbol("wildcard");
|
|
11
12
|
function isRecord(value) {
|
|
12
13
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13
14
|
}
|
|
@@ -20,6 +21,11 @@ function parseFieldPath(fieldPath) {
|
|
|
20
21
|
while (index < fieldPath.length) {
|
|
21
22
|
const current = fieldPath[index];
|
|
22
23
|
if (current === ".") {
|
|
24
|
+
if (fieldPath[index + 1] === "*") {
|
|
25
|
+
tokens.push(WILDCARD);
|
|
26
|
+
index += 2;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
23
29
|
const keyMatch = fieldPath.slice(index + 1).match(/^[A-Za-z0-9_-]+/u);
|
|
24
30
|
if (!keyMatch) {
|
|
25
31
|
throw new Error(`Invalid field-path "${fieldPath}" near index ${index}.`);
|
|
@@ -30,6 +36,11 @@ function parseFieldPath(fieldPath) {
|
|
|
30
36
|
}
|
|
31
37
|
if (current === "[") {
|
|
32
38
|
const rest = fieldPath.slice(index + 1);
|
|
39
|
+
if (rest.startsWith("*]")) {
|
|
40
|
+
tokens.push(WILDCARD);
|
|
41
|
+
index += 3;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
33
44
|
const numberMatch = rest.match(/^(\d+)\]/u);
|
|
34
45
|
if (numberMatch) {
|
|
35
46
|
tokens.push(Number(numberMatch[1]));
|
|
@@ -55,49 +66,86 @@ function parseFieldPath(fieldPath) {
|
|
|
55
66
|
}
|
|
56
67
|
return tokens;
|
|
57
68
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (let index = 0; index < tokens.length - 1; index += 1) {
|
|
62
|
-
const token = tokens[index];
|
|
63
|
-
if (token === undefined) {
|
|
69
|
+
function assignLeaf(container, key, fieldPath, version) {
|
|
70
|
+
if (typeof key === "number") {
|
|
71
|
+
if (!Array.isArray(container) || key >= container.length) {
|
|
64
72
|
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
65
73
|
}
|
|
66
|
-
|
|
67
|
-
if (!Array.isArray(cursor) || token >= cursor.length) {
|
|
68
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
69
|
-
}
|
|
70
|
-
cursor = cursor[token];
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (!isRecord(cursor) || !(token in cursor)) {
|
|
74
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
75
|
-
}
|
|
76
|
-
cursor = cursor[token];
|
|
77
|
-
}
|
|
78
|
-
const leaf = tokens.at(-1);
|
|
79
|
-
if (leaf === undefined) {
|
|
80
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
81
|
-
}
|
|
82
|
-
if (typeof leaf === "number") {
|
|
83
|
-
if (!Array.isArray(cursor) || leaf >= cursor.length) {
|
|
84
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
85
|
-
}
|
|
86
|
-
const current = cursor[leaf];
|
|
74
|
+
const current = container[key];
|
|
87
75
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
88
76
|
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
89
77
|
}
|
|
90
|
-
|
|
78
|
+
container[key] = version;
|
|
91
79
|
return;
|
|
92
80
|
}
|
|
93
|
-
if (!isRecord(
|
|
81
|
+
if (!isRecord(container) || !(key in container)) {
|
|
94
82
|
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
95
83
|
}
|
|
96
|
-
const current =
|
|
84
|
+
const current = container[key];
|
|
97
85
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
98
86
|
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
99
87
|
}
|
|
100
|
-
|
|
88
|
+
container[key] = version;
|
|
89
|
+
}
|
|
90
|
+
function applyTokens(cursor, tokens, position, fieldPath, version) {
|
|
91
|
+
const token = tokens[position];
|
|
92
|
+
const isLeaf = position === tokens.length - 1;
|
|
93
|
+
if (token === WILDCARD) {
|
|
94
|
+
let matched = false;
|
|
95
|
+
if (isRecord(cursor)) {
|
|
96
|
+
for (const key of Object.keys(cursor)) {
|
|
97
|
+
if (isLeaf) {
|
|
98
|
+
assignLeaf(cursor, key, fieldPath, version);
|
|
99
|
+
matched = true;
|
|
100
|
+
}
|
|
101
|
+
else if (applyTokens(cursor[key], tokens, position + 1, fieldPath, version)) {
|
|
102
|
+
matched = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return matched;
|
|
106
|
+
}
|
|
107
|
+
if (Array.isArray(cursor)) {
|
|
108
|
+
for (let i = 0; i < cursor.length; i += 1) {
|
|
109
|
+
if (isLeaf) {
|
|
110
|
+
assignLeaf(cursor, i, fieldPath, version);
|
|
111
|
+
matched = true;
|
|
112
|
+
}
|
|
113
|
+
else if (applyTokens(cursor[i], tokens, position + 1, fieldPath, version)) {
|
|
114
|
+
matched = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return matched;
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`field-path "${fieldPath}" wildcard segment does not target an object or array.`);
|
|
120
|
+
}
|
|
121
|
+
if (typeof token === "number") {
|
|
122
|
+
if (!Array.isArray(cursor) || token >= cursor.length) {
|
|
123
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
124
|
+
}
|
|
125
|
+
if (isLeaf) {
|
|
126
|
+
assignLeaf(cursor, token, fieldPath, version);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
return applyTokens(cursor[token], tokens, position + 1, fieldPath, version);
|
|
130
|
+
}
|
|
131
|
+
if (typeof token === "string") {
|
|
132
|
+
if (!isRecord(cursor) || !(token in cursor)) {
|
|
133
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
134
|
+
}
|
|
135
|
+
if (isLeaf) {
|
|
136
|
+
assignLeaf(cursor, token, fieldPath, version);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return applyTokens(cursor[token], tokens, position + 1, fieldPath, version);
|
|
140
|
+
}
|
|
141
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
142
|
+
}
|
|
143
|
+
function setVersionAtJsonPath(document, fieldPath, version) {
|
|
144
|
+
const tokens = parseFieldPath(fieldPath);
|
|
145
|
+
const matched = applyTokens(document, tokens, 0, fieldPath, version);
|
|
146
|
+
if (!matched) {
|
|
147
|
+
throw new Error(`field-path "${fieldPath}" did not match any fields.`);
|
|
148
|
+
}
|
|
101
149
|
}
|
|
102
150
|
function resolveFieldPath(rule) {
|
|
103
151
|
const fieldPath = rule["field-path"] ?? rule.jsonpath;
|
|
@@ -232,6 +280,9 @@ function findMatchingBrace(content, openBraceIndex, endExclusive) {
|
|
|
232
280
|
}
|
|
233
281
|
function resolveNixPathTokens(fieldPath) {
|
|
234
282
|
const tokens = parseFieldPath(fieldPath);
|
|
283
|
+
if (tokens.some((token) => token === WILDCARD)) {
|
|
284
|
+
throw new Error(`Nix artifact rules do not support wildcard segments in field-path "${fieldPath}".`);
|
|
285
|
+
}
|
|
235
286
|
if (tokens.some((token) => typeof token === "number")) {
|
|
236
287
|
throw new Error(`Nix artifact rules do not support array index segments in field-path "${fieldPath}".`);
|
|
237
288
|
}
|