@fluojs/studio 1.0.4 → 1.0.5

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.
@@ -1,171 +0,0 @@
1
- (function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))s(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const l of i.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&s(l)}).observe(document,{childList:!0,subtree:!0});function t(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(o){if(o.ep)return;o.ep=!0;const i=t(o);fetch(o.href,i)}})();function h(e){return typeof e=="object"&&e!==null}function w(e,n){return Object.hasOwn(e,n)}function C(e){return Array.isArray(e)&&e.every(n=>typeof n=="string")}function I(e){return e==="ready"||e==="not-ready"||e==="degraded"}function A(e){return e==="healthy"||e==="unhealthy"||e==="degraded"}function F(e){return e==="error"||e==="warning"||e==="info"}function q(e){if(!h(e))return null;if(typeof e.generatedAt!="string"||!h(e.readiness)||!h(e.health)||!Array.isArray(e.components)||!Array.isArray(e.diagnostics))throw new Error("Invalid platform snapshot payload.");if(!I(e.readiness.status)||typeof e.readiness.critical!="boolean")throw new Error("Invalid aggregate readiness in platform snapshot payload.");if(!A(e.health.status))throw new Error("Invalid aggregate health in platform snapshot payload.");for(const n of e.components){if(!h(n))throw new Error("Invalid component entry in platform snapshot payload.");if(typeof n.id!="string"||typeof n.kind!="string"||typeof n.state!="string"||!h(n.readiness)||!h(n.health)||!C(n.dependencies)||!h(n.telemetry)||!h(n.ownership)||!h(n.details))throw new Error("Invalid component shape in platform snapshot payload.");if(!I(n.readiness.status)||typeof n.readiness.critical!="boolean")throw new Error("Invalid component readiness in platform snapshot payload.");if(!A(n.health.status))throw new Error("Invalid component health in platform snapshot payload.");if(typeof n.telemetry.namespace!="string"||!h(n.telemetry.tags)||typeof n.ownership.ownsResources!="boolean"||typeof n.ownership.externallyManaged!="boolean")throw new Error("Invalid component telemetry/ownership in platform snapshot payload.")}for(const n of e.diagnostics){if(!h(n))throw new Error("Invalid diagnostics issue entry in platform snapshot payload.");if(typeof n.code!="string"||!F(n.severity)||typeof n.componentId!="string"||typeof n.message!="string")throw new Error("Invalid diagnostics issue shape in platform snapshot payload.");if(n.cause!==void 0&&typeof n.cause!="string"||n.fixHint!==void 0&&typeof n.fixHint!="string"||n.docsUrl!==void 0&&typeof n.docsUrl!="string"||n.dependsOn!==void 0&&!C(n.dependsOn))throw new Error("Invalid optional diagnostics issue fields in platform snapshot payload.")}return e}function J(e){if(!h(e))return null;if(e.version!==1)throw new Error("Unsupported bootstrap timing version. Expected version: 1.");if(typeof e.totalMs!="number"||!Array.isArray(e.phases))throw new Error("Invalid bootstrap timing payload.");for(const n of e.phases)if(!h(n)||typeof n.name!="string"||typeof n.durationMs!="number")throw new Error("Invalid phase entry in bootstrap timing payload.");return e}function H(e){if(!h(e))throw new Error("Invalid inspect report summary payload.");if(typeof e.componentCount!="number"||typeof e.diagnosticCount!="number"||typeof e.errorCount!="number"||!A(e.healthStatus)||!I(e.readinessStatus)||typeof e.timingTotalMs!="number"||typeof e.warningCount!="number")throw new Error("Invalid inspect report summary payload.");return e}function P(e,n,t){const s=n.diagnostics.filter(i=>i.severity==="error").length,o=n.diagnostics.filter(i=>i.severity==="warning").length;if(e.componentCount!==n.components.length||e.diagnosticCount!==n.diagnostics.length||e.errorCount!==s||e.healthStatus!==n.health.status||e.readinessStatus!==n.readiness.status||e.timingTotalMs!==t.totalMs||e.warningCount!==o)throw new Error("Inspect report summary does not match snapshot and timing payload data.")}function U(e){return e.summary!==void 0||w(e,"snapshot")&&w(e,"timing")&&(w(e,"generatedAt")||w(e,"version"))}function _(e,n,t){if(!h(e)||!U(e))return null;if(e.summary===void 0||e.version!==1||typeof e.generatedAt!="string"||!n||!t)throw new Error("Invalid inspect report artifact payload.");const s=H(e.summary);return P(s,n,t),{generatedAt:e.generatedAt,snapshot:n,summary:s,timing:t,version:1}}function B(e){const n=JSON.parse(e),t=h(n)?n:void 0,s=t!==void 0&&w(t,"snapshot"),o=t!==void 0&&w(t,"timing"),i=t!==void 0&&!s&&!o&&w(t,"version")&&w(t,"totalMs")&&w(t,"phases"),l=q(s?t.snapshot:i?void 0:n),a=J(o?t.timing:l?void 0:n),d=_(n,l,a);if(!l&&!a)throw new Error("Unsupported file format. Expected platform snapshot JSON or timing JSON.");return{payload:{...d?{report:d}:{},...l?{snapshot:l}:{},...a?{timing:a}:{}},rawJson:e}}function z(e,n){const t=n.query.trim().toLowerCase(),s=e.components.filter(i=>n.readinessStatuses.length>0&&!n.readinessStatuses.includes(i.readiness.status)?!1:t?i.id.toLowerCase().includes(t)||i.kind.toLowerCase().includes(t)||i.dependencies.some(l=>l.toLowerCase().includes(t)):!0),o=e.diagnostics.filter(i=>{var l,a,d,g;return n.severities.length>0&&!n.severities.includes(i.severity)?!1:t?i.code.toLowerCase().includes(t)||i.componentId.toLowerCase().includes(t)||i.message.toLowerCase().includes(t)||(((l=i.cause)==null?void 0:l.toLowerCase().includes(t))??!1)||(((a=i.fixHint)==null?void 0:a.toLowerCase().includes(t))??!1)||(((d=i.docsUrl)==null?void 0:d.toLowerCase().includes(t))??!1)||(((g=i.dependsOn)==null?void 0:g.some(y=>y.toLowerCase().includes(t)))??!1):!0});return{...e,components:s,diagnostics:o}}function L(e){return e.replaceAll("\\","\\\\").replaceAll('"','\\"').replaceAll(`\r
2
- `,"\\n").replaceAll("\r","\\n").replaceAll(`
3
- `,"\\n")}function V(e){return e.replaceAll(/[^a-zA-Z0-9_]/g,"_")}function Y(e){let n=2166136261;for(const t of e)n^=t.codePointAt(0)??0,n=Math.imul(n,16777619)>>>0;return n.toString(16).padStart(8,"0")}function G(e){return`EXT_${V(e)}_${Y(e)}`}function N(e){const n=["graph TD"],t=new Map,s=new Map;if(e.components.length===0)return n.push(' EMPTY["No registered platform components"]'),n.join(`
4
- `);for(const[l,a]of e.components.entries()){const d=`C${String(l+1)}`;t.set(a.id,d),n.push(` ${d}["${L(a.id)}\\nkind: ${L(a.kind)}\\nreadiness: ${a.readiness.status}\\nhealth: ${a.health.status}"]`)}for(const l of e.components){const a=t.get(l.id);if(a)for(const d of l.dependencies){const g=t.get(d);if(g){n.push(` ${a} --> ${g}`);continue}let y=s.get(d);y||(y=G(d),s.set(d,y),n.push(` ${y}["${L(d)}"]`)),n.push(` ${a} --> ${y}`)}}const o=[],i=[];for(const l of e.components){const a=t.get(l.id);a&&(l.readiness.status==="degraded"&&o.push(a),l.readiness.status==="not-ready"&&i.push(a))}return o.length>0&&(n.push(` class ${o.join(",")} degraded`),n.push(" classDef degraded stroke:#f59e0b,stroke-width:2px")),i.length>0&&(n.push(` class ${i.join(",")} notReady`),n.push(" classDef notReady stroke:#ef4444,stroke-width:2px")),n.join(`
5
- `)}function c(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#039;")}function X(e){try{const n=new URL(e);if(n.protocol==="https:"||n.protocol==="http:")return n.href}catch{return}}function K(e){const n=X(e),t=c(e);return n?`<p><strong>docs:</strong> <a href="${c(n)}" target="_blank" rel="noopener noreferrer">${t}</a></p>`:`<p><strong>docs:</strong> <span>${t}</span></p>`}function j(e){const n=new Set(e.map(o=>o.id)),t=[],s=new Set;for(const o of e)for(const i of o.dependencies)n.has(i)||s.has(i)||(s.add(i),t.push(i));return t}function Q(e,n){if(!e||e.components.length===0)return;const t=new Map(e.components.map(d=>[d.id,d])),s=n?t.get(n)??e.components[0]:e.components[0];if(!s)return;const o=[],i=[];for(const d of s.dependencies){const g=t.get(d);g?o.push(g):i.push(d)}const l=e.components.filter(d=>d.id!==s.id&&d.dependencies.includes(s.id)),a=e.diagnostics.filter(d=>{var g;return d.componentId===s.id||(((g=d.dependsOn)==null?void 0:g.includes(s.id))??!1)});return{component:s,diagnostics:a,externalDependencies:i,incoming:l,outgoing:o}}function W(e,n,t){const s=Math.min(n,t)/2-70,o=n/2,i=t/2,l=new Map,a=j(e.components),d=[...e.components.map(g=>g.id),...a];return d.forEach((g,y)=>{const v=Math.PI*2*y/Math.max(d.length,1);l.set(g,{x:o+s*Math.cos(v),y:i+s*Math.sin(v)})}),l}function Z(e,n){const o=e.components,i=W(e,900,460),l=j(o),a=n?o.find(u=>u.id===n):void 0,d=new Set((a==null?void 0:a.dependencies)??[]),g=new Set(n?o.filter(u=>u.dependencies.includes(n)).map(u=>u.id):[]),y=o.flatMap(u=>u.dependencies.map(r=>{const f=i.get(u.id),m=i.get(r);if(!f||!m)return"";const S=u.id===n||r===n;return`<line x1="${f.x}" y1="${f.y}" x2="${m.x}" y2="${m.y}" class="edge-line${S?" edge-selected":""}" marker-end="url(#arrow)" />`})).join(""),v=o.map(u=>{const r=i.get(u.id);if(!r)return"";const m=["module-node",u.readiness.status==="not-ready"?"component-not-ready":u.readiness.status==="degraded"?"component-degraded":"component-ready",u.id===n?"module-selected":"",d.has(u.id)?"module-neighbor":"",g.has(u.id)?"module-dependent":""].filter(Boolean).join(" ");return`<g>
6
- <circle cx="${r.x}" cy="${r.y}" r="34" class="${m}" data-component="${c(u.id)}" tabindex="0" role="button" aria-label="Inspect ${c(u.id)}" />
7
- <text x="${r.x}" y="${r.y+4}" text-anchor="middle" class="module-label">${c(u.id)}</text>
8
- </g>`}).join(""),E=l.map(u=>{const r=i.get(u);if(!r)return"";const f=["module-node","component-external",d.has(u)?"module-neighbor":""].filter(Boolean).join(" ");return`<g>
9
- <rect x="${r.x-42}" y="${r.y-20}" width="84" height="40" rx="10" class="${f}" />
10
- <text x="${r.x}" y="${r.y+4}" text-anchor="middle" class="module-label">${c(u)}</text>
11
- </g>`}).join("");return`<svg viewBox="0 0 900 460" role="img" aria-label="Platform component dependency graph">
12
- <defs>
13
- <marker id="arrow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
14
- <polygon points="0 0, 10 3.5, 0 7" class="edge-arrow" />
15
- </marker>
16
- </defs>
17
- ${y}
18
- ${v}
19
- ${E}
20
- </svg>`}function ee(e){return e?e.diagnostics.length===0?'<p class="muted">No diagnostics issues.</p>':`<div class="diagnostics-list">
21
- ${e.diagnostics.map(n=>{const t=n.dependsOn&&n.dependsOn.length>0?`<div class="chips">${n.dependsOn.map(s=>`<span class="chip">dependsOn: ${c(s)}</span>`).join("")}</div>`:"";return`<article class="card issue severity-${c(n.severity)}">
22
- <h3>${c(n.code)}</h3>
23
- <p><strong>severity:</strong> ${c(n.severity)} · <strong>component:</strong> ${c(n.componentId)}</p>
24
- <p>${c(n.message)}</p>
25
- ${n.cause?`<p><strong>cause:</strong> ${c(n.cause)}</p>`:""}
26
- ${n.fixHint?`<p><strong>fix hint:</strong> ${c(n.fixHint)}</p>`:""}
27
- ${n.docsUrl?K(n.docsUrl):""}
28
- ${t}
29
- </article>`}).join("")}
30
- </div>`:'<p class="muted">No platform snapshot loaded.</p>'}const k=document.querySelector("#app");if(!k)throw new Error("App root not found.");const ne=k,te=["ready","degraded","not-ready"],oe=["error","warning","info"],p={filter:{query:"",readinessStatuses:[],severities:[]}};function se(e,n){const t=new Blob([n],{type:"application/json"}),s=URL.createObjectURL(t),o=document.createElement("a");o.href=s,o.download=e,o.click(),URL.revokeObjectURL(s)}async function O(e){if(!navigator.clipboard)throw new Error("Clipboard API is unavailable.");await navigator.clipboard.writeText(e)}function M(e,n){return e.includes(n)?e.filter(t=>t!==n):[...e,n]}function T(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement}function re(e){return e instanceof HTMLElement||e instanceof SVGElement}function ie(){const e=document.activeElement;return!T(e)||!e.id?e instanceof SVGElement&&e.dataset.component?{componentId:e.dataset.component,kind:"graph-node"}:void 0:{id:e.id,kind:"text-control",selectionEnd:e.selectionEnd,selectionStart:e.selectionStart}}function ae(e){if(!e)return;if(e.kind==="graph-node"){const s=Array.from(document.querySelectorAll("[data-component]")).find(o=>o instanceof SVGElement&&o.dataset.component===e.componentId)??null;re(s)&&s.focus({preventScroll:!0});return}const n=document.getElementById(e.id);T(n)&&(n.focus({preventScroll:!0}),e.selectionStart!==null&&e.selectionEnd!==null&&n.setSelectionRange(e.selectionStart,e.selectionEnd))}function R(e,n){return!e||e.components.length===0?void 0:(n?e.components.find(s=>s.id===n):void 0)??e.components[0]}function x(){var t;const e=(t=p.payload)==null?void 0:t.snapshot;if(!e){p.filteredSnapshot=void 0,p.selectedComponentId=void 0;return}p.filteredSnapshot=z(e,p.filter);const n=R(p.filteredSnapshot,p.selectedComponentId);p.selectedComponentId=n==null?void 0:n.id}function de(e){if(!e)return'<p class="muted">No component selected.</p>';const n=e.dependencies.length>0?e.dependencies.map(t=>`<span class="chip">dependsOn: ${c(t)}</span>`).join(""):'<span class="chip">dependsOn: none</span>';return`
31
- <h3>${c(e.id)}</h3>
32
- <p class="muted">kind: <strong>${c(e.kind)}</strong> · state: <strong>${c(e.state)}</strong></p>
33
- <div class="chips">
34
- <span class="chip">readiness: ${c(e.readiness.status)}</span>
35
- <span class="chip">critical: ${e.readiness.critical?"true":"false"}</span>
36
- <span class="chip">health: ${c(e.health.status)}</span>
37
- <span class="chip">ownership: owns=${e.ownership.ownsResources?"true":"false"}/external=${e.ownership.externallyManaged?"true":"false"}</span>
38
- ${n}
39
- </div>
40
- <p class="muted">telemetry namespace: <code>${c(e.telemetry.namespace)}</code></p>
41
- <h4>Sanitized details</h4>
42
- <pre>${c(JSON.stringify(e.details,null,2))}</pre>
43
- `}function D(e,n){return`<button class="connection-button" data-select-component="${c(e.id)}" type="button">
44
- <span>${c(e.id)}</span>
45
- <small>${c(n)} · ${c(e.kind)} · ${c(e.readiness.status)}</small>
46
- </button>`}function b(e,n,t){return`
47
- <section class="connection-group">
48
- <h4>${c(e)}</h4>
49
- ${t||`<p class="muted">${c(n)}</p>`}
50
- </section>
51
- `}function ce(e,n){const t=Q(e,n);if(!t)return'<p class="muted">Load a platform snapshot to explore component connections.</p>';const s=t.outgoing.map(a=>D(a,"dependency")).join(""),o=t.incoming.map(a=>D(a,"dependent")).join(""),i=t.externalDependencies.map(a=>`<span class="connection-pill external-pill">${c(a)}</span>`).join(""),l=t.diagnostics.map(a=>`<article class="connection-diagnostic severity-${c(a.severity)}">
52
- <strong>${c(a.code)}</strong>
53
- <span>${c(a.severity)} · ${c(a.componentId)}</span>
54
- <p>${c(a.message)}</p>
55
- </article>`).join("");return`
56
- <div class="connection-hero">
57
- <div>
58
- <p class="eyebrow">Selected component</p>
59
- <h3>${c(t.component.id)}</h3>
60
- <p class="muted">${c(t.component.kind)} · state ${c(t.component.state)}</p>
61
- </div>
62
- <div class="connection-metrics" aria-label="Selected component connection counts">
63
- <span><strong>${String(t.outgoing.length)}</strong> internal deps</span>
64
- <span><strong>${String(t.externalDependencies.length)}</strong> external deps</span>
65
- <span><strong>${String(t.incoming.length)}</strong> dependents</span>
66
- </div>
67
- </div>
68
- <div class="connection-grid">
69
- ${b("Depends on","No internal component dependencies.",s)}
70
- ${b("Required by","No components depend on this selection.",o)}
71
- ${b("External dependencies","No external dependencies.",i)}
72
- ${b("Related diagnostics","No related diagnostics.",l)}
73
- </div>
74
- `}function le(){var n;const e=(n=p.payload)==null?void 0:n.timing;return e?`
75
- <p><strong>Total:</strong> ${e.totalMs.toFixed(3)}ms</p>
76
- <table>
77
- <thead>
78
- <tr><th>phase</th><th>duration (ms)</th></tr>
79
- </thead>
80
- <tbody>
81
- ${e.phases.map(t=>`<tr><td>${c(t.name)}</td><td>${t.durationMs.toFixed(3)}</td></tr>`).join("")}
82
- </tbody>
83
- </table>
84
- `:'<p class="muted">Timing not collected.</p>'}function pe(e){if(!e)return'<p class="muted">No platform snapshot loaded.</p>';const n={degraded:e.components.filter(t=>t.readiness.status==="degraded").length,notReady:e.components.filter(t=>t.readiness.status==="not-ready").length,ready:e.components.filter(t=>t.readiness.status==="ready").length};return`
85
- <div class="chips">
86
- <span class="chip">generatedAt: ${c(e.generatedAt)}</span>
87
- <span class="chip">aggregate readiness: ${c(e.readiness.status)}</span>
88
- <span class="chip">aggregate health: ${c(e.health.status)}</span>
89
- <span class="chip">components: ${String(e.components.length)}</span>
90
- <span class="chip">diagnostics: ${String(e.diagnostics.length)}</span>
91
- <span class="chip">ready/degraded/not-ready: ${n.ready}/${n.degraded}/${n.notReady}</span>
92
- </div>
93
- `}function $(e={}){const n=typeof e=="string"?e:e.message,t=typeof e=="string"||!e.preserveFocus?void 0:ie(),s=p.filteredSnapshot,o=R(s,p.selectedComponentId),i=s?N(s):"",l=s&&s.components.length>0?Z(s,o==null?void 0:o.id):'<p class="muted">No platform components loaded.</p>';ne.innerHTML=`
94
- <main>
95
- <header>
96
- <h1>Fluo Studio Platform Snapshot Viewer</h1>
97
- <p>Load JSON exported by <code>fluo inspect --json</code> (shared platform snapshot/diagnostic schema) and optionally timing JSON from <code>--timing</code>.</p>
98
- </header>
99
-
100
- <section class="card uploader" id="drop-zone">
101
- <h2>Diagnostics file input</h2>
102
- <p>Drag & drop a JSON file, or choose one manually.</p>
103
- <input type="file" id="file-input" accept="application/json" />
104
- <div class="actions">
105
- <button id="download-json" ${p.rawJson?"":"disabled"}>Download loaded JSON</button>
106
- <button id="copy-json" ${p.rawJson?"":"disabled"}>Copy loaded JSON</button>
107
- <button id="copy-mermaid" ${s?"":"disabled"}>Copy Mermaid</button>
108
- </div>
109
- ${n?`<p class="notice">${c(n)}</p>`:""}
110
- </section>
111
-
112
- <section class="card">
113
- <h2>Snapshot summary</h2>
114
- ${pe(s)}
115
- </section>
116
-
117
- <section class="split-grid">
118
- <div class="card">
119
- <h2>Search and filtering</h2>
120
- <label>
121
- Search component/diagnostic
122
- <input type="text" id="search" value="${c(p.filter.query)}" placeholder="e.g. redis.default or QUEUE_DEPENDENCY_NOT_READY" />
123
- </label>
124
-
125
- <div class="filter-row">
126
- <span>Component readiness</span>
127
- ${te.map(r=>`<label><input type="checkbox" id="readiness-${r}" data-readiness="${r}" ${p.filter.readinessStatuses.includes(r)?"checked":""}/> ${r}</label>`).join("")}
128
- </div>
129
-
130
- <div class="filter-row">
131
- <span>Diagnostic severity</span>
132
- ${oe.map(r=>`<label><input type="checkbox" id="severity-${r}" data-severity="${r}" ${p.filter.severities.includes(r)?"checked":""}/> ${r}</label>`).join("")}
133
- </div>
134
- </div>
135
-
136
- <div class="card">
137
- <h2>Timing</h2>
138
- ${le()}
139
- </div>
140
- </section>
141
-
142
- <section class="card">
143
- <h2>Platform dependency graph</h2>
144
- <p class="muted">Component dependencies are rendered directly from the shared platform snapshot schema. Select a node to inspect its dependency neighborhood.</p>
145
- <div id="graph-host">${l}</div>
146
- </section>
147
-
148
- <section class="card inspector-card">
149
- <h2>Connection explorer</h2>
150
- <p class="muted">Studio owns snapshot inspection and rendering: use this panel to inspect incoming and outgoing component relationships without changing CLI export semantics.</p>
151
- ${ce(s,o==null?void 0:o.id)}
152
- </section>
153
-
154
- <section class="split-grid">
155
- <div class="card" id="details-panel">
156
- <h2>Component details</h2>
157
- ${de(o)}
158
- </div>
159
- <div class="card">
160
- <h2>Mermaid output</h2>
161
- <pre>${c(i||"No snapshot loaded.")}</pre>
162
- </div>
163
- </section>
164
-
165
- <section class="card">
166
- <h2>Diagnostics issues</h2>
167
- <p class="muted">Fix hints and dependency chains are rendered from <code>diagnostics.fixHint</code> and <code>diagnostics.dependsOn</code>.</p>
168
- ${ee(s)}
169
- </section>
170
- </main>
171
- `;const a=document.querySelector("#file-input"),d=document.querySelector("#drop-zone"),g=document.querySelector("#search"),y=document.querySelector("#copy-json"),v=document.querySelector("#download-json"),E=document.querySelector("#copy-mermaid"),u=async r=>{const f=await r.text();try{const m=B(f);p.payload=m.payload,p.rawJson=m.rawJson,x(),$("Diagnostics file loaded successfully.")}catch(m){p.payload=void 0,p.filteredSnapshot=void 0,p.selectedComponentId=void 0,p.rawJson=void 0,$(m instanceof Error?m.message:"Failed to parse diagnostics file.")}};a==null||a.addEventListener("change",async r=>{var S;const m=(S=r.target.files)==null?void 0:S[0];m&&await u(m)}),d==null||d.addEventListener("dragover",r=>{r.preventDefault(),d.classList.add("drag-active")}),d==null||d.addEventListener("dragleave",()=>{d.classList.remove("drag-active")}),d==null||d.addEventListener("drop",async r=>{var m,S;r.preventDefault(),d.classList.remove("drag-active");const f=(S=(m=r.dataTransfer)==null?void 0:m.files)==null?void 0:S[0];f&&await u(f)}),g==null||g.addEventListener("input",r=>{const f=r.target;p.filter.query=f.value,x(),$({preserveFocus:!0})}),document.querySelectorAll("input[data-readiness]").forEach(r=>{r.addEventListener("change",()=>{p.filter.readinessStatuses=M(p.filter.readinessStatuses,r.dataset.readiness),x(),$({preserveFocus:!0})})}),document.querySelectorAll("input[data-severity]").forEach(r=>{r.addEventListener("change",()=>{p.filter.severities=M(p.filter.severities,r.dataset.severity),x(),$({preserveFocus:!0})})}),y==null||y.addEventListener("click",async()=>{if(p.rawJson)try{await O(p.rawJson),$("Loaded JSON copied to clipboard.")}catch(r){$(r instanceof Error?r.message:"Failed to copy JSON.")}}),v==null||v.addEventListener("click",()=>{p.rawJson&&(se("fluo-diagnostics.json",p.rawJson),$("Loaded JSON downloaded."))}),E==null||E.addEventListener("click",async()=>{if(s)try{await O(N(s)),$("Mermaid copied to clipboard.")}catch(r){$(r instanceof Error?r.message:"Failed to copy Mermaid text.")}}),document.querySelectorAll("[data-component]").forEach(r=>{r.addEventListener("click",()=>{const f=r.dataset.component;f&&(p.selectedComponentId=f,$({preserveFocus:!0}))}),r.addEventListener("keydown",f=>{if(f.key!=="Enter"&&f.key!==" ")return;f.preventDefault();const m=r.dataset.component;m&&(p.selectedComponentId=m,$({preserveFocus:!0}))})}),document.querySelectorAll("[data-select-component]").forEach(r=>{r.addEventListener("click",()=>{const f=r.dataset.selectComponent;f&&(p.selectedComponentId=f,$())})}),ae(t)}x();$();
@@ -1 +0,0 @@
1
- :root{color-scheme:light dark;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}body{margin:0;background:#0b1020;color:#e5e7eb}main{max-width:1200px;margin:0 auto;padding:24px}h1,h2,h3{margin-top:0}code{background:#1f2937;border-radius:4px;padding:2px 6px}.card{border:1px solid #334155;border-radius:10px;background:#111827;padding:16px;margin-bottom:16px}.split-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}button{background:#2563eb;border:none;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer}button:disabled{background:#475569;cursor:not-allowed}label{display:block;margin-bottom:10px}input[type=text]{width:100%;margin-top:6px;border-radius:8px;border:1px solid #334155;background:#0f172a;color:#e5e7eb;padding:8px 10px}.filter-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px}.muted{color:#94a3b8}.chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}.chip{border:1px solid #334155;border-radius:999px;padding:2px 8px;font-size:12px}table{width:100%;border-collapse:collapse}th,td{border-bottom:1px solid #334155;text-align:left;font-size:13px;padding:6px}pre{overflow:auto;max-height:300px;background:#0f172a;border:1px solid #334155;padding:12px;border-radius:8px}.notice{margin-top:8px;color:#93c5fd}.uploader.drag-active{border-color:#60a5fa;box-shadow:0 0 0 2px #60a5fa59 inset}#graph-host{overflow:auto;border:1px solid #334155;border-radius:8px;background:#0f172a}.edge-line{stroke:#64748b;stroke-width:1.6}.edge-selected{stroke:#f59e0b;stroke-width:2.6}.edge-arrow{fill:#64748b}.module-node{fill:#1e293b;stroke:#64748b;stroke-width:1.5;cursor:pointer}.module-node:focus-visible{outline:none;stroke:#60a5fa;stroke-width:3}.module-root{stroke:#3b82f6;stroke-width:2.6}.component-ready{fill:#14532d}.component-degraded{fill:#7c2d12}.component-not-ready{fill:#7f1d1d}.component-external{fill:#312e81;cursor:default}.module-selected{stroke:#f59e0b;stroke-width:3}.module-neighbor{stroke:#38bdf8;stroke-width:2.6}.module-dependent{stroke:#a78bfa;stroke-width:2.6}.module-label{fill:#e5e7eb;font-size:11px;pointer-events:none}.diagnostics-list{display:grid;gap:12px}.issue{margin-bottom:0}.issue.severity-error{border-color:#ef4444}.issue.severity-warning{border-color:#f59e0b}.issue.severity-info{border-color:#3b82f6}a{color:#93c5fd}.inspector-card{background:linear-gradient(135deg,#0f172af5,#111827f5)}.connection-hero{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-start;justify-content:space-between;border:1px solid #334155;border-radius:12px;background:#0f172a;padding:14px;margin-bottom:14px}.eyebrow{margin:0 0 6px;color:#93c5fd;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}.connection-metrics{display:flex;flex-wrap:wrap;gap:8px}.connection-metrics span,.connection-pill{border:1px solid #334155;border-radius:999px;background:#111827;color:#cbd5e1;padding:6px 10px;font-size:12px}.connection-grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}.connection-group h4{margin:0 0 8px}.connection-button{display:block;width:100%;margin-bottom:8px;border:1px solid #334155;background:#0f172a;color:#e5e7eb;text-align:left}.connection-button:hover,.connection-button:focus-visible{border-color:#60a5fa;outline:none}.connection-button span,.connection-button small{display:block}.connection-button small{margin-top:4px;color:#94a3b8}.external-pill{display:inline-block;margin:0 6px 6px 0}.connection-diagnostic{border-left:3px solid #64748b;padding:8px 0 8px 10px;margin-bottom:8px}.connection-diagnostic.severity-error{border-left-color:#ef4444}.connection-diagnostic.severity-warning{border-left-color:#f59e0b}.connection-diagnostic.severity-info{border-left-color:#3b82f6}.connection-diagnostic span{display:block;color:#94a3b8;font-size:12px;margin-top:2px}.connection-diagnostic p{margin:6px 0 0}