tickmarkr 1.92.0 → 1.92.1
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/config/fleet-overlay.js +49 -20
- package/package.json +1 -1
|
@@ -88,7 +88,7 @@ function setScalarPreservingComment(doc, path, value, authoredComment) {
|
|
|
88
88
|
if (isScalar(existing))
|
|
89
89
|
existing.value = value;
|
|
90
90
|
else
|
|
91
|
-
doc
|
|
91
|
+
setAt(doc, path, doc.createNode(value));
|
|
92
92
|
if (authoredComment !== undefined) {
|
|
93
93
|
const written = doc.getIn(path, true);
|
|
94
94
|
if (isScalar(written))
|
|
@@ -112,11 +112,11 @@ function setStringSequencePreservingComments(doc, path, values) {
|
|
|
112
112
|
if (comments.length)
|
|
113
113
|
tombstone.comment = comments.join("\n");
|
|
114
114
|
}
|
|
115
|
-
doc
|
|
115
|
+
setAt(doc, path, tombstone);
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
if (!isSeq(existing)) {
|
|
119
|
-
doc
|
|
119
|
+
setAt(doc, path, doc.createNode(values));
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
122
|
const available = [...existing.items];
|
|
@@ -127,6 +127,34 @@ function setStringSequencePreservingComments(doc, path, values) {
|
|
|
127
127
|
return doc.createNode(value);
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
|
+
// OBS-533: yaml's setIn/deleteIn throw on any non-collection intermediate ("Expected YAML
|
|
131
|
+
// collection at spec. Remaining path: pin"), and a v1.1 null tombstone (`spec:` under
|
|
132
|
+
// routing.map) is exactly that scalar — deepMerge prunes it before schema validation, so the
|
|
133
|
+
// overlay loads clean and the first fleet write under the tombstoned key crashed the TUI.
|
|
134
|
+
// Total forms: a delete treats the masked subtree as absent (the operator's tombstone already
|
|
135
|
+
// denies it, and survives untouched); a set clears the scalar and rebuilds what fleet owns —
|
|
136
|
+
// the routing.allow precedent below.
|
|
137
|
+
function deleteAt(doc, path) {
|
|
138
|
+
for (let depth = 1; depth < path.length; depth++) {
|
|
139
|
+
if (!isMap(doc.getIn(path.slice(0, depth), true)))
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// deleteIn throws on an empty document — only delete keys that exist.
|
|
143
|
+
if (doc.getIn(path) !== undefined)
|
|
144
|
+
doc.deleteIn(path);
|
|
145
|
+
}
|
|
146
|
+
function setAt(doc, path, value) {
|
|
147
|
+
for (let depth = 1; depth < path.length; depth++) {
|
|
148
|
+
const node = doc.getIn(path.slice(0, depth), true);
|
|
149
|
+
if (node === undefined)
|
|
150
|
+
break;
|
|
151
|
+
if (!isMap(node)) {
|
|
152
|
+
doc.deleteIn(path.slice(0, depth));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
doc.setIn(path, value);
|
|
157
|
+
}
|
|
130
158
|
function deleteEmptyMap(doc, path) {
|
|
131
159
|
const node = doc.getIn(path, true);
|
|
132
160
|
if (isMap(node) && node.items.length === 0)
|
|
@@ -150,27 +178,26 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
150
178
|
const allowNode = doc.getIn(["routing", "allow"], true);
|
|
151
179
|
if (allowNode !== undefined && !isMap(allowNode))
|
|
152
180
|
doc.deleteIn(["routing", "allow"]);
|
|
153
|
-
// deleteIn throws on an empty document — only delete keys that exist.
|
|
154
181
|
if (form.adapters.length) {
|
|
155
182
|
setStringSequencePreservingComments(doc, ["routing", "allow", "adapters"], form.adapters);
|
|
156
183
|
}
|
|
157
|
-
else
|
|
158
|
-
doc
|
|
184
|
+
else {
|
|
185
|
+
deleteAt(doc, ["routing", "allow", "adapters"]);
|
|
159
186
|
}
|
|
160
187
|
if (form.models.length) {
|
|
161
188
|
setStringSequencePreservingComments(doc, ["routing", "allow", "models"], form.models);
|
|
162
189
|
}
|
|
163
|
-
else
|
|
164
|
-
doc
|
|
190
|
+
else {
|
|
191
|
+
deleteAt(doc, ["routing", "allow", "models"]);
|
|
165
192
|
}
|
|
166
193
|
// Whole fleet out: allow stays present but empty — fail-closed, nothing admitted.
|
|
167
194
|
if (doc.getIn(["routing", "allow"]) === undefined) {
|
|
168
|
-
doc
|
|
195
|
+
setAt(doc, ["routing", "allow"], doc.createNode({}));
|
|
169
196
|
}
|
|
170
197
|
}
|
|
171
|
-
else
|
|
198
|
+
else {
|
|
172
199
|
// Whole fleet in: no restriction to express — the allow block goes away entirely.
|
|
173
|
-
doc
|
|
200
|
+
deleteAt(doc, ["routing", "allow"]);
|
|
174
201
|
}
|
|
175
202
|
// Residuals stay in deny; covered scopes are tombstoned so a lower layer can never
|
|
176
203
|
// re-exclude behind the operator's back (workers untouched).
|
|
@@ -189,9 +216,9 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
189
216
|
const after = edited.map[shape];
|
|
190
217
|
if (JSON.stringify(before?.pin) !== JSON.stringify(after?.pin)) {
|
|
191
218
|
if (after?.pin === undefined)
|
|
192
|
-
doc
|
|
219
|
+
deleteAt(doc, ["routing", "map", shape, "pin"]);
|
|
193
220
|
else
|
|
194
|
-
doc
|
|
221
|
+
setAt(doc, ["routing", "map", shape, "pin"], doc.createNode(after.pin));
|
|
195
222
|
}
|
|
196
223
|
if (JSON.stringify(before?.pool) !== JSON.stringify(after?.pool)) {
|
|
197
224
|
const path = ["routing", "map", shape, "pool"];
|
|
@@ -200,9 +227,6 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
200
227
|
setStringSequencePreservingComments(doc, path, null);
|
|
201
228
|
}
|
|
202
229
|
else {
|
|
203
|
-
const existing = doc.getIn(path, true);
|
|
204
|
-
if (existing !== undefined && !isMap(existing))
|
|
205
|
-
doc.deleteIn(path);
|
|
206
230
|
setScalarPreservingComment(doc, [...path, "mode"], after.pool.mode);
|
|
207
231
|
// Channel order is semantic (ordered walks it; any breaks ties by it) — dedupe, never sort.
|
|
208
232
|
setStringSequencePreservingComments(doc, [...path, "channels"], [...new Set(after.pool.channels)]);
|
|
@@ -213,7 +237,7 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
213
237
|
// the pin/pool declaration owns the whole slot at merge (deepMerge drops the lower
|
|
214
238
|
// layer's pin/pool/prefer atomically) — an [] mask here would re-declare prefer BESIDE
|
|
215
239
|
// the pool in one document and fail the exclusivity refine; delete the key instead
|
|
216
|
-
doc
|
|
240
|
+
deleteAt(doc, ["routing", "map", shape, "prefer"]);
|
|
217
241
|
}
|
|
218
242
|
else {
|
|
219
243
|
// Clearing a resolved list with no replacing declaration must mask the lower layer
|
|
@@ -223,7 +247,7 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
223
247
|
}
|
|
224
248
|
if (before?.escalate !== after?.escalate) {
|
|
225
249
|
if (after?.escalate === undefined)
|
|
226
|
-
doc
|
|
250
|
+
deleteAt(doc, ["routing", "map", shape, "escalate"]);
|
|
227
251
|
else
|
|
228
252
|
setScalarPreservingComment(doc, ["routing", "map", shape, "escalate"], after.escalate);
|
|
229
253
|
}
|
|
@@ -233,7 +257,7 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
233
257
|
continue;
|
|
234
258
|
const tier = edited.floors[shape];
|
|
235
259
|
if (tier === undefined)
|
|
236
|
-
doc
|
|
260
|
+
deleteAt(doc, ["routing", "floors", shape]);
|
|
237
261
|
else
|
|
238
262
|
setScalarPreservingComment(doc, ["routing", "floors", shape], tier);
|
|
239
263
|
}
|
|
@@ -283,7 +307,7 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
283
307
|
if (JSON.stringify(before) === JSON.stringify(after))
|
|
284
308
|
continue;
|
|
285
309
|
if (after === undefined) {
|
|
286
|
-
doc
|
|
310
|
+
deleteAt(doc, [key, "prefer"]);
|
|
287
311
|
deleteEmptyMap(doc, [key]);
|
|
288
312
|
}
|
|
289
313
|
else {
|
|
@@ -291,6 +315,11 @@ export function renderFleetOverlayWrite(priorBytes, write) {
|
|
|
291
315
|
}
|
|
292
316
|
}
|
|
293
317
|
}
|
|
318
|
+
// Every mutation no-oped against an empty or comment-only overlay (contents stays null;
|
|
319
|
+
// deleteAt never creates content): return the prior bytes verbatim — stringifying a null
|
|
320
|
+
// document would write a literal `null` line into the file.
|
|
321
|
+
if (doc.contents === null)
|
|
322
|
+
return priorBytes;
|
|
294
323
|
// OBS-505: fleet's two-space note style (`tier: mid # note`) applies to INLINE comments only.
|
|
295
324
|
// The previous commentString prefixed " #" onto EVERY comment line, so block comments — the
|
|
296
325
|
// whole init scaffold at column 0, and indented operator essays — each gained a stray leading
|