@wairon/cli 5.1.1-dev.91 → 5.1.1-dev.92
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/cli/index.js +384 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +256 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3725,6 +3725,7 @@ __export(src_exports, {
|
|
|
3725
3725
|
registerExporter: () => registerExporter,
|
|
3726
3726
|
registerPackRef: () => registerPackRef,
|
|
3727
3727
|
reinjectLocalGuides: () => reinjectLocalGuides,
|
|
3728
|
+
relationHealth: () => relationHealth,
|
|
3728
3729
|
removeDomain: () => removeDomain,
|
|
3729
3730
|
removeExternal: () => removeExternal,
|
|
3730
3731
|
removeMember: () => removeMember,
|
|
@@ -7727,6 +7728,12 @@ var ParentExcerptSchema = import_zod8.z.object({
|
|
|
7727
7728
|
/** sha256:… over the canonical excerpt without its commit. */
|
|
7728
7729
|
digest: import_zod8.z.string()
|
|
7729
7730
|
});
|
|
7731
|
+
function relationHealth(status) {
|
|
7732
|
+
if (status.uses.some((u) => u.state === "changed" || u.state === "removed")) return "incompatible";
|
|
7733
|
+
if (!status.reachable || status.outOfReach || status.uses.some((u) => u.state === "unavailable" || u.state === "unlocked")) return "unavailable";
|
|
7734
|
+
if (status.drifted) return "drifted";
|
|
7735
|
+
return "ok";
|
|
7736
|
+
}
|
|
7730
7737
|
var NamedOpenApiSpecSchema = import_zod8.z.object({
|
|
7731
7738
|
portalId: import_zod8.z.string(),
|
|
7732
7739
|
name: import_zod8.z.string(),
|
|
@@ -9048,12 +9055,16 @@ function memberProjectNodes() {
|
|
|
9048
9055
|
trustedLinks: [],
|
|
9049
9056
|
project: true
|
|
9050
9057
|
}));
|
|
9051
|
-
const
|
|
9052
|
-
|
|
9058
|
+
const rootExternals = family.nodes.find((n) => n.namespace === "")?.externals ?? [];
|
|
9059
|
+
const referenced = rootExternals.filter((e) => e.role === "member").map((e) => ({ id: e.alias, name: e.alias, description: "", trustedLinks: [], project: true, storage: storageBadge(e.sourceKind === "family" ? "contained" : e.sourceKind, e.directory, e.commit) }));
|
|
9060
|
+
const taken = new Set([...contained, ...referenced].map((n) => n.id));
|
|
9061
|
+
const external = rootExternals.filter((e) => e.role !== "member" && e.sourceKind !== "family" && !taken.has(e.alias)).map((e) => ({ id: e.alias, name: e.alias, description: e.project === e.alias ? "" : `project ${e.project}`, trustedLinks: [], project: true, external: true, storage: storageBadge(e.sourceKind, e.directory, e.commit) }));
|
|
9062
|
+
return [...contained, ...referenced, ...external];
|
|
9053
9063
|
}
|
|
9054
9064
|
function storageBadge(storage, directory, commit2) {
|
|
9055
9065
|
if (storage === "git") return `git ${commit2 ? commit2.slice(0, 7) : ""}`.trim();
|
|
9056
9066
|
if (storage === "hosted") return "hosted";
|
|
9067
|
+
if (storage === "unresolved") return "unresolved";
|
|
9057
9068
|
if (storage === "path") return directory ? `../${directory.split(/[\\/]/).pop()}` : "sibling";
|
|
9058
9069
|
return "contained";
|
|
9059
9070
|
}
|
|
@@ -9065,7 +9076,60 @@ function partBadges() {
|
|
|
9065
9076
|
}
|
|
9066
9077
|
return out;
|
|
9067
9078
|
}
|
|
9068
|
-
function
|
|
9079
|
+
function useLabel(use) {
|
|
9080
|
+
if (use.publicName === void 0) return use.member ?? "(the external)";
|
|
9081
|
+
return use.member === void 0 || use.member === "type" ? use.publicName : `${use.publicName}.${use.member}`;
|
|
9082
|
+
}
|
|
9083
|
+
function relationFrom(id, consumer, producer, status, comparedAt) {
|
|
9084
|
+
const changed = status.uses.filter((u) => u.state !== "unchanged");
|
|
9085
|
+
const health = relationHealth(status);
|
|
9086
|
+
return {
|
|
9087
|
+
id,
|
|
9088
|
+
consumer,
|
|
9089
|
+
producer,
|
|
9090
|
+
health,
|
|
9091
|
+
uses: changed.map((u) => ({ name: useLabel(u), state: u.state, ...u.detail !== void 0 ? { detail: u.detail } : {} })),
|
|
9092
|
+
unchanged: status.uses.length - changed.length,
|
|
9093
|
+
...status.pinnedCommit !== void 0 ? { pinnedCommit: status.pinnedCommit } : {},
|
|
9094
|
+
...status.pinnedDigest !== void 0 ? { pinnedDigest: status.pinnedDigest } : {},
|
|
9095
|
+
comparedAt,
|
|
9096
|
+
...health === "unavailable" && status.detail !== void 0 ? { detail: status.detail } : {}
|
|
9097
|
+
};
|
|
9098
|
+
}
|
|
9099
|
+
function statusFor(entry, consumer, producer) {
|
|
9100
|
+
const { alias, node } = producer;
|
|
9101
|
+
return entry.externals.find((s) => alias !== void 0 && s.alias === alias || node !== void 0 && (node.parent === consumer && s.alias === node.mountAlias || s.sourceKind === "family" && node.id !== void 0 && s.project === node.id));
|
|
9102
|
+
}
|
|
9103
|
+
function nameRelations(edges, relations, outsideIds, ownerOf4) {
|
|
9104
|
+
const family = graph();
|
|
9105
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9106
|
+
const out = /* @__PURE__ */ new Map();
|
|
9107
|
+
for (const edge of edges) {
|
|
9108
|
+
if (!edge.consumption) continue;
|
|
9109
|
+
const consumer = ownerOf4(edge.from);
|
|
9110
|
+
const node = outsideIds.has(edge.to) ? void 0 : familyNode(family, ownerOf4(edge.to)) ?? void 0;
|
|
9111
|
+
const alias = outsideIds.has(edge.to) ? edge.to : void 0;
|
|
9112
|
+
const entry = relations.find((r) => r.project === consumer);
|
|
9113
|
+
const status = entry && !entry.detail ? statusFor(entry, consumer, { alias, node }) : void 0;
|
|
9114
|
+
const producer = status?.alias ?? alias ?? (node?.parent === consumer ? node.mountAlias : void 0) ?? node?.id ?? ownerOf4(edge.to);
|
|
9115
|
+
const id = `${consumer}\u2192${producer}`;
|
|
9116
|
+
if (!out.has(id)) {
|
|
9117
|
+
out.set(id, status ? relationFrom(id, consumer, producer, status, entry.comparedAt) : {
|
|
9118
|
+
id,
|
|
9119
|
+
consumer,
|
|
9120
|
+
producer,
|
|
9121
|
+
health: "unavailable",
|
|
9122
|
+
uses: [],
|
|
9123
|
+
unchanged: 0,
|
|
9124
|
+
comparedAt: entry?.comparedAt ?? now,
|
|
9125
|
+
detail: entry?.detail ?? (entry ? `the consumer's statuses name no producer "${producer}"` : "the consumer's statuses were not read")
|
|
9126
|
+
});
|
|
9127
|
+
}
|
|
9128
|
+
edge.relation = id;
|
|
9129
|
+
}
|
|
9130
|
+
return [...out.values()];
|
|
9131
|
+
}
|
|
9132
|
+
function buildCanvasModel(issues = [], relations) {
|
|
9069
9133
|
const system = loadSystemSpec();
|
|
9070
9134
|
const subsystems = loadSubsystemSpecs();
|
|
9071
9135
|
const components = loadComponentSpecs();
|
|
@@ -9173,22 +9237,26 @@ function buildCanvasModel(issues = []) {
|
|
|
9173
9237
|
const badges = partBadges();
|
|
9174
9238
|
const componentSub = new Map(components.map((c) => [c.id, c.subsystem]));
|
|
9175
9239
|
const edges = [];
|
|
9176
|
-
const
|
|
9240
|
+
const outsideIds = new Set(projectNodes.filter((p) => p.storage !== void 0).map((p) => p.id));
|
|
9241
|
+
const owners = graph().owners;
|
|
9242
|
+
const ownerOfSpec = (id) => owners.get(id) ?? "";
|
|
9177
9243
|
for (const comp of components) {
|
|
9178
9244
|
for (const depId of comp.dependsOn) {
|
|
9179
9245
|
const alias = depId.includes("::") ? depId.split("::")[0] : "";
|
|
9180
|
-
if (
|
|
9181
|
-
edges.push({ from: comp.id, to: alias, cross: true });
|
|
9246
|
+
if (outsideIds.has(alias) && !componentIds.has(depId)) {
|
|
9247
|
+
edges.push({ from: comp.id, to: alias, cross: true, consumption: true });
|
|
9182
9248
|
continue;
|
|
9183
9249
|
}
|
|
9184
9250
|
if (!componentIds.has(depId)) continue;
|
|
9185
9251
|
edges.push({
|
|
9186
9252
|
from: comp.id,
|
|
9187
9253
|
to: depId,
|
|
9188
|
-
cross: componentSub.get(depId) !== comp.subsystem
|
|
9254
|
+
cross: componentSub.get(depId) !== comp.subsystem,
|
|
9255
|
+
...ownerOfSpec(depId) !== ownerOfSpec(comp.id) ? { consumption: true } : {}
|
|
9189
9256
|
});
|
|
9190
9257
|
}
|
|
9191
9258
|
}
|
|
9259
|
+
const canvasRelations = relations === void 0 ? void 0 : nameRelations(edges, relations, outsideIds, ownerOfSpec);
|
|
9192
9260
|
const typeSpecs = loadTypeSpecs();
|
|
9193
9261
|
const usedByFor = (t) => {
|
|
9194
9262
|
const qualified = t.subsystem && !t.id.startsWith(`${t.subsystem}::`) ? `${t.subsystem}::${t.id}` : t.id;
|
|
@@ -9310,6 +9378,7 @@ function buildCanvasModel(issues = []) {
|
|
|
9310
9378
|
],
|
|
9311
9379
|
components: modelComponents,
|
|
9312
9380
|
edges,
|
|
9381
|
+
...canvasRelations !== void 0 ? { relations: canvasRelations } : {},
|
|
9313
9382
|
types: modelTypes,
|
|
9314
9383
|
typeEdges,
|
|
9315
9384
|
dataEdges,
|
|
@@ -9483,6 +9552,7 @@ body[data-theme="light"] .selectControl { color-scheme:light; }
|
|
|
9483
9552
|
#cy { position:absolute; inset:0; }
|
|
9484
9553
|
.legend { position:absolute; left:12px; bottom:12px; background:var(--chrome); border:1px solid var(--chrome-border); border-radius:10px; padding:8px 12px; font-size:11px; color:var(--dim); z-index:5; pointer-events:none; }
|
|
9485
9554
|
.legend .sw { display:inline-block; width:10px; height:10px; border-radius:3px; margin-right:4px; vertical-align:-1px; border:1.5px solid; }
|
|
9555
|
+
.reltip { position:absolute; display:none; background:var(--chrome); border:1px solid var(--chrome-border); border-radius:8px; padding:6px 10px; font-size:11px; color:var(--dim); white-space:pre; z-index:6; pointer-events:none; max-width:520px; overflow:hidden; }
|
|
9486
9556
|
/* Stage overlays clear the floating header (52px + 10px top + 10px gap). The
|
|
9487
9557
|
header hides in presentation mode, where they return to the top edge. */
|
|
9488
9558
|
.viewhint { position:absolute; top:72px; left:12px; color:var(--dim); font-size:11px; background:var(--chrome); border:1px solid var(--chrome-border); border-radius:9px; padding:5px 10px; z-index:5; pointer-events:none; }
|
|
@@ -9668,6 +9738,7 @@ body.presentation #exitPresent, body.presentation #presentDetails { display:bloc
|
|
|
9668
9738
|
<div class="viewhint" id="viewHint"></div>
|
|
9669
9739
|
<div id="typesWarn"></div>
|
|
9670
9740
|
<div class="legend" id="legend"></div>
|
|
9741
|
+
<div class="reltip" id="relTip"></div>
|
|
9671
9742
|
</div>
|
|
9672
9743
|
<div id="panelResizer" title="Drag to resize details sidebar"></div>
|
|
9673
9744
|
<div id="panel"></div>
|
|
@@ -9995,6 +10066,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
9995
10066
|
retired: { fill: '#ebe8e4', stroke: '#857b73', text: '#35302b' },
|
|
9996
10067
|
},
|
|
9997
10068
|
issue: '#b3261e', selGlow: '#3465b4', bgLabel: '#f2f5f8', png: '#f2f5f8',
|
|
10069
|
+
relOk: '#2e7d4f', relDrift: '#8a6116', relBad: '#b3261e', relUnknown: '#5f6b78',
|
|
9998
10070
|
},
|
|
9999
10071
|
syw: {
|
|
10000
10072
|
pageEdge: '#7c8ca3', edgeText: '#aebdd2', cross: '#ff6b81', ink: '#eef2f8',
|
|
@@ -10016,6 +10088,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
10016
10088
|
retired: { fill: '#24211f', stroke: '#a8a29e', text: '#e7e5e4' },
|
|
10017
10089
|
},
|
|
10018
10090
|
issue: '#ff6b81', selGlow: '#22ddff', bgLabel: '#0a0a0f', png: '#0a0a0f',
|
|
10091
|
+
relOk: '#34d399', relDrift: '#f59e0b', relBad: '#ff6b81', relUnknown: '#93a1b8',
|
|
10019
10092
|
},
|
|
10020
10093
|
};
|
|
10021
10094
|
|
|
@@ -10078,6 +10151,15 @@ var MODEL = __MODEL_JSON__;
|
|
|
10078
10151
|
{ selector: 'edge.bundle', style: { width: 4.5, opacity: 0.7 } },
|
|
10079
10152
|
{ selector: 'edge.toghost', style: { 'line-style': 'dashed', opacity: 0.75 } },
|
|
10080
10153
|
{ selector: 'edge.inneredge', style: { width: 1.1, 'arrow-scale': 0.6, opacity: 0.8 } },
|
|
10154
|
+
// Relation health on consumption edges: the health colour replaces the
|
|
10155
|
+
// boundary-hop colour, and unavailable is dotted as well as grey, so the
|
|
10156
|
+
// state never rests on colour alone (the glyph is the edge's label).
|
|
10157
|
+
{ selector: 'edge.rel-unchecked', style: { 'line-color': t.pageEdge, 'target-arrow-color': t.pageEdge } },
|
|
10158
|
+
{ selector: 'edge.rel-ok', style: { 'line-color': t.relOk, 'target-arrow-color': t.relOk } },
|
|
10159
|
+
{ selector: 'edge.rel-drifted', style: { 'line-color': t.relDrift, 'target-arrow-color': t.relDrift } },
|
|
10160
|
+
{ selector: 'edge.rel-incompatible', style: { 'line-color': t.relBad, 'target-arrow-color': t.relBad } },
|
|
10161
|
+
{ selector: 'edge.rel-unavailable', style: { 'line-color': t.relUnknown, 'target-arrow-color': t.relUnknown, 'line-style': 'dotted' } },
|
|
10162
|
+
{ selector: '.extProject', style: { 'border-style': 'dashed' } },
|
|
10081
10163
|
{ selector: 'edge.stubHover', style: { 'line-color': t.selGlow, 'target-arrow-color': t.selGlow, width: 2.6, opacity: 1, 'z-compound-depth': 'top' } },
|
|
10082
10164
|
{ selector: '.dimmed', style: { opacity: 0.13 } },
|
|
10083
10165
|
{ selector: '.hasIssue', style: { 'border-color': t.issue, 'border-style': 'dashed', 'border-width': 3 } },
|
|
@@ -10114,6 +10196,83 @@ var MODEL = __MODEL_JSON__;
|
|
|
10114
10196
|
];
|
|
10115
10197
|
}
|
|
10116
10198
|
|
|
10199
|
+
// ---- relation health (consumption edges) ----------------------------------
|
|
10200
|
+
// The model carries relations only when health was computed; without them a
|
|
10201
|
+
// consumption edge is drawn neutral and the legend says it was not checked \u2014
|
|
10202
|
+
// never green for something nobody compared.
|
|
10203
|
+
var HAS_RELATIONS = Array.isArray(MODEL.relations);
|
|
10204
|
+
var REL_BY_ID = {};
|
|
10205
|
+
(MODEL.relations || []).forEach(function (r) { REL_BY_ID[r.id] = r; });
|
|
10206
|
+
var HEALTH_RANK = { ok: 1, drifted: 2, unavailable: 3, incompatible: 4 };
|
|
10207
|
+
var HEALTH_GLYPH = { ok: '\\u2713', drifted: '\\u0394', incompatible: '\\u2715', unavailable: '?' };
|
|
10208
|
+
var HAS_CONSUMPTION = MODEL.edges.some(function (e) { return !!e.consumption; });
|
|
10209
|
+
function edgeHealth(edge) {
|
|
10210
|
+
var r = edge.relation ? REL_BY_ID[edge.relation] : null;
|
|
10211
|
+
return r ? r.health : (HAS_RELATIONS ? 'unavailable' : null);
|
|
10212
|
+
}
|
|
10213
|
+
// Where edges fold into one, the worst health wins.
|
|
10214
|
+
function worseHealth(a, b) {
|
|
10215
|
+
if (!a) return b;
|
|
10216
|
+
if (!b) return a;
|
|
10217
|
+
return HEALTH_RANK[b] > HEALTH_RANK[a] ? b : a;
|
|
10218
|
+
}
|
|
10219
|
+
function relationsComparedAt() {
|
|
10220
|
+
var at = null;
|
|
10221
|
+
(MODEL.relations || []).forEach(function (r) { if (!at || r.comparedAt < at) at = r.comparedAt; });
|
|
10222
|
+
return at;
|
|
10223
|
+
}
|
|
10224
|
+
function shortPin(r) {
|
|
10225
|
+
if (r.pinnedCommit) return r.pinnedCommit.slice(0, 7);
|
|
10226
|
+
return r.pinnedDigest ? r.pinnedDigest.replace(/^[a-z0-9-]+:/, '').slice(0, 12) : '';
|
|
10227
|
+
}
|
|
10228
|
+
function relationName(r) { return (r.consumer || 'this project') + ' \\u2192 ' + r.producer; }
|
|
10229
|
+
function relationText(r) {
|
|
10230
|
+
var lines = [relationName(r) + ': ' + HEALTH_GLYPH[r.health] + ' ' + r.health];
|
|
10231
|
+
r.uses.forEach(function (u) { lines.push(' ' + u.name + ' \\u2014 ' + u.state + (u.detail ? ': ' + u.detail : '')); });
|
|
10232
|
+
if (r.unchanged) lines.push(' ' + r.unchanged + ' use' + (r.unchanged === 1 ? '' : 's') + ' unchanged');
|
|
10233
|
+
if (r.detail) lines.push(' ' + r.detail);
|
|
10234
|
+
var pin = shortPin(r);
|
|
10235
|
+
lines.push((pin ? 'pinned ' + pin + ' \\u00B7 ' : '') + 'compared ' + r.comparedAt);
|
|
10236
|
+
return lines.join('\\n');
|
|
10237
|
+
}
|
|
10238
|
+
function relationHtml(r) {
|
|
10239
|
+
var pin = shortPin(r);
|
|
10240
|
+
return '<div class="method"><div class="mname">' + esc(relationName(r)) + '<span class="grow"></span><span class="chip">' + HEALTH_GLYPH[r.health] + ' ' + esc(r.health) + '</span></div>'
|
|
10241
|
+
+ r.uses.map(function (u) { return '<div class="mdesc">' + esc(u.name) + ' \\u2014 ' + esc(u.state) + (u.detail ? ': ' + esc(u.detail) : '') + '</div>'; }).join('')
|
|
10242
|
+
+ (r.unchanged ? '<div class="mdesc">' + r.unchanged + ' use' + (r.unchanged === 1 ? '' : 's') + ' unchanged</div>' : '')
|
|
10243
|
+
+ (r.detail ? '<div class="mdesc">' + esc(r.detail) + '</div>' : '')
|
|
10244
|
+
+ '<div class="mdesc">' + (pin ? 'pinned ' + esc(pin) + ' \\u00B7 ' : '') + 'compared ' + esc(r.comparedAt) + '</div></div>';
|
|
10245
|
+
}
|
|
10246
|
+
// The relations whose consumption edges start or land inside a node.
|
|
10247
|
+
function relationsTouching(sid) {
|
|
10248
|
+
var seen = {}, out = [];
|
|
10249
|
+
var inside = function (x) {
|
|
10250
|
+
var c = compById[x];
|
|
10251
|
+
return x === sid || x.indexOf(sid + '::') === 0 || !!(c && (c.subsystem === sid || c.subsystem.indexOf(sid + '::') === 0));
|
|
10252
|
+
};
|
|
10253
|
+
MODEL.edges.forEach(function (e) {
|
|
10254
|
+
if (!e.relation || seen[e.relation] || !(inside(e.to) || inside(e.from))) return;
|
|
10255
|
+
seen[e.relation] = true;
|
|
10256
|
+
if (REL_BY_ID[e.relation]) out.push(REL_BY_ID[e.relation]);
|
|
10257
|
+
});
|
|
10258
|
+
return out;
|
|
10259
|
+
}
|
|
10260
|
+
// The one legend row, only when the model has a consumption edge.
|
|
10261
|
+
function relationLegend(t) {
|
|
10262
|
+
if (!HAS_CONSUMPTION) return '';
|
|
10263
|
+
if (!HAS_RELATIONS) return '<br>relations: <span style="color:' + t.pageEdge + '">health not checked</span>';
|
|
10264
|
+
var at = relationsComparedAt();
|
|
10265
|
+
return '<br>relations: <span style="color:' + t.relOk + '">\\u2713 ok</span> <span style="color:' + t.relDrift + '">\\u0394 drifted</span> '
|
|
10266
|
+
+ '<span style="color:' + t.relBad + '">\\u2715 incompatible</span> <span style="color:' + t.relUnknown + '">? unavailable (dotted)</span>'
|
|
10267
|
+
+ (at ? ' \\u00B7 as of ' + esc(at) : '');
|
|
10268
|
+
}
|
|
10269
|
+
// A project's own page, only through the host's open-project hook (the web
|
|
10270
|
+
// app): never in a standalone file or on a shared page, which have none.
|
|
10271
|
+
function openProjectButton(s) {
|
|
10272
|
+
if (!s.recordId || typeof opts === 'undefined' || !opts || typeof opts.onOpenProject !== 'function') return '';
|
|
10273
|
+
return '<div class="openbtn"><button class="tbtn" data-openproject-id="' + esc(s.recordId) + '">Open project \\u2197</button></div>';
|
|
10274
|
+
}
|
|
10275
|
+
|
|
10117
10276
|
function renderLegend() {
|
|
10118
10277
|
var t = THEMES[state.theme];
|
|
10119
10278
|
var sw = function (c) { return '<span class="sw" style="background:' + c.fill + ';border-color:' + c.stroke + '"></span>'; };
|
|
@@ -10127,7 +10286,8 @@ var MODEL = __MODEL_JSON__;
|
|
|
10127
10286
|
sw(t.proxyIn) + '\\u21E0 in-port ' + sw(t.proxyOut) + '\\u21E2 out-port \u2014 bold border = published \xB7 ' +
|
|
10128
10287
|
'<span style="color:' + t.cross + '">red</span> = boundary hop \xB7 double-click = open<br>' +
|
|
10129
10288
|
'on select: <span style="color:' + t.selGlow + '">\\u2192 depends on</span> <span style="color:' + t.warn + '">\\u2190 used by</span>' +
|
|
10130
|
-
(state.dataCoupling ? ' \xB7 <span style="color:' + t.typeV.stroke + '">- - \\u25B8 uses models</span>' : '')
|
|
10289
|
+
(state.dataCoupling ? ' \xB7 <span style="color:' + t.typeV.stroke + '">- - \\u25B8 uses models</span>' : '') +
|
|
10290
|
+
relationLegend(t);
|
|
10131
10291
|
}
|
|
10132
10292
|
|
|
10133
10293
|
// ---- view layout ---------------------------------------------------------------
|
|
@@ -10594,6 +10754,14 @@ var MODEL = __MODEL_JSON__;
|
|
|
10594
10754
|
if (!agg[key]) agg[key] = { src: src, tgt: tgt, n: 0, cross: false, ghost: ghost };
|
|
10595
10755
|
agg[key].n++;
|
|
10596
10756
|
if (edge.cross) agg[key].cross = true;
|
|
10757
|
+
if (edge.consumption) {
|
|
10758
|
+
agg[key].consumption = true;
|
|
10759
|
+
agg[key].health = worseHealth(agg[key].health, edgeHealth(edge));
|
|
10760
|
+
if (edge.relation) {
|
|
10761
|
+
var rels = agg[key].rels || (agg[key].rels = []);
|
|
10762
|
+
if (rels.indexOf(edge.relation) < 0) rels.push(edge.relation);
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
10597
10765
|
});
|
|
10598
10766
|
return { agg: agg, ghosts: ghosts };
|
|
10599
10767
|
}
|
|
@@ -11154,7 +11322,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
11154
11322
|
var classes, label;
|
|
11155
11323
|
var isPub = e.kind === 'component' && compById[e.id] && compById[e.id].public;
|
|
11156
11324
|
if (e.kind === 'subsystem') {
|
|
11157
|
-
classes = 'subsysBox';
|
|
11325
|
+
classes = 'subsysBox' + (subById[e.id] && subById[e.id].external ? ' extProject' : '');
|
|
11158
11326
|
label = nameOf(e) + (e.hasKids && !inner ? '\\n\\u25B8 open' : '');
|
|
11159
11327
|
} else {
|
|
11160
11328
|
var c = compById[e.id];
|
|
@@ -11362,9 +11530,13 @@ var MODEL = __MODEL_JSON__;
|
|
|
11362
11530
|
var bundle = e.n > 1;
|
|
11363
11531
|
var dim = state.query && (dimmedAnchors[e.src] || dimmedAnchors[e.tgt]);
|
|
11364
11532
|
var route = routeData(e.src, e.tgt, key);
|
|
11533
|
+
// A consumption edge carries its relation's health: the glyph at its middle,
|
|
11534
|
+
// its colour (and line, dotted when unavailable) by class.
|
|
11535
|
+
var glyph = e.health ? HEALTH_GLYPH[e.health] : '';
|
|
11536
|
+
var relCls = e.consumption ? 'rel rel-' + (e.health || 'unchecked') + ' ' : '';
|
|
11365
11537
|
eles.push({
|
|
11366
|
-
data: { id: 'e' + (i++), source: e.src, target: e.tgt, lbl: bundle ? e.n + ' links' : '', cpDist: route.cpDist, cpWeight: route.cpWeight, taxiTurn: route.taxiTurn },
|
|
11367
|
-
classes: 'routed ' + (e.cross ? 'cross ' : '') + (bundle ? 'bundle ' : '') + (e.ghost ? 'toghost ' : '') + (dim ? 'dimmed' : ''),
|
|
11538
|
+
data: { id: 'e' + (i++), source: e.src, target: e.tgt, lbl: (bundle ? e.n + ' links' : '') + (glyph ? (bundle ? ' ' : '') + glyph : ''), rels: (e.rels || []).join('|'), cpDist: route.cpDist, cpWeight: route.cpWeight, taxiTurn: route.taxiTurn },
|
|
11539
|
+
classes: 'routed ' + (e.cross ? 'cross ' : '') + (bundle ? 'bundle ' : '') + (e.ghost ? 'toghost ' : '') + relCls + (dim ? 'dimmed' : ''),
|
|
11368
11540
|
});
|
|
11369
11541
|
});
|
|
11370
11542
|
|
|
@@ -11864,6 +12036,27 @@ var MODEL = __MODEL_JSON__;
|
|
|
11864
12036
|
cy.on('mouseover', 'node', function (ev) { setHover(ev.target); });
|
|
11865
12037
|
cy.on('mouseout', 'node', function (ev) { if (hoveredNode && hoveredNode.id() === ev.target.id()) setHover(null); });
|
|
11866
12038
|
|
|
12039
|
+
// Relation health: hovering a consumption edge shows its relation(s) \u2014 which
|
|
12040
|
+
// uses changed or were removed, why one could not be compared, the pin and
|
|
12041
|
+
// when it was compared; tapping it shows the same in the details panel.
|
|
12042
|
+
function relationsOfEdge(edge) {
|
|
12043
|
+
return (edge.data('rels') || '').split('|').filter(Boolean).map(function (rid) { return REL_BY_ID[rid]; }).filter(Boolean);
|
|
12044
|
+
}
|
|
12045
|
+
cy.on('mouseover', 'edge.rel', function (ev) {
|
|
12046
|
+
var tip = document.getElementById('relTip');
|
|
12047
|
+
var rels = relationsOfEdge(ev.target);
|
|
12048
|
+
tip.textContent = rels.length ? rels.map(relationText).join('\\n\\n') : 'relation health not checked';
|
|
12049
|
+
var at = ev.renderedPosition || { x: 0, y: 0 };
|
|
12050
|
+
tip.style.left = (at.x + 12) + 'px';
|
|
12051
|
+
tip.style.top = (at.y + 12) + 'px';
|
|
12052
|
+
tip.style.display = 'block';
|
|
12053
|
+
});
|
|
12054
|
+
cy.on('mouseout', 'edge.rel', function () { document.getElementById('relTip').style.display = 'none'; });
|
|
12055
|
+
cy.on('tap', 'edge.rel', function (ev) {
|
|
12056
|
+
var ids = ev.target.data('rels') || '';
|
|
12057
|
+
if (ids) select('relation', ids, false);
|
|
12058
|
+
});
|
|
12059
|
+
|
|
11867
12060
|
cy.on('tap', 'node', function (ev) {
|
|
11868
12061
|
var t = idOf(ev.target);
|
|
11869
12062
|
if (t.group) return;
|
|
@@ -11921,7 +12114,15 @@ var MODEL = __MODEL_JSON__;
|
|
|
11921
12114
|
var hasKids = t.kind === 'subsystem'
|
|
11922
12115
|
? (childSubsOf(t.id).length + childCompsOf(t.id).length) > 0
|
|
11923
12116
|
: memberCompsOf(t.id).length > 0;
|
|
11924
|
-
if (hasKids) navigateTo(t.kind, t.id);
|
|
12117
|
+
if (hasKids) { navigateTo(t.kind, t.id); return; }
|
|
12118
|
+
// A project node with nothing to drill into (a referenced or external one):
|
|
12119
|
+
// its own page through the host's open-project hook when it carries a
|
|
12120
|
+
// record id, else its details panel \u2014 its storage and its relations.
|
|
12121
|
+
var ps = t.kind === 'subsystem' ? subById[t.id] : null;
|
|
12122
|
+
if (ps && ps.project) {
|
|
12123
|
+
if (ps.recordId && typeof opts !== 'undefined' && opts && typeof opts.onOpenProject === 'function') { opts.onOpenProject(ps.recordId); return; }
|
|
12124
|
+
select('subsystem', t.id, false);
|
|
12125
|
+
}
|
|
11925
12126
|
});
|
|
11926
12127
|
cy.on('dragfree', 'node', function () { harvestPositions(); });
|
|
11927
12128
|
|
|
@@ -13158,7 +13359,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
13158
13359
|
cy.nodes().removeClass('sel');
|
|
13159
13360
|
cy.edges().removeClass('fieldhl');
|
|
13160
13361
|
if (id) {
|
|
13161
|
-
var node = nodeForRef(kind, id);
|
|
13362
|
+
var node = kind === 'relation' ? cy.collection() : nodeForRef(kind, id);
|
|
13162
13363
|
if (node.length) {
|
|
13163
13364
|
node.addClass('sel');
|
|
13164
13365
|
applyFocus(node);
|
|
@@ -13328,6 +13529,10 @@ var MODEL = __MODEL_JSON__;
|
|
|
13328
13529
|
via.map(function (v) { return chip(v.label, v.kind, v.id); }).join(''), true);
|
|
13329
13530
|
}
|
|
13330
13531
|
}
|
|
13532
|
+
} else if (focusKind === 'relation') {
|
|
13533
|
+
var rl = String(focusId).split('|').map(function (rid) { return REL_BY_ID[rid]; }).filter(Boolean);
|
|
13534
|
+
head = '<h2>' + esc(rl.length === 1 ? relationName(rl[0]) : rl.length + ' relations') + '</h2>' + staticChip('relation');
|
|
13535
|
+
body += rl.map(relationHtml).join('');
|
|
13331
13536
|
} else if (focusKind === 'type') {
|
|
13332
13537
|
var ty = null;
|
|
13333
13538
|
MODEL.types.forEach(function (t2) { if (t2.id === focusId) ty = t2; });
|
|
@@ -13411,8 +13616,14 @@ var MODEL = __MODEL_JSON__;
|
|
|
13411
13616
|
+ (scopeFocus ? staticChip('current view') : '')
|
|
13412
13617
|
+ (scopeFocus ? '' : openViewButton('subsystem', s.id, subKids > 0))
|
|
13413
13618
|
+ openApiButton(subsystemExposesApi(s.id), '')
|
|
13414
|
-
+ openSpecButton('subsystem', s.id)
|
|
13619
|
+
+ openSpecButton('subsystem', s.id)
|
|
13620
|
+
+ (s.project ? staticChip(s.external ? 'external project' : 'project') : '')
|
|
13621
|
+
+ (s.storage ? staticChip(s.storage) : '')
|
|
13622
|
+
+ openProjectButton(s);
|
|
13415
13623
|
body += '<p class="desc">' + esc(s.description) + '</p>';
|
|
13624
|
+
var nodeRels = relationsTouching(s.id);
|
|
13625
|
+
if (nodeRels.length) body += section('Relations', nodeRels.length, nodeRels.map(relationHtml).join(''), true);
|
|
13626
|
+
else if (s.project && HAS_CONSUMPTION && !HAS_RELATIONS) body += section('Relations', null, '<span class="desc">relation health was not checked</span>', true);
|
|
13416
13627
|
if (s.trustedLinks.length) {
|
|
13417
13628
|
body += section('Trusted links (fast lanes)', s.trustedLinks.length, s.trustedLinks.map(function (t2) {
|
|
13418
13629
|
return '<div class="method">' + chip(t2.subsystem, 'subsystem', t2.subsystem) + '<div class="mdesc">' + esc(t2.reason) + '</div></div>';
|
|
@@ -13479,6 +13690,14 @@ var MODEL = __MODEL_JSON__;
|
|
|
13479
13690
|
});
|
|
13480
13691
|
})(ospecs[si]);
|
|
13481
13692
|
}
|
|
13693
|
+
var oprojs = panel.querySelectorAll('[data-openproject-id]');
|
|
13694
|
+
for (var opi = 0; opi < oprojs.length; opi++) {
|
|
13695
|
+
(function (b) {
|
|
13696
|
+
b.addEventListener('click', function () {
|
|
13697
|
+
if (typeof opts !== 'undefined' && opts && typeof opts.onOpenProject === 'function') opts.onOpenProject(b.getAttribute('data-openproject-id'));
|
|
13698
|
+
});
|
|
13699
|
+
})(oprojs[opi]);
|
|
13700
|
+
}
|
|
13482
13701
|
var flows = panel.querySelectorAll('[data-flow-comp]');
|
|
13483
13702
|
for (var j = 0; j < flows.length; j++) {
|
|
13484
13703
|
(function (b) {
|
|
@@ -14074,7 +14293,14 @@ function externalStatus(binding, lock) {
|
|
|
14074
14293
|
const { external } = binding;
|
|
14075
14294
|
const entry = lock?.externals[external.alias];
|
|
14076
14295
|
const pinned = entry !== void 0 && externalsRepository.readSnapshot(external.alias) !== null;
|
|
14077
|
-
const base = {
|
|
14296
|
+
const base = {
|
|
14297
|
+
alias: external.alias,
|
|
14298
|
+
project: external.project,
|
|
14299
|
+
sourceKind: external.sourceKind,
|
|
14300
|
+
pinned,
|
|
14301
|
+
...entry !== void 0 ? { pinnedDigest: entry.digest } : {},
|
|
14302
|
+
...entry?.commit !== void 0 ? { pinnedCommit: entry.commit } : {}
|
|
14303
|
+
};
|
|
14078
14304
|
const unreadable = external.sourceKind === "unresolved" ? hostedOnly(external) ? external.problem : `the external does not resolve: ${external.problem}` : producerUnreadable(external);
|
|
14079
14305
|
let live = null;
|
|
14080
14306
|
let reason = unreadable;
|
|
@@ -14314,7 +14540,8 @@ function reachCeiling(root, family) {
|
|
|
14314
14540
|
}
|
|
14315
14541
|
function within2(dir, ceiling, fn) {
|
|
14316
14542
|
if (ceiling === null) return runWithProjectRoot(dir, fn);
|
|
14317
|
-
|
|
14543
|
+
const lookup2 = getHostedLookup();
|
|
14544
|
+
return runWithProjectBinding(dir, { topRoot: ceiling.topRoot, parentReach: true, narrowed: ceiling.narrowed, ...lookup2 ? { hostedLookup: lookup2 } : {} }, fn);
|
|
14318
14545
|
}
|
|
14319
14546
|
function depthOf(family, node) {
|
|
14320
14547
|
let depth = 0;
|
|
@@ -14365,7 +14592,8 @@ function referencedOf(nodes) {
|
|
|
14365
14592
|
return out;
|
|
14366
14593
|
}
|
|
14367
14594
|
function atReferenced(ref, fn) {
|
|
14368
|
-
|
|
14595
|
+
const lookup2 = getHostedLookup();
|
|
14596
|
+
return runWithProjectBinding(ref.directory, { topRoot: ref.directory, parentReach: true, narrowed: true, ...lookup2 ? { hostedLookup: lookup2 } : {} }, fn);
|
|
14369
14597
|
}
|
|
14370
14598
|
function narrowed(family, selected) {
|
|
14371
14599
|
const keys = /* @__PURE__ */ new Set(["", ...selected.map((s) => s.node.namespace)]);
|
|
@@ -14853,7 +15081,7 @@ function defaultTargetConfig(type) {
|
|
|
14853
15081
|
enabled: true
|
|
14854
15082
|
};
|
|
14855
15083
|
}
|
|
14856
|
-
var WAIRON_VERSION = "5.1.1-dev.
|
|
15084
|
+
var WAIRON_VERSION = "5.1.1-dev.92";
|
|
14857
15085
|
var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
14858
15086
|
var ARCHITECT_AGENT_ID = "agent-architect";
|
|
14859
15087
|
var ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -25349,10 +25577,11 @@ function familyApprovals(depth) {
|
|
|
25349
25577
|
}
|
|
25350
25578
|
|
|
25351
25579
|
// src/core/diagram.ts
|
|
25352
|
-
function renderDiagram(format) {
|
|
25580
|
+
function renderDiagram(format, relations) {
|
|
25353
25581
|
switch (format) {
|
|
25582
|
+
// Only the canvas carries relation health; the other formats ignore it.
|
|
25354
25583
|
case "canvas":
|
|
25355
|
-
return renderCanvasHtml(buildCanvasModel(diagramIssues()));
|
|
25584
|
+
return renderCanvasHtml(buildCanvasModel(diagramIssues(), relations));
|
|
25356
25585
|
case "mermaid":
|
|
25357
25586
|
return generateComponentDiagram();
|
|
25358
25587
|
case "drawio":
|
|
@@ -25363,8 +25592,8 @@ function renderDiagram(format) {
|
|
|
25363
25592
|
throw new Error(`Unsupported diagram format "${format}" (canvas | mermaid | drawio | excalidraw).`);
|
|
25364
25593
|
}
|
|
25365
25594
|
}
|
|
25366
|
-
function buildCanvasDataModel() {
|
|
25367
|
-
return buildCanvasModel(diagramIssues());
|
|
25595
|
+
function buildCanvasDataModel(relations) {
|
|
25596
|
+
return buildCanvasModel(diagramIssues(), relations);
|
|
25368
25597
|
}
|
|
25369
25598
|
function diagramIssues() {
|
|
25370
25599
|
try {
|
|
@@ -39525,7 +39754,10 @@ var externalStatusesOutput = {
|
|
|
39525
39754
|
stale: import_zod11.z.boolean(),
|
|
39526
39755
|
drifted: import_zod11.z.boolean().optional(),
|
|
39527
39756
|
uses: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())),
|
|
39528
|
-
detail: import_zod11.z.string().optional()
|
|
39757
|
+
detail: import_zod11.z.string().optional(),
|
|
39758
|
+
outOfReach: import_zod11.z.boolean().optional(),
|
|
39759
|
+
pinnedDigest: import_zod11.z.string().optional().describe("The content digest the lock recorded; provenance, never compared here."),
|
|
39760
|
+
pinnedCommit: import_zod11.z.string().optional().describe("The producer commit the lock recorded, for one in another repository; provenance only.")
|
|
39529
39761
|
})).describe("One status per declared external, in declaration order; EXTERNAL_CHECK_UNAVAILABLE marks what could not be compared."),
|
|
39530
39762
|
...staleServerOutput
|
|
39531
39763
|
};
|
|
@@ -41717,6 +41949,7 @@ function loadProjectConfig3() {
|
|
|
41717
41949
|
registerExporter,
|
|
41718
41950
|
registerPackRef,
|
|
41719
41951
|
reinjectLocalGuides,
|
|
41952
|
+
relationHealth,
|
|
41720
41953
|
removeDomain,
|
|
41721
41954
|
removeExternal,
|
|
41722
41955
|
removeMember,
|