Repository navigation
Add e18e replacement suggestions, supply-chain combination flags, and maintenance drift tiers - #95
Conversation
…e drift tiers Ports the useful analysis from the retired SaaS into the CLI as three features, deliberately excluding the composite risk score: - Replacement suggestions: dependencies are matched offline against the vendored e18e module-replacements catalogue (es-tooling/module-replacements v3.0.0, MIT). Matches appear in the JSON model, the report detail panel, explain output, and as info-level modernization findings for direct deps. The report header stat, filter toggle, and detail section only appear when a scan actually has matches. Refresh with `npm run update:replacements`. - Supply-chain combination flags: install lifecycle scripts paired with a mutable or unverifiable source (git dependency, non-registry tarball, unexpected registry host, missing lockfile integrity) now produce dedicated error/warning findings, escalate overall dependency risk in the report, and back a new opt-in `supply-chain-combo` --fail-on rule. - Maintenance drift tiers: a new `slowing` status (12+ months without a registry write), plus dual-signal escalation using the repository push timestamp already returned by the bounded ecosyste.ms lookups - both the registry and the repo must be quiet before a package is called stale or unmaintained. Also derives a coarse `upgrade.risk` band per dependency. Schema bumps to 1.7 (additive; 1.6 baselines remain valid for compare). Committed dist/ also catches up with PR #86, which shipped without a rebuild. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe change adds dual-surface maintenance statuses, offline replacement suggestions, upgrade-risk bands, supply-chain combination findings and policy rules, schema 1.7 updates, and report UI support for displaying and filtering the new dependency data. ChangesReport enrichment and risk signals
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant Aggregator
participant Findings
participant ReportUI
CLI->>Aggregator: Aggregate dependencies and enrich records
Aggregator->>Findings: Build findings from enriched records and signals
Findings-->>CLI: Return findings and policy inputs
CLI->>ReportUI: Render schema 1.7 report data
ReportUI-->>CLI: Display replacement, maintenance, risk, and supply-chain details
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@report-ui/index.html`:
- Around line 239-247: Update the report stat-chip grid styling used by the
stat-replacements chip so all six desktop chips fit on one row, either by
changing the fixed layout to six columns or by using an adaptive grid. Preserve
the existing responsive behavior for narrower viewports.
In `@report-ui/types.ts`:
- Line 103: Update the schemaVersion type in report-ui/types.ts to include '1.7'
alongside the existing supported versions, keeping the report UI contract
aligned with CLI-generated payloads.
In `@src/cli.ts`:
- Around line 2335-2336: Update the aggregation flow around
applyUpgradeRisk(aggregated) so upgrade-risk derivation always runs immediately
after aggregation, regardless of enrichmentTouchedData. Keep only any
enrichment-dependent findings recomputation conditional, and add a CLI
regression test covering scans without registry or maintenance enrichment that
still produce dep.upgrade.risk from local outdated or blocker data.
In `@src/report-assets.ts`:
- Line 16: Update the source-signal indexing logic in function s so packageId is
used as the primary key, preserving its version-qualified identity when deriving
install-script combinations; fall back to packageName only when packageId is
absent. Ensure combination lookup in function i uses the same packageId-first
keying, then regenerate the JS_CONTENT bundle asset.
In `@src/supplyChainCombos.ts`:
- Around line 67-80: The supply-chain signal index currently collapses different
package instances by name, causing false combinations. In
src/supplyChainCombos.ts:67-80, key the map by packageId or the canonical
packageName@packageVersion identity; in src/failOn.ts:543-548, query it using
the matching dependency instance key such as dep.package.id. Add coverage
proving a source signal on one version and an install hook on another does not
trigger supply-chain-combo.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c357148c-f42d-4d65-b82a-f81c4032aa10
⛔ Files ignored due to path filters (20)
dist/aggregator.jsis excluded by!**/dist/**dist/cli.jsis excluded by!**/dist/**dist/explain.jsis excluded by!**/dist/**dist/failOn.jsis excluded by!**/dist/**dist/findings.jsis excluded by!**/dist/**dist/generated/replacements.jsis excluded by!**/dist/**,!**/generated/**dist/license.jsis excluded by!**/dist/**dist/maintenanceCache.jsis excluded by!**/dist/**dist/outputFormats.jsis excluded by!**/dist/**dist/report-assets.jsis excluded by!**/dist/**dist/report.jsis excluded by!**/dist/**dist/reportDetailRules.jsis excluded by!**/dist/**dist/runners/maintenanceSignals.jsis excluded by!**/dist/**dist/runners/npmAudit.jsis excluded by!**/dist/**dist/schema.jsis excluded by!**/dist/**dist/supplyChainCombos.jsis excluded by!**/dist/**dist/upgradeRisk.jsis excluded by!**/dist/**report-ui/dist/report.cssis excluded by!**/dist/**report-ui/dist/report.iife.jsis excluded by!**/dist/**src/generated/replacements.tsis excluded by!**/generated/**
📒 Files selected for processing (27)
README.mdpackage.jsonreport-ui/index.htmlreport-ui/main.tsreport-ui/sample-data.jsonreport-ui/types.tsscripts/build-replacements.tssrc/aggregator.tssrc/cli.test.tssrc/cli.tssrc/explain.tssrc/failOn.test.tssrc/failOn.tssrc/findings.test.tssrc/findings.tssrc/maintenanceCache.tssrc/report-assets.tssrc/report.tssrc/reportDetailRules.tssrc/runners/maintenanceSignals.test.tssrc/runners/maintenanceSignals.tssrc/schema.tssrc/supplyChainCombos.test.tssrc/supplyChainCombos.tssrc/types.tssrc/upgradeRisk.test.tssrc/upgradeRisk.ts
| <button | ||
| type="button" | ||
| class="stat-chip" | ||
| id="stat-replacements" | ||
| data-stat-filter="has-replacement" | ||
| hidden | ||
| > | ||
| <span class="meta-label">Replacements</span> <strong>–</strong> | ||
| </button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Prevent the replacement stat from wrapping into its own desktop row.
This adds a sixth chip, but the shipped report CSS uses grid-template-columns: repeat(5, 1fr). Reports with replacements will show a lone second-row stat. Use six columns or an adaptive grid.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@report-ui/index.html` around lines 239 - 247, Update the report stat-chip
grid styling used by the stat-replacements chip so all six desktop chips fit on
one row, either by changing the fixed layout to six columns or by using an
adaptive grid. Preserve the existing responsive behavior for narrower viewports.
| if (enrichmentTouchedData) { | ||
| applyUpgradeRisk(aggregated); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Apply upgrade-risk derivation even when no enrichment ran.
applyUpgradeRisk() is gated by enrichmentTouchedData, which remains false for scans without registry/maintenance enrichment (including offline-oriented runs). Those reports omit the new dep.upgrade.risk field despite having local outdated/blocker data. Invoke it immediately after aggregation; keep only findings recomputation conditional if needed. Add a no-enrichment CLI regression test.
Proposed fix
- if (enrichmentTouchedData) {
- applyUpgradeRisk(aggregated);
+ applyUpgradeRisk(aggregated);
+ if (enrichmentTouchedData) {
const findings = buildDependencyFindings(aggregated, { targetNodeMajor: opts.targetNodeMajor });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (enrichmentTouchedData) { | |
| applyUpgradeRisk(aggregated); | |
| applyUpgradeRisk(aggregated); | |
| if (enrichmentTouchedData) { |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/cli.ts` around lines 2335 - 2336, Update the aggregation flow around
applyUpgradeRisk(aggregated) so upgrade-risk derivation always runs immediately
after aggregation, regardless of enrichmentTouchedData. Keep only any
enrichment-dependent findings recomputation conditional, and add a CLI
regression test covering scans without registry or maintenance enrichment that
still produce dep.upgrade.risk from local outdated or blocker data.
| @@ -13,4 +13,4 @@ export const CSS_CONTENT = `*,:before,:after{box-sizing:border-box}:root{--bg-pr | |||
| * JavaScript content for the dependency radar HTML report | |||
| * Built from report-ui/main.ts | |||
| */ | |||
| export const JS_CONTENT = `!function(){var e={"network-access":"Accesses network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"};function t(e){return e.critical+e.high+e.moderate+e.low}function n(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e.split(/[-_\\s]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function a(a,s){const r=[],i=t(s),o=a.security.advisories?.some(e=>e.fixAvailable);if(s.critical||s.high){const e=s.critical+s.high;r.push(\`\${e} critical/high \${1===e?"vulnerability":"vulnerabilities"}\${o?", fix available":""}\`)}if(s.moderate||s.low){const e=s.moderate+s.low;r.push(\`\${function(e){const t=[];return e.moderate&&t.push(\`\${e.moderate} moderate\`),e.low&&t.push(\`\${e.low} low\`),t.join(", ")}(s)} \${1===e?"vulnerability":"vulnerabilities"}\${o?", fix available":""}\`)}"deprecated"===a.maintenance?.status?r.push(a.maintenance.deprecated&&!a.maintenance.deprecated.installedVersion?"Latest version deprecated by the author":"Deprecated by the author"):"archived"===a.maintenance?.status?r.push("Source repository is archived"):"unmaintained"===a.maintenance?.status?r.push("No registry activity for 3+ years"):"stale"===a.maintenance?.status&&r.push("No registry activity for 18+ months"),"green"!==a.compliance.licenseRisk&&r.push("Licence status: "+function(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}(a.compliance.license.status)),a.upgrade.blocksNodeMajor&&r.push("Blocks Node major upgrade"),a.upgrade.blockers?.length&&r.push(\`\${a.upgrade.blockers.length} upgrade \${1===a.upgrade.blockers.length?"blocker":"blockers"} detected\`);const c=a.execution?.risk||"green";var l;if("green"!==c&&r.push(("red"===(l=c)?"High":"amber"===l?"Medium":"Low")+" install-time execution risk"),a.execution?.scripts?.hooks?.length&&r.push("Runs "+a.execution.scripts.hooks.slice(0,2).join(", ")+" lifecycle script"+(1===a.execution.scripts.hooks.length?"":"s")),function(e){return Array.from(new Set([...e.execution?.scripts?.signals||[],...e.execution?.signals||[]]))}(a).slice(0,3).forEach(t=>r.push(e[t])),a.packaging?.signals?.length&&r.push(\`\${a.packaging.signals.length} package content \${1===a.packaging.signals.length?"signal":"signals"}\`),a.supplyChain?.registry?.signals?.length&&r.push(\`\${a.supplyChain.registry.signals.length} registry metadata \${1===a.supplyChain.registry.signals.length?"signal":"signals"}\`),a.usage.direct)r.push(\`Direct \${n(a.usage.scope).toLowerCase()} dependency\`);else{const e=a.usage.origins.topParentPackages?.[0]?\` introduced by \${a.usage.origins.topParentPackages[0]}\`:"";r.push(\`Transitive \${n(a.usage.scope).toLowerCase()} dependency\${e}\`)}return a.usage.depth>1&&r.push(\`Dependency depth \${a.usage.depth}\`),(0===r.length||0===i&&"green"===c&&"green"===a.compliance.licenseRisk&&r.length<3)&&["No known vulnerabilities","No install-time execution signals detected","Licence status appears consistent",a.usage.direct?\`Direct \${n(a.usage.scope).toLowerCase()} dependency\`:\`Transitive \${n(a.usage.scope).toLowerCase()} dependency\`].forEach(e=>{r.includes(e)||r.push(e)}),Array.from(new Set(r)).slice(0,8)}function s(e){if(!e.workspaces.enabled)return[];const t=new Set;return(e.workspaces.workspacePackages||[]).forEach(e=>{e.name&&t.add(e.name)}),Object.values(e.dependencies||{}).forEach(e=>{(e.usage.origins.workspaces||[]).forEach(e=>{e&&t.add(e)})}),Array.from(t).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t))}var r=2.8,i='500 11.5px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function o(e,t,n){return Math.min(n,Math.max(t,e))}function c(e,t=!1){return t?e.length:Math.min(e.length,34)}function l(e){const t=c(e);return e.length<=34?t:Math.max(1,t-6)}function d(e){const{labelGraphemes:t}=e;if(t.length<=34)return e.ref.name;const n=o(Math.round(e.renderLabelChars),1,t.length);return n>=t.length?e.ref.name:\`\${t.slice(0,n-1).join("")}…\`}function u(e,t,n){const a=function(e){const t=e.trim(),n=t.match(/^#([0-9a-f]{3}|[0-9a-f]{6})\$/i);if(n){const e=n[1];return 3===e.length?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16)}:{r:parseInt(e.slice(0,2),16),g:parseInt(e.slice(2,4),16),b:parseInt(e.slice(4,6),16)}}const a=t.match(/^rgba?\\(([^)]+)\\)\$/i);if(!a)return null;const s=a[1].replace(/\\//g," ").split(/[\\s,]+/).filter(Boolean).slice(0,3);if(3!==s.length)return null;const r=e=>{if(e.endsWith("%")){const t=Number(e.slice(0,-1));return Number.isFinite(t)?o(Math.round(t/100*255),0,255):null}const t=Number(e);return Number.isFinite(t)?o(Math.round(t),0,255):null},i=r(s[0]),c=r(s[1]),l=r(s[2]);return null===i||null===c||null===l?null:{r:i,g:c,b:l}}(e);if(!a)return n;const s=o(t,0,1);return\`rgb(\${Math.round(a.r+(255-a.r)*s)}, \${Math.round(a.g+(255-a.g)*s)}, \${Math.round(a.b+(255-a.b)*s)})\`}function p(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function h(e,t,n){if(0===t.length)return;if(e.moveTo(t[0].x,t[0].y),1===t.length)return;if(2===t.length)return void e.lineTo(t[1].x,t[1].y);for(let s=1;s<t.length-1;s+=1){const a=t[s-1],r=t[s],i=t[s+1],o=r.x-a.x,c=r.y-a.y,l=i.x-r.x,d=i.y-r.y,u=Math.hypot(o,c),p=Math.hypot(l,d);if(u<.001||p<.001){e.lineTo(r.x,r.y);continue}const h=Math.min(n,.45*u,.45*p),g=r.x-o/u*h,m=r.y-c/u*h,v=r.x+l/p*h,f=r.y+d/p*h;e.lineTo(g,m),e.quadraticCurveTo(r.x,r.y,v,f)}const a=t[t.length-1];e.lineTo(a.x,a.y)}function g(e){const t=new Map;return e.nodes.forEach(e=>{const n=t.get(e.depth);n?n.push(e):t.set(e.depth,[e])}),t.forEach(e=>{e.sort((e,t)=>e.renderY-t.renderY)}),t}function m(e,t,n,a){const s=t.renderX,r=t.renderY,i=n.renderX,c=n.renderY,l=n.depth-t.depth,d=Math.abs(l);if(0===d){const n=Math.abs(s-i)<a.sameColumnXThreshold,l=Math.abs(r-c),d=t.depth<a.maxDepth;if(n&&l>a.minDetourVerticalSpan&&d){const n=a.paddingX+t.depth*a.layerGap,d=a.paddingX+(t.depth+1)*a.layerGap,u=.5*(n+d);let p=u+a.detourInset;const g=Math.min(r,c)-12,m=Math.max(r,c)+12;(function(e,t,n,a,s){const r=e.depthNodeIndex.get(t);if(!r||0===r.length)return!1;const i=function(e,t){let n=0,a=e.length;for(;n<a;){const s=n+(a-n>>1);e[s].renderY<t?n=s+1:a=s}return n}(r,n);for(let o=i;o<r.length&&r[o].renderY<=a;o+=1)if(Math.abs(r[o].renderX-s)<e.detourNodeClearance)return!0;return!1})(a,t.depth+1,g,m,p)&&(p+=12);p=o(p,u+8,d-24);const v=Math.max(1,p-s);return void h(e,[{x:s,y:r},{x:p,y:r},{x:p,y:c},{x:i,y:c}],o(.42*Math.min(v,l),16,52))}e.moveTo(s,r);const u=s+.5*(i-s),p=r+(c-r)*a.edgeCurve;return void e.quadraticCurveTo(u,p,i,c)}if(1===d){const o=Math.min(t.depth,n.depth),l=a.paddingX+o*a.layerGap+.5*a.layerGap;return e.moveTo(s,r),void e.bezierCurveTo(l,r,l,c,i,c)}const u=Math.sign(l),p=c-r,g=[{x:s,y:r}],m=a.paddingX+t.depth*a.layerGap+u*(.5*a.layerGap);g.push({x:m,y:r});for(let o=1;o<d;o+=1){const e=t.depth+u*o,n=a.paddingX+e*a.layerGap+u*(.5*a.layerGap),s=o/d;g.push({x:n,y:r+p*s})}const v=a.paddingX+n.depth*a.layerGap-u*(.5*a.layerGap);g.push({x:v,y:c}),g.push({x:i,y:c}),h(e,g,14)}function v(e,t,n,a){a&&t.highlighted?function(e,t,n){const a=t.renderX,s=t.renderY,r=n.renderX,i=n.renderY,c=r-a,l=i-s;if(e.moveTo(a,s),Math.abs(c)<18){const t=a+(s<=i?26:-26);return void e.bezierCurveTo(t,s,t,i,r,i)}const d=o(.44*Math.abs(c),42,150),u=Math.sign(c),p=o(.12*Math.abs(l),0,24);e.bezierCurveTo(a+u*d,s+p*Math.sign(l),r-u*d,i-p*Math.sign(l),r,i)}(e,t.from,t.to):m(e,t.from,t.to,n)}function f(e,t){return\`\${e}@\${t}\`}function y(e,t){return\`\${e}->\${t}\`}function k(e){if(!e||"object"!=typeof e)return!1;const t=e;if(!Array.isArray(t.workspaces))return!1;if(!t.dependencies||"object"!=typeof t.dependencies)return!1;const n=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e);return!!t.workspaces.every(e=>(e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&!!Array.isArray(t.directDependencies)&&!!Array.isArray(t.directDevDependencies)})(e))&&(!!t.workspaces.every(e=>n(e.directDependencies)&&n(e.directDevDependencies))&&!!Object.entries(t.dependencies).every(([,e])=>{if(!e||"object"!=typeof e)return!1;const t=e;return!(void 0!==t.dependencies&&!Array.isArray(t.dependencies))&&!(void 0!==t.workspaceOrigins&&!Array.isArray(t.workspaceOrigins))}))}function b(e){const t=e.compliance.license.declared?.valid?e.compliance.license.declared.spdxId:void 0;return t||(e.compliance.license.inferred?.spdxId||"Unknown")}function w(e){const t=e.security?.summary;return t?Number(t.critical||0)+Number(t.high||0)+Number(t.moderate||0)+Number(t.low||0):0}function C(e){const t=e.security?.summary?.highest;return"critical"===t||"high"===t?"high":"moderate"===t?"moderate":"none"}function E(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.parents.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function x(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.children.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function S(e,t,n){const a=new Map,s=[{slug:t,distance:0}];let r=0;for(;r<s.length;){const t=s[r++],i=e.nodes.get(t.slug);i&&i[n].forEach(e=>{a.has(e)||(a.set(e,t.distance+1),s.push({slug:e,distance:t.distance+1}))})}return a}function L(e){const t=function(e,t,n){const a=window.__DEPENDENCY_DATA__;if(k(a)){const e={};return Object.entries(a.dependencies).forEach(([t,n])=>{const a=n,s=a.vulnerabilitySeverity||a.vulnerabilityHighest||a.highestSeverity||"none",r=String(s).trim().toLowerCase();let i="none";"critical"===r||"high"===r?i="high":"moderate"!==r&&"medium"!==r||(i="moderate"),e[t]={slug:String(a.slug||t),name:String(a.name||t),version:String(a.version||""),dependencies:Array.isArray(a.dependencies)?a.dependencies.map(e=>String(e)):[],license:String(a.license||"Unknown"),vulnerabilityCount:Number(a.vulnerabilityCount||0),vulnerabilitySeverity:i,isDevOnly:Boolean(a.isDevOnly),workspaceOrigins:Array.isArray(a.workspaceOrigins)?a.workspaceOrigins.map(e=>String(e)):[]}}),{workspaces:a.workspaces,dependencies:e}}const s={},r=Object.values(e.dependencies||{});r.forEach(e=>{const t=f(e.package.name,e.package.version);s[t]={slug:t,name:e.package.name,version:e.package.version,dependencies:[],license:b(e),vulnerabilityCount:w(e),vulnerabilitySeverity:C(e),isDevOnly:"dev"===e.usage.scope,workspaceOrigins:e.usage.origins.workspaces||[]}}),r.forEach(e=>{const a=f(e.package.name,e.package.version),r=e.graph.subDeps;if(!r)return;const i=new Set;["dep","dev","opt","peer"].forEach(e=>{const o=r[e];o&&Object.values(o).forEach(e=>{const r=e[1];if(!r)return;const o=n(r);o&&t.has(o)&&s[o]&&o!==a&&i.add(o)})}),s[a].dependencies=[...i]});const i=new Map,o=e=>{const t=i.get(e);if(t)return t;const n={directDependencies:new Set,directDevDependencies:new Set};return i.set(e,n),n};return o("root"),(e.workspaces.workspacePackages||[]).forEach(e=>{o(e.name)}),r.forEach(e=>{if(!e.usage.direct)return;const t=f(e.package.name,e.package.version);(e.usage.origins.workspaces?.length?e.usage.origins.workspaces:["root"]).forEach(n=>{const a=o(n);"dev"===e.usage.scope?a.directDevDependencies.add(t):a.directDependencies.add(t)})}),{workspaces:[...i.entries()].map(([e,t])=>({name:e,directDependencies:[...t.directDependencies],directDevDependencies:[...t.directDevDependencies]})).sort((e,t)=>e.name.localeCompare(t.name)),dependencies:s}}(e.report,e.knownDepKeys,e.resolveDepKey),n=new Map(t.workspaces.map(e=>[e.name,e])),a=new Map,s=new Map;Object.values(t.dependencies).forEach(e=>{const n=(e.dependencies||[]).filter(n=>n!==e.slug&&Boolean(t.dependencies[n]));s.set(e.slug,n),n.forEach(t=>{const n=a.get(t)||[];n.push(e.slug),a.set(t,n)})});let h=null,m="",L=null,I=null,M=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,X=new Set,N=new Set,T=null,j=1,R=0,V=0,\$=1,H=.1,O=0,F=0,W=null,U=null,G=!1,_=!0,q=0,z=Math.max(1,Math.floor(window.devicePixelRatio||1)),K=1,J=1,Z=50;const Q={down:!1,moved:!1,startX:0,startY:0,startPanX:0,startPanY:0},ee={active:!1,startX1:0,startY1:0,startX2:0,startY2:0,startPanX:0,startPanY:0,startDist:0,startZoom:0,anchorX:null,anchorY:null},te={active:!1,velocityX:0,velocityY:0,lastSampleX:0,lastSampleY:0,lastSampleTime:0,lastFrameTime:0},ne=e.canvas.getContext("2d"),ae=Boolean(ne);let se=!1,re=!1,ie=!1,oe=null,ce=null,le=null,de=!1;const ue="function"==typeof window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null;let pe={runtime:"#10b981",runtimeHighlight:"#34d399",dev:"#f59e0b",devHighlight:"#fcd34d",transitive:"#06b6d4",transitiveHighlight:"#67e8f9",edge:"#64748b",highlight:"#22d3ee",muted:"#64748b",ringHigh:"#ef4444",ringModerate:"#f59e0b",label:"#e8edf5",backgroundPrimary:"#0c1222"};function he(){const e=p("--graph-direct-runtime")||"#10b981",t=p("--graph-direct-dev")||"#f59e0b",n=p("--graph-transitive")||"#06b6d4";pe={runtime:e,runtimeHighlight:u(e,.2,"#34d399"),dev:t,devHighlight:u(t,.28,"#fcd34d"),transitive:n,transitiveHighlight:u(n,.38,"#67e8f9"),edge:p("--graph-edge")||"#64748b",highlight:p("--graph-highlight")||"#22d3ee",muted:p("--graph-muted")||"#64748b",ringHigh:p("--graph-vuln-high")||"#ef4444",ringModerate:p("--graph-vuln-medium")||"#f59e0b",label:p("--text-primary")||"#e8edf5",backgroundPrimary:p("--bg-primary")||"#0c1222"}}function ge(){if(de)return;de=!0,console.warn("Dependency Radar: unable to initialize 2D canvas; graph rendering disabled."),e.controlsRoot.classList.add("hidden"),e.workspaceWrap.classList.add("hidden"),e.canvas.style.display="none";const t=document.createElement("div");t.className="empty-state";const n=document.createElement("div");n.className="empty-state-text",n.textContent="Graph view is unavailable in this browser context.",t.appendChild(n),e.canvasHost.appendChild(t)}function me(e){return(e-R)/j}function ve(e){return(e-V)/j}function fe(e,t){if(!h)return{x:e,y:t};const n=h.bounds.minX-120,a=h.bounds.maxX+120,s=h.bounds.minY-90,r=h.bounds.maxY+90,i=Math.min(.22*K,220),c=Math.min(.22*J,180),l=i-a*j,d=K-i-n*j,u=c-r*j,p=J-c-s*j;return{x:l>d? .5*(l+d):o(e,l,d),y:u>p? .5*(u+p):o(t,u,p)}}function ye(e,t){const n=fe(e,t);R=n.x,V=n.y}function ke(){W=null,U=null}function be(e,t,n){Ee(),ke();const a=o(e,H,r),s=me(t),i=ve(n);j=a,ye(t-s*j,n-i*j),_=!0,ze()}function we(e,t){Ee(),ke(),ye(R+e,V+t),_=!0,ze()}function Ce(){return!ue?.matches}function Ee(){te.active=!1,te.velocityX=0,te.velocityY=0,te.lastFrameTime=0}function xe(e,t,n){te.lastSampleX=e,te.lastSampleY=t,te.lastSampleTime=n}function Se(e,t,n){const a=n-te.lastSampleTime;if(a<=0)return void xe(e,t,n);const s=(e-te.lastSampleX)/a,r=(t-te.lastSampleY)/a;te.velocityX+=.22*(s-te.velocityX),te.velocityY+=.22*(r-te.velocityY),xe(e,t,n)}function Le(){Ce()?Math.hypot(te.velocityX,te.velocityY)<.08?Ee():(te.active=!0,te.lastFrameTime=performance.now(),Ve(!1),ze()):Ee()}function Ie(){const t=e.canvasHost.getBoundingClientRect();K=Math.max(1,Math.floor(t.width)),J=Math.max(1,Math.floor(t.height)),z=Math.max(1,Math.floor(window.devicePixelRatio||1)),e.canvas.width=K*z,e.canvas.height=J*z,e.canvas.style.width=\`\${K}px\`,e.canvas.style.height=\`\${J}px\`;const n=e.canvasHost.querySelector(".graph-overlay-top");Z=n?Math.ceil(n.getBoundingClientRect().height):50,e.canvasHost.style.setProperty("--graph-toolbar-height",\`\${Z}px\`),_=!0,ze()}function Me(){if(!h)return;const e=h.bounds;let t=e.maxX;ne&&(ne.save(),ne.font=i,h.nodes.forEach(e=>{const n=d(e);if(!n)return;const a=ne.measureText(n).width;t=Math.max(t,e.baseX+e.radius+6+a)}),ne.restore());const n=Math.max(1,e.maxY-e.minY),a=Math.max(1,K-32),s=Math.max(1,J-Z-24),c=a/Math.max(1,t-e.minX),l=s/n;\$=o(Math.min(c,l),.05,r),H=o(.64*\$,.05,r),O=16+.5*(a-Math.max(1,t-e.minX)*\$)-e.minX*\$,F=Z+12+.5*(s-n*\$)-e.minY*\$}function Pe(t,n){if(!h)return null;const a=e.canvas.getBoundingClientRect();if(t<a.left||t>a.right||n<a.top||n>a.bottom)return null;const s=me(t-a.left),r=ve(n-a.top);let i=null,o=1/0;return h.nodes.forEach(e=>{const t=s-e.renderX,n=r-e.renderY,a=Math.sqrt(t*t+n*n);a<=e.renderRadius+5&&a<o&&(o=a,i=e)}),i}function Be(t){e.canvas.classList.toggle("is-clickable",t&&!Q.down&&!ee.active)}function De(t=!1){Be(!1),t&&e.canvas.classList.remove("is-panning")}function Ae(e,t){const n=Pe(e,t);return He(n?n.slug:null),Be(Boolean(n)),n}function Ye(e){const r=n.get(e);if(!r)return null;const i=new Set(r.directDependencies.filter(e=>Boolean(t.dependencies[e]))),o=new Set(r.directDevDependencies.filter(e=>Boolean(t.dependencies[e]))),d=new Set([...i,...o]);0===d.size&&Object.keys(t.dependencies).filter(e=>0===(a.get(e)||[]).length).slice(0,40).forEach(e=>{d.add(e)});const u=new Set,p=[...d];let h=0;for(;h<p.length;){const e=p[h++];e&&(u.has(e)||t.dependencies[e]&&(u.add(e),(s.get(e)||[]).forEach(e=>{u.has(e)||p.push(e)})))}if(0===u.size)return null;const g=new Map;u.forEach(e=>{const n=i.has(e)?"direct-runtime":o.has(e)?"direct-dev":"transitive",a=Array.from(t.dependencies[e].name);g.set(e,{slug:e,ref:t.dependencies[e],labelGraphemes:a,parents:new Set,children:new Set,depth:Number.POSITIVE_INFINITY,order:0,amplification:0,kind:n,baseX:0,baseY:0,targetX:0,targetY:0,renderX:0,renderY:0,radius:8,targetRadius:8,renderRadius:8,targetLabelChars:c(a),renderLabelChars:l(a)})}),g.forEach(e=>{(a.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.parents.add(t)}),(s.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.children.add(t)})});const m=[];for(d.forEach(e=>{const t=g.get(e);t&&(t.depth=0,m.push(e))});m.length>0;){const e=m.shift();if(!e)continue;const t=g.get(e);t&&t.children.forEach(e=>{const n=g.get(e);if(!n)return;const a=t.depth+1;a>=n.depth||(n.depth=a,m.push(e))})}g.forEach(e=>{if(Number.isFinite(e.depth))return;let t=Number.POSITIVE_INFINITY;e.parents.forEach(e=>{const n=g.get(e);n&&Number.isFinite(n.depth)&&(t=Math.min(t,n.depth+1))}),e.depth=Number.isFinite(t)?t:0});const v=[...g.values()].reduce((e,t)=>Math.max(e,t.depth),0),f=Array.from({length:v+1},()=>[]);g.forEach(e=>{f[e.depth].push(e.slug)});const y=[];g.forEach(e=>{e.children.forEach(t=>{y.push({from:e.slug,to:t,direct:0===e.depth})})});const k={workspaceName:e,nodes:g,edges:y,layers:f,directRuntime:i,directDev:o,directAll:new Set([...i,...o]),bounds:{minX:0,maxX:1,minY:0,maxY:1}};return Xe(k),Ne(k),k}function Xe(e){e.nodes.forEach(e=>{e.amplification=0}),e.nodes.forEach(t=>{if(0!==t.depth)return;if(!e.directAll.has(t.slug))return;const n=new Set,a=[...t.children];for(;a.length>0;){const s=a.pop();if(!s)continue;if(s===t.slug)continue;if(n.has(s))continue;n.add(s);const r=e.nodes.get(s);r&&r.children.forEach(e=>{n.has(e)||a.push(e)})}t.amplification=n.size})}function Ne(e){const t=new Map;e.layers.forEach((n,a)=>{0===a?n.sort((t,n)=>{const a=e.nodes.get(t),s=e.nodes.get(n);if(!a&&!s)return 0;if(!a)return 1;if(!s)return-1;if(a.amplification!==s.amplification)return s.amplification-a.amplification;if(a.kind!==s.kind){if("direct-runtime"===a.kind)return-1;if("direct-runtime"===s.kind)return 1}return a.ref.name.localeCompare(s.ref.name)}):n.sort((n,a)=>{const s=e.nodes.get(n),r=e.nodes.get(a);if(!s&&!r)return 0;if(!s)return 1;if(!r)return-1;const i=(()=>{let e=0,n=0;return s.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})(),o=(()=>{let e=0,n=0;return r.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})();return i!==o?i-o:s.ref.name.localeCompare(r.ref.name)}),n.forEach((e,n)=>{t.set(e,n)})});const n=e.layers.reduce((e,t)=>Math.max(e,t.length),1);e.bounds={minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY},e.layers.forEach((t,a)=>{const s=Math.max(0,43*(t.length-1)),r=64+.5*(43*n-s);t.forEach((t,n)=>{const s=e.nodes.get(t);if(!s)return;s.order=n,s.baseX=96+240*a,s.baseY=r+43*n,s.targetX=s.baseX,s.targetY=s.baseY,s.renderX=s.baseX,s.renderY=s.baseY;const i=.55*Math.log(s.children.size+s.parents.size+1),o=0===s.depth&&e.directAll.has(s.slug)?1.05*Math.log(s.amplification+1):0;s.radius=6.7+i+o,s.targetRadius=s.radius,s.renderRadius=s.radius,s.targetLabelChars=c(s.labelGraphemes),s.renderLabelChars=l(s.labelGraphemes),e.bounds.minX=Math.min(e.bounds.minX,s.baseX),e.bounds.maxX=Math.max(e.bounds.maxX,s.baseX),e.bounds.minY=Math.min(e.bounds.minY,s.baseY),e.bounds.maxY=Math.max(e.bounds.maxY,s.baseY)})}),Number.isFinite(e.bounds.minX)||(e.bounds={minX:0,maxX:1,minY:0,maxY:1})}function Te(e,t){if(!h)return;const n=o(Math.max(j,1.35*\$),H,r);j+=(n-j)*(ue?.matches?1:.35),function(e,t){const n=fe(e,t);W=n.x,U=n.y}(.46*K-e*j,.5*J-t*j)}function je(e){if(!h||!h.nodes.has(e))return;Ee(),L=e;const t=E(h,e),n=x(h,e);M=new Set([e]),t.forEach(e=>{M.add(e)}),n.forEach(e=>{M.add(e)}),P=new Set;const a=[e],s=new Set([e]);for(;a.length>0;){const e=a.pop();if(!e)continue;const t=h.nodes.get(e);t&&t.parents.forEach(t=>{P.add(y(t,e)),s.has(t)||(s.add(t),a.push(t))})}const r=[e],i=new Set([e]);for(;r.length>0;){const e=r.pop();if(!e)continue;const t=h.nodes.get(e);t&&t.children.forEach(t=>{P.add(y(e,t)),i.has(t)||(i.add(t),r.push(t))})}B=new Set(M);const c=h.nodes.get(e);c.parents.forEach(e=>{B.add(e)}),c.children.forEach(e=>{B.add(e)});const l=null===A||null===Y,d=!l&&Boolean(T)&&M.has(T);!l&&d||(A=c.renderX,Y=c.renderY),D=function(e,t,n,a){const s=new Map,r=S(e,t,"parents"),i=S(e,t,"children"),c=new Map;return s.set(t,{x:n,y:a}),M.forEach(a=>{if(a===t)return;const s=e.nodes.get(a);if(!s)return;const o=r.get(a),l=i.get(a);let d=0;"number"==typeof o&&("number"!=typeof l||o<=l)?d=-o:"number"==typeof l&&(d=l),0===d&&(d=s.baseX<n?-1:1);const u=c.get(d)||[];u.push(s),c.set(d,u)}),c.forEach((e,t)=>{e.sort((e,n)=>{const a=t<0?r.get(e.slug)||0:i.get(e.slug)||0,s=t<0?r.get(n.slug)||0:i.get(n.slug)||0;return a!==s?a-s:e.baseY!==n.baseY?e.baseY-n.baseY:e.ref.name.localeCompare(n.ref.name)});const c=o(760/Math.max(1,e.length-1),34,54),l=a-(e.length-1)*c*.5;e.forEach((e,a)=>{const r=170*(1+.78*Math.max(0,Math.abs(t)-1));s.set(e.slug,{x:n+Math.sign(t)*r,y:l+a*c})})}),s}(h,e,A??c.renderX,Y??c.renderY),Te(A??c.renderX,Y??c.renderY),_=!0,ze()}function Re(){L=null,M=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,ke(),_=!0,ze()}function Ve(e=!0){I=null,X=new Set,N=new Set,e&&(_=!0,ze())}function \$e(){if(!h)return;const e=L&&h.nodes.get(L)||null;h.nodes.forEach(t=>{t.targetRadius=function(e){const t=L===e.slug,n=M.has(e.slug);let a=e.radius;t?a*=1.85:L&&n?a*=1.22:L&&!n?a*=.84:I&&X.has(e.slug)?a*=1.1:I&&(a*=.9);return a}(t),t.targetLabelChars=c(t.labelGraphemes,Boolean(L)&&M.has(t.slug)||!L&&Boolean(I)&&X.has(t.slug));const n=D.get(t.slug);if(e&&n)return t.targetX=n.x,void(t.targetY=n.y);if(!e||!B.has(t.slug))return t.targetX=t.baseX,void(t.targetY=t.baseY);const a=t.baseX-e.baseX,s=t.baseY-e.baseY,r=1+120/(Math.sqrt(a*a+s*s)+1);t.targetX=e.baseX+a*r,t.targetY=e.baseY+s*r})}function He(e){if(L)return;if(I=e,X=new Set,N=new Set,!h||!e||!h.nodes.has(e))return _=!0,void ze();const t=E(h,e),n=x(h,e);X=new Set([e]),t.forEach(e=>{X.add(e)}),n.forEach(e=>{X.add(e)});const a=h.nodes.get(e);a&&(a.parents.forEach(e=>{X.add(e)}),a.children.forEach(e=>{X.add(e)})),h.edges.forEach(e=>{X.has(e.from)&&X.has(e.to)&&N.add(y(e.from,e.to))}),_=!0,ze()}function Oe(t){if(!h)return;const n=h.nodes.get(t);if(!n)return;const a=0===n.depth&&h.directAll.has(n.slug);T=t,e.popoverName.textContent=n.ref.name,e.popoverVersion.textContent=\`Version: \${n.ref.version}\`,e.popoverLicense.textContent=\`License: \${n.ref.license||"Unknown"}\`,e.popoverVulns.textContent=\`Vulnerabilities: \${n.ref.vulnerabilityCount||0}\`,e.popoverAmplification.textContent=a?\`Amplification: \${n.amplification}\`:\`Dependencies: \${n.children.size} • Dependents: \${n.parents.size}\`,e.popover.hidden=!1,We()}function Fe(){T=null,e.popover.hidden=!0}function We(){if(!h||!T||e.popover.hidden)return;const t=h.nodes.get(T);if(!t)return void Fe();const n=t.renderX*j+R,a=t.renderY*j+V,s=e.canvasHost.getBoundingClientRect(),r=e.popover.getBoundingClientRect(),i=Math.max(8,s.width-r.width-8),c=Math.max(8,s.height-r.height-8),l=o(n+14,8,i),d=o(a+14,8,c);e.popover.style.left=\`\${l}px\`,e.popover.style.top=\`\${d}px\`}function Ue(e){return L?M.has(e)?1:.14:I?X.has(e)?1:.16:.95}function Ge(){if(!ne)return;if(ne.setTransform(z,0,0,z,0,0),ne.clearRect(0,0,K,J),!h)return;const e=h,t=me(0)-80,n=me(K)+80,a=ve(0)-80,s=ve(J)+80;ne.setTransform(z*j,0,0,z*j,z*R,z*V);const r=pe.runtime,c=pe.dev,l=pe.transitive,u=pe.edge,p=pe.highlight,m=pe.muted,f=pe.ringHigh,k=pe.ringModerate,b=pe.label,w=pe.backgroundPrimary,C=new Set;e.nodes.forEach(e=>{const r=Math.max(e.radius,e.renderRadius);e.renderX+r>=t&&e.renderX-r<=n&&e.renderY+r>=a&&e.renderY-r<=s&&C.add(e.slug)});const E=[];let x=0;e.nodes.forEach(e=>{if(!C.has(e.slug))return;let t=0;L===e.slug?t=2:(M.has(e.slug)||X.has(e.slug))&&(t=1),E.push({node:e,priority:t,order:x++})}),E.sort((e,t)=>e.priority-t.priority||e.order-t.order);const S=Math.max(0,e.layers.length-1),B={depthNodeIndex:g(e),maxDepth:S,sameColumnXThreshold:6,minDetourVerticalSpan:80,detourInset:14,detourNodeClearance:26,paddingX:96,layerGap:240,edgeCurve:.2},D=[];e.edges.forEach(t=>{const n=e.nodes.get(t.from),a=e.nodes.get(t.to);if(!n||!a)return;if(!C.has(n.slug)&&!C.has(a.slug))return;const s=y(t.from,t.to);D.push({from:n,to:a,highlighted:P.has(s)||!L&&N.has(s),span:Math.abs(a.depth-n.depth)})}),D.sort((e,t)=>t.span-e.span),ne.globalCompositeOperation="source-over",ne.strokeStyle=L||I?m:u,ne.lineWidth=1.05,ne.globalAlpha=L||I? .04*o((j-.35)/.9,.75,1):.25*o((j-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted||v(ne,e,B,Boolean(L))}),ne.stroke(),ne.globalCompositeOperation="lighter",ne.strokeStyle=p,ne.lineWidth=1.2,ne.globalAlpha=.36*o((j-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted&&v(ne,e,B,Boolean(L))}),ne.stroke(),ne.globalCompositeOperation="source-over";const A=e=>{const t=L===e.slug,n=e.renderRadius;ne.globalAlpha=1,ne.fillStyle=w,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),ne.globalAlpha=Ue(e.slug);const a=ne.createRadialGradient(e.renderX-.3*n,e.renderY-.3*n,0,e.renderX,e.renderY,1.2*n);"direct-runtime"===e.kind?(a.addColorStop(0,pe.runtimeHighlight),a.addColorStop(1,r)):"direct-dev"===e.kind?(a.addColorStop(0,pe.devHighlight),a.addColorStop(1,c)):(a.addColorStop(0,pe.transitiveHighlight),a.addColorStop(1,l)),ne.fillStyle=a,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),t&&(ne.globalAlpha=.95,ne.strokeStyle=p,ne.lineWidth=1.5,ne.beginPath(),ne.arc(e.renderX,e.renderY,n+4,0,2*Math.PI),ne.stroke())},Y=e=>{if(!e.ref.vulnerabilityCount||e.ref.vulnerabilityCount<=0)return;if("none"===e.ref.vulnerabilitySeverity)return;const t=e.renderRadius,n="high"===e.ref.vulnerabilitySeverity?f:k;var a;ne.save(),ne.translate(e.renderX,e.renderY),ne.globalAlpha=(a=e.slug,L?M.has(a)? .78:.11:I?X.has(a)? .76:.12:.8),ne.strokeStyle=n;const s=t/e.radius,r=t/3*1.2/12,i=1.2*r+3*(s-1),o=Math.max(.5*r,.15),c=Math.max(1*r,.3),l=Math.max(3*r,.8),d=Math.max(1*r,.3),u=Math.max(.5*r,.15),p=t+(2+6*(s-1))+o/2,h=p+o/2+i+c/2,g=h+c/2+i+l/2,m=g+l/2+i+d/2,v=m+d/2+i+u/2;ne.setLineDash([]),ne.lineWidth=u,ne.beginPath(),ne.arc(0,0,v,0,2*Math.PI),ne.stroke(),ne.lineWidth=d,ne.beginPath(),ne.arc(0,0,m,0,2*Math.PI),ne.stroke(),ne.lineWidth=l,ne.beginPath(),ne.arc(0,0,g,0,2*Math.PI),ne.stroke(),ne.lineWidth=c,ne.beginPath(),ne.arc(0,0,h,0,2*Math.PI),ne.stroke(),ne.lineWidth=o,ne.beginPath(),ne.arc(0,0,p,0,2*Math.PI),ne.stroke(),ne.restore()};for(const i of[0,1,2])E.forEach(({node:e,priority:t})=>{t===i&&A(e)}),E.forEach(({node:e,priority:t})=>{t===i&&Y(e)});ne.textBaseline="middle",ne.font=i,ne.fillStyle=b,E.forEach(({node:e})=>{(e=>{const t=d(e);t&&(ne.globalAlpha=Ue(e.slug),ne.fillText(t,e.renderX+e.renderRadius+6,e.renderY))})(e)}),ne.globalAlpha=1,We()}function _e(){if(!G)return void(q=0);\$e();const e=function(){if(!h)return!1;let e=!1;const t=ue?.matches;return h.nodes.forEach(n=>{if(t)return n.renderX=n.targetX,n.renderY=n.targetY,n.renderRadius=n.targetRadius,void(n.renderLabelChars=n.targetLabelChars);const a=L? .18:.15;n.renderX+=(n.targetX-n.renderX)*a,n.renderY+=(n.targetY-n.renderY)*a,n.renderRadius+=.18*(n.targetRadius-n.renderRadius),n.renderLabelChars+=.32*(n.targetLabelChars-n.renderLabelChars),Math.abs(n.targetX-n.renderX)<.06&&Math.abs(n.targetY-n.renderY)<.06&&Math.abs(n.targetRadius-n.renderRadius)<.04&&Math.abs(n.targetLabelChars-n.renderLabelChars)<.12||(e=!0)}),e}(),t=function(e){if(!te.active)return!1;if(!Ce())return Ee(),!1;const t=o(e-te.lastFrameTime||16,1,32);te.lastFrameTime=e,ye(R+te.velocityX*t,V+te.velocityY*t);const n=Math.exp(-.0042*t);return te.velocityX*=n,te.velocityY*=n,_=!0,!(Math.hypot(te.velocityX,te.velocityY)<.02&&(Ee(),1))}(performance.now()),n=null!==W&&null!==U&&(ue?.matches?(ye(W,U),ke(),_=!0,!1):(R+=.12*(W-R),V+=.12*(U-V),ye(R,V),Math.abs((W??R)-R)<.35&&Math.abs((U??V)-V)<.35?(ye(W,U),ke(),_=!0,!1):(_=!0,!0)));if(_||e||t||n)return Ge(),_=!1,void(q=G&&(_||e||t||n)?window.requestAnimationFrame(_e):0);q=0}function qe(){G&&!q&&_&&(q=window.requestAnimationFrame(_e))}function ze(){_=!0,G&&qe()}function Ke(e){const t=Ye(e);t&&(Ee(),m=e,h=t,Re(),Fe(),I=null,X=new Set,N=new Set,De(!0),h&&(Ee(),ke(),Me(),j=\$,ye(O,F)),_=!0,ze())}function Je(t){0===t.button&&(Ee(),ke(),Q.down=!0,Q.moved=!1,Q.startX=t.clientX,Q.startY=t.clientY,Q.startPanX=R,Q.startPanY=V,xe(t.clientX,t.clientY,t.timeStamp),De(),e.canvas.classList.add("is-panning"))}function Ze(e){if(!Q.down)return void Ae(e.clientX,e.clientY);const t=e.clientX-Q.startX,n=e.clientY-Q.startY;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(Q.startPanX+t,Q.startPanY+n),Se(e.clientX,e.clientY,e.timeStamp),ze()}function Qe(t){if(!Q.down)return;e.canvas.classList.remove("is-panning");const n=Q.moved;if(Q.down=!1,Q.moved=!1,n)return Le(),te.active?void Be(!1):void Ae(t.clientX,t.clientY);const a=Ae(t.clientX,t.clientY);if(!a)return Ve(!1),Re(),void Fe();je(a.slug),Oe(a.slug)}function et(t){if(!e.canvasHost.contains(t.target))return;t.preventDefault(),Ee();const n=e.canvas.getBoundingClientRect(),a=t.clientX-n.left,s=t.clientY-n.top,r=t.ctrlKey||t.metaKey? .015*t.deltaY:.002*t.deltaY,i=Math.exp(-r);be(j*i,a,s)}function tt(t){if(0===t.touches.length)return;t.preventDefault(),Ee(),ke(),De();const n=e.canvas.getBoundingClientRect();if(1===t.touches.length)ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startPanX=R,ee.startPanY=V,xe(t.touches[0].clientX,t.touches[0].clientY,t.timeStamp),e.canvas.classList.add("is-panning");else if(2===t.touches.length){ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startX2=t.touches[1].clientX,ee.startY2=t.touches[1].clientY;const e=ee.startX2-ee.startX1,a=ee.startY2-ee.startY1;ee.startDist=Math.sqrt(e*e+a*a),ee.startZoom=j;const s=(ee.startX1+ee.startX2)/2,r=(ee.startY1+ee.startY2)/2,i=s-n.left,o=r-n.top;ee.anchorX=i,ee.anchorY=o}}function nt(e){if(ee.active)if(e.preventDefault(),1===e.touches.length){const t=e.touches[0].clientX-ee.startX1,n=e.touches[0].clientY-ee.startY1;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(ee.startPanX+t,ee.startPanY+n),Se(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp),ze()}else if(2===e.touches.length){Ee(),Q.moved=!0;const t=e.touches[0].clientX,n=e.touches[0].clientY,a=e.touches[1].clientX-t,s=e.touches[1].clientY-n,r=Math.sqrt(a*a+s*s);if(ee.startDist>0){const e=r/ee.startDist;be(ee.startZoom*e,ee.anchorX??K/2,ee.anchorY??J/2)}}}function at(e){if(ee.active){if(e.preventDefault(),"touchcancel"===e.type)return Ee(),De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,void(Q.moved=!1);if(0===e.touches.length){if(De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,Q.moved||1!==e.changedTouches.length)Q.moved&&Le();else{const t=Pe(e.changedTouches[0].clientX,e.changedTouches[0].clientY);t?(je(t.slug),Oe(t.slug)):(Ve(!1),Re(),Fe())}Q.moved=!1}else 1===e.touches.length&&(ee.startX1=e.touches[0].clientX,ee.startY1=e.touches[0].clientY,ee.startPanX=R,ee.startPanY=V,xe(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp))}}function st(){He(null),De()}function rt(t){if(!G)return;const n=t.target;e.popover.hidden||e.popover.contains(n)||e.canvasHost.contains(n)||Fe()}function it(e){const t=e.target.closest("button[data-action]");if(!t)return;const n=t.dataset.action;n&&("zoom-in"!==n?"zoom-out"!==n?"pan-left"!==n?"pan-right"!==n?"pan-up"!==n?"pan-down"!==n?"reset"===n&&(Ee(),j=\$,ye(O,F),Re(),Fe(),ze()):we(0,52):we(0,-52):we(52,0):we(-52,0):be(j/1.18,.5*K,.5*J):be(1.18*j,.5*K,.5*J))}function ot(){T&&e.onOpenList(T)}function ct(){Ke(e.workspaceSelect.value)}function lt(){G&&(Ie(),K<=1||J<=1||(Me(),j=o(j,H,r),ye(R,V),ze()))}function dt(){ie||(e.workspaceSelect.addEventListener("change",ct),ie=!0),re||(e.controlsRoot.addEventListener("click",it),e.popoverOpenButton.addEventListener("click",ot),re=!0)}return{initGraphView:function(){const a=t.workspaces.length?t.workspaces:[{name:"root",directDependencies:[],directDevDependencies:[]}],s=a.find(e=>"root"===e.name),r=s?[s,...a.filter(e=>"root"!==e.name)]:a;e.workspaceSelect.textContent="",r.forEach((t,n)=>{const a=document.createElement("option");if(a.value=t.name,a.textContent="root"===t.name?"Workspace root":t.name,e.workspaceSelect.appendChild(a),"root"===t.name&&r.length>1&&0===n){const t=document.createElement("option");t.disabled=!0,t.textContent="──────────────",e.workspaceSelect.appendChild(t)}}),e.workspaceWrap.classList.toggle("hidden",a.length<=1),n.has("root")||1!==a.length||n.set("root",a[0]),m=r[0].name,e.workspaceSelect.value=m,he(),function(){if(oe&&oe.disconnect(),oe=new MutationObserver(()=>{he(),ze()}),oe.observe(document.documentElement,{attributes:!0,attributeFilter:["class","data-theme"]}),ce&&(ce.disconnect(),ce=null),le&&(window.removeEventListener("resize",le),le=null),"undefined"!=typeof ResizeObserver)return ce=new ResizeObserver(lt),void ce.observe(e.canvasHost);le=lt,window.addEventListener("resize",le)}(),dt(),ae?(Ie(),Ke(m)):ge()},buildWorkspaceGraph:Ye,computeAmplification:Xe,layoutGraph:Ne,renderLoop:qe,applyFocus:je,clearFocus:Re,showPopover:Oe,hidePopover:Fe,switchWorkspace:Ke,setActive:function(t){if(G=t,G)return ae?(!se&&ae&&(e.canvas.addEventListener("mousedown",Je),window.addEventListener("mousemove",Ze),window.addEventListener("mouseup",Qe),e.canvas.addEventListener("wheel",et,{passive:!1}),e.canvas.addEventListener("touchstart",tt,{passive:!1}),window.addEventListener("touchmove",nt,{passive:!1}),window.addEventListener("touchend",at,{passive:!1}),window.addEventListener("touchcancel",at,{passive:!1}),e.canvas.addEventListener("mouseleave",st),document.addEventListener("mousedown",rt),se=!0),Ie(),K>1&&J>1&&(Me(),j=o(j,H,r),ye(R,V)),qe(),void ze()):void ge();se&&(e.canvas.removeEventListener("mousedown",Je),window.removeEventListener("mousemove",Ze),window.removeEventListener("mouseup",Qe),e.canvas.removeEventListener("wheel",et),e.canvas.removeEventListener("touchstart",tt),window.removeEventListener("touchmove",nt),window.removeEventListener("touchend",at),window.removeEventListener("touchcancel",at),e.canvas.removeEventListener("mouseleave",st),document.removeEventListener("mousedown",rt),De(!0),Q.down=!1,Q.moved=!1,ee.active=!1,ee.anchorX=null,ee.anchorY=null,Ee(),se=!1),Ee(),q&&(window.cancelAnimationFrame(q),q=0)},requestRender:ze}}var I={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]},M={"network-access":"Accesses the network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"},P={"bundled-dependencies":"Declares bundled dependencies","embedded-shrinkwrap":"Contains embedded npm-shrinkwrap.json"},B={"recent-package":"Recently created package","recent-version":"Recently published installed version","low-release-history":"Low release history","reactivated-package":"Reactivated after dormancy","old-major-new-patch":"Recent patch on older major line"};function D(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function A(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function Y(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function X(e){return e?.highest||"none"}function N(e){return e&&e.risk||"green"}var T={permissive:"green",weakCopyleft:"amber",strongCopyleft:"red",unknown:"gray"},j={none:0,low:1,moderate:2,high:3,critical:4},R=[{id:"type",label:"Type",sortKey:"type",getValue:e=>e.usage.direct?"Dependency":"Sub-Dependency",getTone:e=>e.usage.direct?"green":"amber",sortFn:(e,t)=>e.usage.direct===t.usage.direct?0:e.usage.direct?-1:1},{id:"scope",label:"Scope",sortKey:"scope",getValue:e=>{return"runtime"===(t=e.usage.scope)?"Runtime":"dev"===t?"Dev":"optional"===t?"Optional":"peer"===t?"Peer":t;var t},getTone:e=>"runtime"===e.usage.scope?"green":"dev"===e.usage.scope||"optional"===e.usage.scope?"amber":"gray",sortFn:(e,t)=>e.usage.scope.localeCompare(t.usage.scope)},{id:"license",label:"License",sortKey:"license",getValue:e=>{const t=A(e),n=t.isInferred?\`\${t.value} (inferred)\`:t.value;return"mismatch"===e.compliance.license.status?\`\${n} *\`:n},getTone:e=>{const t=function(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(I))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}(A(e).value);return T[t]},sortFn:(e,t)=>{const n=A(e).value,a=A(t).value;return n.localeCompare(a)}},{id:"vulns",label:"Vulnerabilities",sortKey:"severity",getValue:e=>D(X(Y(e).summary)),getTone:e=>Y(e).summary.risk,sortFn:(e,t)=>j[X(Y(t).summary)]-j[X(Y(e).summary)]},{id:"install",label:"Install",sortKey:"install",getValue:e=>{return(t=e.execution)?D(t.risk||"low"):"Low";var t},getTone:e=>N(e.execution),sortFn:(e,t)=>{const n={green:0,amber:1,red:2},a=N(e.execution),s=N(t.execution);return n[a]-n[s]}},{id:"maintenance",label:"Maintenance",sortKey:"maintenance",getValue:e=>\$(e.maintenance?.status),getTone:e=>{return t=e.maintenance?.status,"deprecated"===t||"archived"===t?"red":"unmaintained"===t||"stale"===t?"amber":"active"===t?"green":"gray";var t},sortFn:(e,t)=>H(t.maintenance?.status)-H(e.maintenance?.status)}],V={deprecated:"Deprecated",archived:"Archived",unmaintained:"Unmaintained",stale:"Stale",active:"Active",unknown:"—"};function \$(e){return e&&V[e]||"—"}function H(e){return e&&{deprecated:5,archived:4,unmaintained:3,stale:2,active:1}[e]||0}function O(e){const t=e.maintenance?.status;return"deprecated"===t||"archived"===t||"unmaintained"===t||"stale"===t}function F(e){return"green"!==e.compliance.licenseRisk}function W(e){return Boolean(e.upgrade.blocksNodeMajor||e.upgrade.blockers?.length)}var U=R.length;function G(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(I))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}function _(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function q(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}var z={none:0,low:1,moderate:2,high:3,critical:4};function K(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function J(e){return e?"Yes":"No"}function Z(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}function Q(e){return null!=e&&("string"==typeof e?e.trim().length>0:Array.isArray(e)?e.length>0:"object"!=typeof e||Object.keys(e).length>0)}function ee(e){return Array.isArray(e)?e.map(e=>ee(e)).join(", "):"boolean"==typeof e?e?"Yes":"No":"object"==typeof e&&null!==e?Object.entries(e).filter(([,e])=>Q(e)).map(([e,t])=>Z(e)+": "+ee(t)).join("<br>"):Z(String(e))}function te(e,t){return Q(t)?'<div class="metadata-row"><div class="metadata-row-label">'+Z(e)+'</div><div class="metadata-row-value">'+ee(t)+"</div></div>":""}function ne(e,t){const n=t.filter(Boolean);return 0===n.length?"":'<section class="metadata-section"><div class="metadata-section-title">'+Z(e)+'</div><div class="metadata-grid">'+n.join("")+"</div></section>"}function ae(e){const t=e.workspaces;if(!t||!t.enabled)return ne("Workspaces",[te("Enabled",!1),te("Type",t?.type)]);const n=t.workspacePackages||[],a=n.length?'<div class="metadata-list">'+n.map(e=>'<div class="metadata-list-item"><div class="metadata-row-value">'+Z(e.name)+'</div><div class="metadata-muted">'+Z(e.relativePath)+" · runtime "+Z(String(e.directExternal.runtime))+" · dev "+Z(String(e.directExternal.dev))+"</div></div>").join("")+"</div>":"";return ne("Workspaces",[te("Enabled",t.enabled),te("Type",t.type),te("Package count",t.packageCount),a?'<div class="metadata-row"><div class="metadata-row-label">Packages</div><div>'+a+"</div></div>":""])}function se(e){const t=e.supplyChain;if(!t)return"";const n=t.signatureAudit;return ne("Supply Chain",[te("Signals",t.signals?.length),n?te("Signature audit",{attempted:n.attempted,ok:n.ok,status:n.status,error:n.error}):""])}function re(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e}function ie(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function oe(e){return e.split(/[\\s-_]+/).map(e=>e?ie(e):e).join(" ")}function ce(e){return R.map(t=>{return n=t.label,a=t.getValue(e),'<div class="badge-card '+t.getTone(e)+'"><span class="badge-label">'+Z(n)+'</span><span class="badge-value">'+Z(a)+"</span></div>";var n,a}).join("")}function le(e,t){const n=R.map(n=>function(e,t,n,a){const s=n===e,r=s?a?" ▲":" ▼":"",i=s?a?" sorted-asc":" sorted-desc":"";return'<button type="button" class="column-header'+(s?" sorted":"")+i+'" data-sort="'+Z(e)+'"><span class="column-header-label">'+Z(t)+'</span><span class="sort-indicator">'+r+"</span></button>"}(n.sortKey,n.label,e,t)).join("");return'<div class="column-headers" style="--column-count: '+U+'">'+n+"</div>"}function de(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+Z(e)+"</span>",a+='<span class="kv-value">'+Z(String(t))+"</span>",n&&(a+='<span class="kv-hint">'+Z(n)+"</span>"),a+="</div>",a}function ue(e,t){return'<span class="kv-value risk-value"><span class="risk-dot '+t+'"></span>'+Z(String(e))+"</span>"}function pe(e,t="neutral"){return'<span class="status-chip '+t+'">'+Z(e)+"</span>"}function he(e,n,a){const s=t(n),r=e.execution?.risk||"green",i=e.upgrade.blocksNodeMajor||!!e.upgrade.blockers?.length;return'<div class="status-chip-strip">'+[pe(e.usage.direct?"Direct dependency":"Transitive dependency"),pe(re(e.usage.scope)),pe(s>0?"Vulnerability: "+oe(n.highest):"Vulnerability: None","green"===n.risk?"neutral":n.risk),pe("Licence: "+a,"green"===e.compliance.licenseRisk?"neutral":e.compliance.licenseRisk),pe("Install risk: "+Pe(r),"green"===r?"neutral":r),pe(i?"Upgrade blocker":"No upgrade blocker",i?"amber":"neutral")].join("")+"</div>"}function ge(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+Z(e)+"</span>",a+=t,n&&(a+='<span class="kv-hint">'+Z(n)+"</span>"),a+="</div>",a}function me(e,t){if(!e||0===e.length)return'<span class="kv-value">None</span>';const n=e.slice(0,t),a=e.length-t;let s='<div class="package-list">';return n.forEach(e=>{s+='<span class="package-tag">'+Z(e)+"</span>"}),a>0&&(s+='<span class="package-tag">+'+a+" more</span>"),s+="</div>",s}function ve(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{const t=Ee(e,n,a);i+=t?'<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(t))+'" data-dep-key="'+Z(t)+'" aria-label="Jump to dependency '+Z(t)+'">'+Z(e)+"</a>":'<span class="package-tag">'+Z(e)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function fe(e,t){return e+"@"+t}var ye=new WeakMap;function ke(e){const t=e.lastIndexOf("@npm:");if(t>0)return{name:e.slice(0,t),version:e.slice(t+1)};const n=e.lastIndexOf("@");return n<=0?null:{name:e.slice(0,n),version:e.slice(n+1)}}function be(e){return\`dep-\${e}\`}function we(e){const t=ye.get(e);if(t)return t;const n=new Map;return e.forEach(e=>{const t=ke(e);if(!t)return;const a=n.get(t.name)||[];a.push(e),n.set(t.name,a)}),ye.set(e,n),n}function Ce(e,t,n){const a=((n||we(t)).get(e)||[]).filter(e=>t.has(e));return 1===a.length?a[0]:null}function Ee(e,t,n){if(t.has(e))return e;const a=ke(e);if(!a)return Ce(e,t,n);if(a.version.startsWith("npm:")){const e=a.version.slice(4),n=a.name+(e.startsWith("@")?e:"@"+e);if(t.has(n))return n}return Ce(a.name,t,n)}function xe(e,t){if(t.has(e))return e;const n=ke(e);if(!n)return null;if(n.version.startsWith("npm:")){const e=n.version.slice(4),a=n.name+(e.startsWith("@")?e:"@"+e);if(t.has(a))return a}return null}function Se(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{if("string"==typeof e){const t=Ee(e,n,a);return t?void(i+='<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(t))+'" data-dep-key="'+Z(t)+'" aria-label="Jump to dependency '+Z(t)+'">'+Z(e)+"</a>"):void(i+='<span class="package-tag">'+Z(e)+"</span>")}const t=fe(e.name,e.version),s=e.name+"@"+e.version,r=Ee(t,n,a);i+=r?'<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(r))+'" data-dep-key="'+Z(r)+'" aria-label="Jump to dependency '+Z(r)+'">'+Z(s)+"</a>":'<span class="package-tag">'+Z(s)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function Le(e,t,n){const a=e.graph.subDeps;if(!a)return"";const s=[{title:"Dependencies",key:"dep"},{title:"Optional",key:"opt"},{title:"Peer",key:"peer"},{title:"Dev Dependencies",key:"dev"}];let r=0,i=0;for(const l of s){const e=a[l.key];if(e)for(const t of Object.values(e))r+=1,t[1]&&(i+=1)}if(0===r)return"";const o='<div class="declared-summary">Total: '+r+" • Installed: "+i+" • Not installed: "+(r-i)+"</div>",c=s.map(e=>{const s=a[e.key];if(!s||0===Object.keys(s).length)return"";let r=0,i=0;const o=Object.entries(s).sort(([e],[t])=>e.localeCompare(t)).map(([e,[a,s]])=>{r+=1,s&&(i+=1);const o='<div class="declared-name">'+Z(e)+"</div>",c='<div class="declared-range">'+Z(a)+"</div>",l=s?function(e,t,n){const a=Ee(e,t,n);return a?'<a class="status-pill installed root-package-link" href="#'+Z(be(a))+'" data-dep-key="'+Z(a)+'" aria-label="Jump to dependency '+Z(a)+'">Installed</a>':'<span class="status-pill installed">Installed</span>'}(s,t,n):'<span class="status-pill missing">Not installed</span>';return'<div class="declared-row">'+o+c+l+"</div>"}),c=i+" of "+r+" installed";return['<details class="declared-group">','<summary class="declared-group-summary"><span class="expand-icon" aria-hidden="true"></span><span class="declared-group-title">'+Z(e.title)+' <span class="declared-count">('+c+")</span></span></summary>",'<div class="declared-table">'+o.join("")+"</div>","</details>"].join("")}).filter(Boolean);return Ie("Declared Dependencies","Dependencies declared by this package",o+'<div class="declared-deps">'+c.join("")+"</div>")}function Ie(e,t,n){let a='<div class="section">';return a+='<div class="section-header">',a+='<span class="section-title">'+Z(e)+"</span>",t&&(a+='<span class="section-desc">'+Z(t)+"</span>"),a+="</div>",a+=n,a+="</div>",a}function Me(e,t,n,a){let s='<div class="subsection'+(a?" "+a:"")+'">';return s+='<div class="subsection-header">',s+='<span class="subsection-title">'+Z(e)+"</span>",n&&(s+='<span class="subsection-desc">'+Z(n)+"</span>"),s+="</div>",s+=t,s+="</div>",s}function Pe(e){return"red"===e?"High":"amber"===e?"Medium":"Low"}function Be(e){return e&&0!==e.length?Me("Supply chain source",'<div class="section-note">Shown only when lockfile source metadata is unusual or incomplete.</div><div class="kv-grid">'+e.map(e=>{return de({"git-dependency":"Git dependency source","file-dependency":"Local dependency source","non-registry-tarball":"Non-registry tarball","missing-integrity":"Missing lockfile integrity","unexpected-registry-host":"Unexpected registry host"}[t=e.type]||oe(t),e.source,e.detail);var t}).join("")+"</div>","Lockfile source signals","warning"):""}function De(e){if(!e)return;const t=e.trim();if(!t)return;const n=e=>e.replace(/\\.git\$/i,"");if(/^https?:\\/\\//i.test(t))return n(t);if(/^git\\+https?:\\/\\//i.test(t))return n(t.replace(/^git\\+/,""));if(/^git:\\/\\/github\\.com\\//i.test(t))return n(t.replace(/^git:\\/\\//i,"https://"));if(/^github:/i.test(t)){const e=t.slice(7).replace(/^\\/+/,"");return e?\`https://github.com/\${n(e)}\`:void 0}if(/^git@github\\.com:/i.test(t)){const e=t.slice(15);return e?\`https://github.com/\${n(e)}\`:void 0}return/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\$/.test(t)?\`https://github.com/\${n(t)}\`:void 0}function Ae(e,t){const n=De(e);if(!n)return;let a;try{a=new URL(n)}catch{return}if("github.com"!==a.hostname.toLowerCase())return;const s=a.pathname.split("/").filter(Boolean);if(s.length<2)return;const r=s[0],i=s[1].replace(/\\.git\$/i,"");return r&&i?\`https://github.com/\${r}/\${i}/blob/HEAD/\${t}\`:void 0}function Ye(e,t){return t?Z(e)+' <a class="kv-inline-link" href="'+Z(t)+'" target="_blank" rel="noopener noreferrer">GitHub<svg class="kv-inline-link-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M7 17 17 7"/><path d="M9 7h8v8"/></svg></a>':Z(e)}function Xe(e){if(e)try{const t=new URL(e);if("https:"!==t.protocol&&"http:"!==t.protocol)return;return t.username="",t.password="",t.toString()}catch{return}}function Ne(e){const t='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';if(!(e.npm||e.repository||e.homepage||e.issues))return"";let r='<div class="package-links">';const i=Xe(e.npm),o=Xe(e.repository),c=Xe(e.homepage),l=Xe(e.issues);return i||o||c||l?(i&&(r+='<a href="'+Z(i)+'" target="_blank" rel="noopener" class="package-link">'+t+"npm</a>"),o&&(r+='<a href="'+Z(o)+'" target="_blank" rel="noopener" class="package-link">'+n+"Repository</a>"),c&&(r+='<a href="'+Z(c)+'" target="_blank" rel="noopener" class="package-link">'+s+"Homepage</a>"),l&&(r+='<a href="'+Z(l)+'" target="_blank" rel="noopener" class="package-link">'+a+"Issues</a>"),r+="</div>",r):""}function Te(e,n,s,r){const i=K(e),o=i.summary,c=_(e),l=c.isInferred?\`\${c.value} (inferred)\`:c.value,d=function(e){const t=e.package?.links||{},n=e.links||{},a=De(t.repository||n.repository||n.repo);return{npm:t.npm||n.npm,repository:a||t.repository||n.repository||n.repo,homepage:t.homepage||n.homepage,issues:t.bugs||t.issues||n.bugs||n.issues}}(e),u=JSON.stringify(e,null,2),p=e.usage.origins.workspaces?.length?'<div class="micro-sublist"><div class="micro-subtitle">Workspaces</div>'+me(e.usage.origins.workspaces,8)+"</div>":"",h=e.package.description?'<p class="dep-description"><span>Description: </span>'+Z(e.package.description)+"</p>":"";var g,m;const v=Ie("Overview",void 0,'<div class="definition-grid">'+[de("Dependency status",e.usage.direct?"Direct dependency":"Transitive dependency"),de("Scope",re(e.usage.scope)),e.usage.introduction?de("Introduced by",oe(e.usage.introduction)):"",e.usage.runtimeImpact?de("Runtime impact",(m=e.usage.runtimeImpact,m?oe(m):"")):"",de("Dependency depth",e.usage.depth),e.usage.direct?"":ge("Introduced via root packages",Se(e.usage.origins.topRootPackages,8,n,s)),e.usage.direct?"":de("Direct roots",e.usage.origins.rootPackageCount),e.usage.direct?"":ge("Direct parents",ve(e.usage.origins.topParentPackages,8,n,s)),e.usage.direct?"":de("Direct parents count",e.usage.origins.parentPackageCount??0),de("TypeScript types",(g=e.usage.tsTypes,"bundled"===g?"Bundled":"definitelyTyped"===g?"DefinitelyTyped":"none"===g?"None":"Unknown"))].filter(Boolean).join("")+"</div>"+p+function(e,t,n,a){if(!t||0===t.length)return"";const s=t.slice(0,n),r=t.length-n;let i='<div class="detail-list">';return i+='<div class="detail-title">'+Z(e)+"</div>",i+='<ul class="detail-items'+(a?" "+a:"")+'">',s.forEach(e=>{i+='<li class="detail-item">'+Z(e)+"</li>"}),r>0&&(i+='<li class="detail-item muted">+'+r+" more</li>"),i+="</ul></div>",i}("Top import locations",e.usage.importUsage?.topFiles,5,"mono")),f=e.compliance.license,y=Ae(d.repository,"package.json"),k=Ae(d.repository,"LICENSE"),b=[ge("Primary license",ue(l,e.compliance.licenseRisk)),de("Status",q(f.status))];if(f.declared){const e=[f.declared.valid?"valid":"invalid",f.declared.expression?"expression":void 0,f.declared.deprecated?"deprecated":void 0].filter(Boolean).join(", "),t=f.exception?.id?\` WITH \${f.exception.id}\`:"";b.push(ge("Declared SPDX in package.json",'<span class="kv-value">'+Ye(\`\${f.declared.spdxId}\${t}\${e?\` (\${e})\`:""}\`,y)+"</span>"))}f.inferred&&b.push(ge("Inferred from LICENSE file",'<span class="kv-value">'+Ye(\`\${f.inferred.spdxId} (\${f.inferred.confidence})\`,k)+"</span>")),"mismatch"===f.status&&b.push(de("Mismatch","Declared SPDX and LICENSE text do not match")),"invalid-spdx"===f.status&&b.push(de("Invalid SPDX","Package.json license is not a valid SPDX identifier or expression"));const w=Me("License",'<div class="kv-grid">'+b.join("")+"</div>"),C=t(o),E=[ge("Vulnerability status",ue(0===C?"No known vulnerabilities":String(C),o.risk)),de("Highest severity","none"===o.highest?"None":oe(o.highest))],x=C>0?'<div class="kv-grid kv-grid-tight">'+[de("Critical",o.critical),de("High",o.high),de("Moderate",o.moderate),de("Low",o.low)].join("")+"</div>":"",S=function(e){if(!e||0===e.length)return"";let t='<table class="vuln-table"><thead><tr>';return t+="<th>Title</th><th>Severity</th><th>Affected range</th><th>Fix available</th><th>Reference</th>",t+="</tr></thead><tbody>",e.forEach(e=>{const n=Z(e.title),a=Xe(e.url),s=a?'<a href="'+Z(a)+'" target="_blank" rel="noopener">Link</a>':"";t+='<tr data-severity="'+Z(e.severity)+'">',t+='<td data-label="Title">'+n+"</td>",t+='<td data-label="Severity">'+Z(ie(e.severity))+"</td>",t+='<td data-label="Affected range">'+Z(e.vulnerableRange)+"</td>",t+='<td data-label="Fix available">'+Z(e.fixAvailable?"Yes":"No")+"</td>",t+='<td data-label="Reference">'+s+"</td>",t+="</tr>"}),t+="</tbody></table>",t}(i.advisories),L=Me("Vulnerabilities",['<div class="kv-grid">'+E.join("")+"</div>",x||"",S||""].join(""),"Known security issues from npm audit","vuln-block"),I=e.execution?function(e){const t=[ge("Execution risk",ue(Pe(e.risk),e.risk))];if(e.native&&t.push(de("Native build tooling detected (native)","Yes")),e.scripts?.hooks?.length&&t.push(ge("Lifecycle hooks",me(e.scripts.hooks,6))),"number"==typeof e.scripts?.complexity&&t.push(de("Heuristic complexity","Script complexity: "+e.scripts.complexity+" (complexity)")),e.scripts?.signals?.length){const n=e.scripts.signals.map(e=>\`\${M[e]} (\${e})\`);t.push(ge("Install-time signals",me(n,6)))}const n=(e.signals||[]).filter(t=>!(e.scripts?.signals||[]).includes(t));if(n.length){const e=n.map(e=>\`\${M[e]} (\${e})\`);t.push(ge("Local execution signals",me(e,6)))}return Me("Install-time execution behaviour",'<div class="section-note">Execution behaviour signals are local static review cues from lifecycle scripts, entry files, package bins, or a small bounded set of package files. They do not imply compromise.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.execution):"",D=function(e){if(!e?.signals?.length)return"";const t=[ge("Packaging signals",me(e.signals.map(e=>\`\${P[e]} (\${e})\`),6))];return e.bundledDependencies?.length&&t.push(ge("Bundled dependencies",me(e.bundledDependencies,8))),Me("Package contents",'<div class="section-note">Packaging signals describe local package structure that may warrant review; they are not malware verdicts.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.packaging),A=function(e){if(!e?.attempted)return"";const t=[de("Lookup",e.ok?"Available":"Unavailable"),ge("Candidate reasons",me(e.candidateReasons||[],6))];if(e.error&&t.push(de("Error",e.error)),e.signals?.length){const n=e.signals.map(e=>\`\${B[e]} (\${e})\`);t.push(ge("Registry signals",me(n,6)))}return e.installedVersionPublishedAt&&t.push(de("Installed version published",e.installedVersionPublishedAt)),e.packageCreatedAt&&t.push(de("Package created",e.packageCreatedAt)),"number"==typeof e.versionCount&&t.push(de("Published versions",e.versionCount)),e.latestVersion&&t.push(de("Latest dist-tag",e.latestVersion)),Me("Registry metadata",'<div class="section-note">Targeted npm registry metadata is collected only for packages that already show local review signals, and is skipped in offline scans.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.supplyChain?.registry),Y=Ie("Risk & Compliance",void 0,w+L+function(e){if(!e?.attempted)return"";const t=[de("Status",\$(e.status))];if(e.deprecated){const n=e.deprecated.installedVersion?"Installed version":"Latest version";t.push(de("Deprecated",n,e.deprecated.message))}void 0!==e.repoArchived&&t.push(de("Repository archived",J(e.repoArchived),e.repoCheckedAt?\`Checked \${e.repoCheckedAt}\`:void 0)),e.packageModifiedAt&&t.push(de("Last registry activity",e.packageModifiedAt,"number"==typeof e.monthsSinceModified?\`~\${e.monthsSinceModified} months ago\`:void 0)),e.latestVersion&&t.push(de("Latest version",e.latestVersion)),e.fetchedAt&&t.push(de("Data fetched",e.fetchedAt+(e.fromCache?" (cached)":""))),e.error&&t.push(de("Error",e.error));const n="deprecated"===e.status||"archived"===e.status?"warning":void 0;return Me("Maintenance",'<div class="section-note">Conservative registry heuristics: "last registry activity" updates on any packument write, so age-based statuses under-flag rather than over-flag. Review cues, not verdicts.</div><div class="kv-grid">'+t.join("")+"</div>",void 0,n)}(e.maintenance)+I+D+A+Be(r)),X=[de("Outdated status",(N=e.upgrade.outdatedStatus,N?"unknown"===N?"Unknown":oe(N):"Not reported"))];var N;e.upgrade.latestVersion&&X.push(de("Latest version",e.upgrade.latestVersion));const T=Me("Version",'<div class="section-note">Based on npm outdated findings and registry metadata.</div><div class="kv-grid">'+X.join("")+"</div>"),j=e.package.deprecated&&!e.maintenance?.deprecated?Me("Deprecated",'<div class="kv-grid">'+de("Deprecated","Yes","Declared by the package author.")+"</div>",void 0,"warning"):"",R=[de("Node engine constraint",e.upgrade.nodeEngine||"Any")];void 0!==e.upgrade.blocksNodeMajor&&R.push(de("Blocks Node major upgrade",J(e.upgrade.blocksNodeMajor)));const V=Me("Constraints",'<div class="kv-grid">'+R.join("")+"</div>"),H=Me("Blast radius",'<div class="kv-grid">'+[de("Used by other packages (fanIn)",e.graph.fanIn),de("Depends on packages (fanOut)",e.graph.fanOut)].join("")+"</div>"),O={nodeEngine:"Node engine constraint",peerDependency:"Peer dependency constraints",nativeBindings:"Native bindings/build tooling",installScripts:"Install lifecycle scripts",deprecated:"Deprecated by author"},F=Ie("Upgrade & Change Impact","Currency, constraints, and blast radius",T+j+V+H+('<div class="subsection"><div class="subsection-header"><span class="subsection-title">Upgrade blockers</span></div>'+(e.upgrade.blockers?.length?'<ul class="bullet-list">'+e.upgrade.blockers.map(e=>"<li>"+Z(O[e]||e)+"</li>").join("")+"</ul>":'<div class="status-row">No upgrade blockers detected</div>')+"</div>")),W=Le(e,n,s);return[Ne(d),h,he(e,o,l),(U=a(e,o),['<div class="key-points">','<div class="section-header compact"><span class="section-title">Key points</span></div>','<ul class="key-points-list">',U.map(e=>"<li>"+Z(e)+"</li>").join(""),"</ul>","</div>"].join("")),v,Y,F,W,'<details class="raw-data-toggle"><summary><span class="expand-icon" aria-hidden="true"></span>View raw data</summary><div class="raw-data-pane"><pre>'+Z(u)+'</pre><button type="button" class="copy-json-btn" aria-label="Copy raw JSON">Copy JSON</button></div></details>'].join("");var U}async function je(){const e=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}();void 0===window.__DEPENDENCY_DATA__&&(window.__DEPENDENCY_DATA__=e);const t=document.getElementById("dependency-list"),n=document.getElementById("results-summary"),a=document.getElementById("scan-status-banner");if(a&&e.scanStatus?.warnings.length){a.hidden=!1;const t=document.createElement("strong");t.textContent=e.scanStatus.complete?"Some analysis was intentionally skipped":"Scan evidence is incomplete",a.appendChild(t);const n=document.createElement("ul");e.scanStatus.warnings.slice(0,8).forEach(e=>{const t=document.createElement("li");t.textContent=e.length>300?\`\${e.slice(0,297)}…\`:e,n.appendChild(t)}),a.appendChild(n)}const r=document.getElementById("project-path");r&&(r.textContent=e.project.name||e.project.projectDir,r.title=e.project.projectDir);const i=document.getElementById("metadata-toggle"),o=document.getElementById("metadata-panel"),c=document.getElementById("formatted-date");let l=e.generatedAt||"";if(c&&e.generatedAt)try{const t=new Date(e.generatedAt);Number.isNaN(t.getTime())?(l=e.generatedAt,c.textContent=e.generatedAt):(l=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(t),c.textContent=l)}catch{l=e.generatedAt,c.textContent=e.generatedAt}o&&(o.innerHTML=function(e,t){const n=e.environment||{},a=n.minRequiredMajor,s=a&&a>0?"Node requirement derived from dependency engine ranges.":"";return[ne("Report",[te("Dependency Radar",e.dependencyRadarVersion),te("Schema",e.schemaVersion),te("Generated",t||e.generatedAt),te("Generated raw",e.generatedAt)]),ne("Project",[te("Name",e.project.name),te("Version",e.project.version),te("Path",e.project.projectDir),te("Description",e.project.description),te("License",e.project.license),te("Homepage",e.project.homepage),te("Repository",e.project.repository),te("Constraints",e.project.constraints),te("Dependency policy",e.project.dependencyPolicySummary)]),ne("Git",[te("Branch",e.git?.branch)]),ne("Environment",[te("Node",n.nodeVersion),te("Runtime",n.runtimeVersion),te("Minimum required Node major",n.minRequiredMajor),te("Target Node major",n.targetNodeMajor),te("Platform",n.platform),te("Architecture",n.arch),te("CI",n.ci),te("packageManager field",n.packageManagerField),te("Package manager",n.packageManager),te("Package manager version",n.packageManagerVersion),te("Tool versions",n.toolVersions),te("Node note",s)]),ae(e),ne("Summary",[te("Dependencies",e.summary?.dependencyCount),te("Direct",e.summary?.directCount),te("Transitive",e.summary?.transitiveCount),te("Findings",e.summary?.findingCount)]),ne("Scan evidence",[te("Complete",e.scanStatus?.complete),te("Collectors",e.scanStatus?.collectors),te("Warnings",e.scanStatus?.warnings)]),se(e)].filter(Boolean).join("")}(e,l),o.hidden=!1,o.inert=!0,o.setAttribute("aria-hidden","true"));const d=e=>{i&&o&&(o.classList.toggle("open",e),o.inert=!e,o.setAttribute("aria-hidden",String(!e)),i.classList.toggle("open",e),i.setAttribute("aria-expanded",String(e)))};i?.addEventListener("click",()=>{const e=!o?.classList.contains("open");d(e)}),document.addEventListener("click",e=>{if(!i||!o)return;if(!o.classList.contains("open"))return;const t=e.target;i.contains(t)||o.contains(t)||d(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&d(!1)});const u={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),workspace:document.getElementById("workspace-filter"),workspaceWrap:document.getElementById("workspace-filter-wrap"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),maintenanceConcerns:document.getElementById("maintenance-concerns"),licenseIssues:document.getElementById("license-issues"),upgradeBlockers:document.getElementById("upgrade-blockers"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly"),filtersToggle:document.getElementById("filters-toggle"),filterCountBadge:document.getElementById("filter-count-badge"),filterControls:document.getElementById("filter-controls"),activeFiltersRow:document.getElementById("active-filters-row"),activeFilterChips:document.getElementById("active-filter-chips"),activeFilterClear:document.getElementById("active-filter-clear"),clearAllFilters:document.getElementById("clear-all-filters"),licensePermissiveLabel:document.getElementById("license-permissive-label"),licenseWeakCopyleftLabel:document.getElementById("license-weak-copyleft-label"),licenseStrongCopyleftLabel:document.getElementById("license-strong-copyleft-label"),licenseUnknownLabel:document.getElementById("license-unknown-label"),hasVulnsLabel:document.getElementById("has-vulns-label"),maintenanceConcernsLabel:document.getElementById("maintenance-concerns-label"),licenseIssuesLabel:document.getElementById("license-issues-label"),upgradeBlockersLabel:document.getElementById("upgrade-blockers-label"),columnHeadersContainer:document.getElementById("column-headers-container"),packageHeader:document.getElementById("package-header"),viewGraphButton:document.getElementById("view-graph-btn"),graphBackButton:document.getElementById("graph-back-btn"),listViewPanel:document.getElementById("list-view"),graphViewPanel:document.getElementById("graph-view"),graphWorkspaceSelect:document.getElementById("graph-workspace"),graphWorkspaceWrap:document.getElementById("graph-workspace-wrap"),graphControls:document.getElementById("graph-controls"),graphCanvas:document.getElementById("graph-canvas"),graphCanvasShell:document.getElementById("graph-canvas-shell"),graphPopover:document.getElementById("graph-popover"),graphPopoverName:document.getElementById("graph-popover-name"),graphPopoverVersion:document.getElementById("graph-popover-version"),graphPopoverLicense:document.getElementById("graph-popover-license"),graphPopoverVulns:document.getElementById("graph-popover-vulns"),graphPopoverAmplification:document.getElementById("graph-popover-amplification"),graphOpenList:document.getElementById("graph-open-list"),reportFooter:document.querySelector(".report-footer")};let p="name",h=!0,g=null,m=!1;document.documentElement.setAttribute("data-theme","dark"),"light"===localStorage.getItem("dependency-radar-theme")?(document.documentElement.classList.add("light"),u.themeSwitch.classList.add("light"),u.themeSwitch.setAttribute("aria-pressed","true"),document.documentElement.setAttribute("data-theme","light")):(document.documentElement.classList.remove("light"),u.themeSwitch.classList.remove("light"),u.themeSwitch.setAttribute("aria-pressed","false"),document.documentElement.setAttribute("data-theme","dark")),u.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),u.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");document.documentElement.setAttribute("data-theme",e?"light":"dark"),u.themeSwitch.setAttribute("aria-pressed",String(e)),localStorage.setItem("dependency-radar-theme",e?"light":"dark"),g?.requestRender()});const v=window.matchMedia("(max-width: 768px)");let f=v.matches;const y=e=>{u.filterControls&&u.filtersToggle&&(u.filterControls.classList.toggle("open",e),u.filterControls.inert=!e,u.filterControls.setAttribute("aria-hidden",String(!e)),u.filtersToggle.classList.toggle("open",e),u.filtersToggle.setAttribute("aria-expanded",String(e)),e&&d(!1))},k=()=>{if(v.matches)return y(!1),void(f=!0);f&&y(!1),f=!1};function b(){if(u.columnHeadersContainer&&(u.columnHeadersContainer.innerHTML=le(p,h)),u.packageHeader){const e=u.packageHeader.querySelector(".sort-indicator");e&&("name"===p?(e.textContent=h?" ▲":" ▼",u.packageHeader.classList.add("sorted")):(e.textContent="",u.packageHeader.classList.remove("sorted")))}}function w(e){const t=e.target.closest(".column-header");if(!t)return;const n=t.dataset.sort;n&&(p===n?h=!h:(p=n,h=!0),u.sort&&(u.sort.value=p,u.sortDirection.textContent=h?"↑":"↓"),b(),q())}u.filtersToggle&&u.filterControls&&u.filtersToggle.addEventListener("click",()=>{const e=!u.filterControls.classList.contains("open");y(e)}),document.addEventListener("click",e=>{if(!u.filterControls||!u.filtersToggle)return;const t=e.target;u.filterControls.contains(t)||u.filtersToggle.contains(t)||y(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&y(!1)}),y(!1),window.addEventListener("resize",k),k(),u.sortDirection.addEventListener("click",()=>{h=!h,u.sortDirection.textContent=h?"↑":"↓",b(),q()}),u.sort.addEventListener("change",()=>{p=u.sort.value,b(),q()}),u.columnHeadersContainer&&u.columnHeadersContainer.addEventListener("click",w),u.packageHeader&&u.packageHeader.addEventListener("click",w),b(),u.licenseAll.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0,X.clear(),q()}),u.licenseFriendly.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!1,u.licenseStrongCopyleft.checked=!1,u.licenseUnknown.checked=!1,X.clear(),q()});const C=Object.values(e.dependencies||{}),E=e=>{const t=e.usage.origins.workspaces||[];return t.length>0?t:["root"]},x=Array.from(new Set([...s(e),...C.flatMap(E)])).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t)),S=(e,t)=>e+" ("+t+")",I=e=>{return z[t=K(e).summary,t?.highest||"none"]>0;var t},M=e=>C.reduce((t,n)=>t+(e(n)?1:0),0);if(u.workspace&&u.workspaceWrap&&x.length>1){u.workspace.textContent="";const e=document.createElement("option");e.value="all",e.textContent=S("All workspaces",C.length),u.workspace.appendChild(e),x.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=S("root"===e?"Workspace root":e,M(t=>E(t).includes(e))),u.workspace.appendChild(t)}),u.workspaceWrap.classList.remove("hidden")}!function(){const e=C.length;u.direct.options[0].textContent=S("All",e),u.direct.options[1].textContent=S("Direct",M(e=>e.usage.direct)),u.direct.options[2].textContent=S("Transitive",M(e=>!e.usage.direct));const t={all:"All",runtime:"Production",dev:"Development",optional:"Optional",peer:"Peer"};Array.from(u.runtime.options).forEach(n=>{n.textContent=S(t[n.value]||n.textContent||n.value,"all"===n.value?e:M(e=>e.usage.scope===n.value))});const n={permissive:0,weakCopyleft:0,strongCopyleft:0,unknown:0};C.forEach(e=>{n[G(_(e).value)]+=1}),u.licensePermissiveLabel&&(u.licensePermissiveLabel.textContent=S("Permissive",n.permissive)),u.licenseWeakCopyleftLabel&&(u.licenseWeakCopyleftLabel.textContent=S("Weak Copyleft",n.weakCopyleft)),u.licenseStrongCopyleftLabel&&(u.licenseStrongCopyleftLabel.textContent=S("Strong Copyleft",n.strongCopyleft)),u.licenseUnknownLabel&&(u.licenseUnknownLabel.textContent=S("Other / Unknown",n.unknown)),u.hasVulnsLabel&&(u.hasVulnsLabel.textContent=S("Has vulnerabilities",M(I))),u.maintenanceConcernsLabel&&(u.maintenanceConcernsLabel.textContent=S("Maintenance concerns",M(O))),u.licenseIssuesLabel&&(u.licenseIssuesLabel.textContent=S("Licence issues",M(F))),u.upgradeBlockersLabel&&(u.upgradeBlockersLabel.textContent=S("Upgrade blockers",M(W)))}(),function(){const t=document.getElementById("header-stats");if(!t)return;let n=0,a=0,s=0,r=!1,i=0,o=0;C.forEach(e=>{if(I(e)&&(n+=1),e.maintenance?.attempted&&(r=!0),O(e)){a+=1;const t=e.maintenance?.status;"deprecated"!==t&&"archived"!==t||(s+=1)}F(e)&&(i+=1),W(e)&&(o+=1)});const c=(e,t,n,a)=>{const s=document.getElementById(e);if(!s)return;const r=s.querySelector("strong");r&&(r.textContent=String(t)),s.classList.remove("red","amber"),n&&t>0&&s.classList.add(n),a&&(s.title=a)};c("stat-total",e.summary.dependencyCount,void 0,\`\${e.summary.directCount} direct, \${e.summary.transitiveCount} transitive\`),c("stat-vulnerable",n,"red","Dependencies with known vulnerabilities — click to filter");const l=(e,t,n)=>{const a=document.getElementById(e);if(!a)return;a.hidden=!1,a.disabled=!0,a.classList.remove("red","amber");const s=a.querySelector("strong");s&&(s.textContent="?"),a.title=\`\${n} is unknown because its collector is \${t}\`},d=e.scanStatus?.collectors.audit;d&&"available"!==d&&l("stat-vulnerable",d,"Vulnerability status"),c("stat-license",i,"amber","Dependencies with licence review flags — click to filter"),c("stat-blockers",o,"amber","Dependencies with upgrade blockers — click to filter");const p=document.getElementById("stat-maintenance");if(p){const t=e.scanStatus?.collectors.maintenance;t&&"available"!==t?l("stat-maintenance",t,"Maintenance status"):r?c("stat-maintenance",a,s>0?"red":"amber","Deprecated, archived, unmaintained, or stale dependencies — click to filter"):p.hidden=!0}t.addEventListener("click",e=>{const t=e.target.closest("[data-stat-filter]");if(!t)return;if(t.disabled)return;const n={"has-vulns":u.hasVulns,"maintenance-concerns":u.maintenanceConcerns,"license-issues":u.licenseIssues,"upgrade-blockers":u.upgradeBlockers}[t.dataset.statFilter||""];if(!n)return;const a=n.checked;u.search.value="",\$(),n.checked=!a,n.dispatchEvent(new Event("change"))})}();const P=new Map;C.forEach(e=>{P.set(fe(e.package.name,e.package.version),e)});const B=new Set(P.keys()),D=we(B),A=function(e,t,n){const a=new Map,s=(e,t)=>{const n=a.get(e)||[];n.push(t),a.set(e,n)};for(const r of e.supplyChain?.signals||[]){const e=[r.packageId,r.packageName&&r.packageVersion?fe(r.packageName,r.packageVersion):void 0].filter(Boolean);let a=!1;for(const n of e){const e=xe(n,t);if(e){s(e,r),a=!0;break}}if(!a&&r.packageName&&!r.packageVersion){const e=Ce(r.packageName,t,n);e&&s(e,r)}}return a}(e,B,D),Y=new Set,X=new Set,N=new Map,T=(()=>{const e=document.getElementById("copy-announcer");if(e)return e;const t=document.createElement("div");return t.id="copy-announcer",t.className="sr-only",t.setAttribute("aria-live","polite"),document.body.appendChild(t),t})();function j(e){const t=e.dataset.depKey;if(!t)return;const n=e.querySelector(".dep-details");if(!n||"true"===n.dataset.rendered)return;const a=P.get(t);a&&(n.setAttribute("aria-busy","true"),n.innerHTML=['<div class="dep-loading" role="presentation">','<div class="dep-loading-bar"></div>',"</div>"].join(""),requestAnimationFrame(()=>{n.innerHTML=Te(a,B,D,A.get(t)),n.dataset.rendered="true",n.removeAttribute("aria-busy")}))}function V(e){return(e.selectedOptions[0]?.textContent||"").replace(/\\s+\\(\\d+\\)\$/,"")}function \$(){u.direct.value="all",u.runtime.value="all",u.workspace&&(u.workspace.value="all"),u.hasVulns.checked=!1,u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1),u.licenseIssues&&(u.licenseIssues.checked=!1),u.upgradeBlockers&&(u.upgradeBlockers.checked=!1),u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0}function H(){const e=[],t=u.search.value.trim();return t&&e.push({id:"search",label:"Search: "+t,remove:()=>{u.search.value=""}}),"all"!==u.direct.value&&e.push({id:"type",label:"Type: "+V(u.direct),remove:()=>{u.direct.value="all"}}),"all"!==u.runtime.value&&e.push({id:"scope",label:"Scope: "+V(u.runtime),remove:()=>{u.runtime.value="all"}}),u.workspace&&"all"!==u.workspace.value&&e.push({id:"workspace",label:"Workspace: "+V(u.workspace),remove:()=>{u.workspace.value="all"}}),[{id:"license-permissive",checked:u.licensePermissive.checked,label:"License: Permissive",reset:()=>{u.licensePermissive.checked=!0}},{id:"license-weak-copyleft",checked:u.licenseWeakCopyleft.checked,label:"License: Weak Copyleft",reset:()=>{u.licenseWeakCopyleft.checked=!0}},{id:"license-strong-copyleft",checked:u.licenseStrongCopyleft.checked,label:"License: Strong Copyleft",reset:()=>{u.licenseStrongCopyleft.checked=!0}},{id:"license-unknown",checked:u.licenseUnknown.checked,label:"License: Other / Unknown",reset:()=>{u.licenseUnknown.checked=!0}}].forEach(t=>{t.checked||e.push({id:t.id,label:t.label,remove:t.reset})}),u.hasVulns.checked&&e.push({id:"has-vulns",label:"Has vulnerabilities",remove:()=>{u.hasVulns.checked=!1}}),u.maintenanceConcerns?.checked&&e.push({id:"maintenance-concerns",label:"Maintenance concerns",remove:()=>{u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1)}}),u.licenseIssues?.checked&&e.push({id:"license-issues",label:"Licence issues",remove:()=>{u.licenseIssues&&(u.licenseIssues.checked=!1)}}),u.upgradeBlockers?.checked&&e.push({id:"upgrade-blockers",label:"Upgrade blockers",remove:()=>{u.upgradeBlockers&&(u.upgradeBlockers.checked=!1)}}),e}function q(){!function(){const e=H(),t=e.length;u.filtersToggle.classList.toggle("has-active-filters",t>0),u.filterCountBadge&&(u.filterCountBadge.hidden=0===t,u.filterCountBadge.textContent=String(t)),u.activeFiltersRow&&u.activeFilterChips&&(u.activeFiltersRow.hidden=0===t,u.activeFilterChips.innerHTML=e.map(e=>'<span class="active-filter-chip">'+Z(e.label)+'<button type="button" class="active-filter-remove" data-filter-chip="'+Z(e.id)+'" aria-label="Remove '+Z(e.label)+'">×</button></span>').join(""))}();const a=function(e){const t=[...e];if("name"===p)t.sort((e,t)=>e.package.name.localeCompare(t.package.name));else if("depth"===p)t.sort((e,t)=>e.usage.depth-t.usage.depth);else{const e=R.find(e=>e.sortKey===p||e.id===p);e?.sortFn?t.sort(e.sortFn):e&&t.sort((t,n)=>e.getValue(t).localeCompare(e.getValue(n)))}return h||t.reverse(),t}(function(){const e=(u.search.value||"").toLowerCase(),t=u.direct.value,n=u.runtime.value,a=u.workspace?.value||"all",s=u.hasVulns.checked,r=u.maintenanceConcerns?.checked??!1,i=u.licenseIssues?.checked??!1,o=u.upgradeBlockers?.checked??!1,c=u.licensePermissive.checked,l=u.licenseWeakCopyleft.checked,d=u.licenseStrongCopyleft.checked,p=u.licenseUnknown.checked;return C.filter(u=>{const h=fe(u.package.name,u.package.version);if(X.has(h))return!0;const g=_(u),m=[g.value,u.compliance.license.declared?.spdxId,u.compliance.license.inferred?.spdxId].filter(Boolean).join(" ").toLowerCase();if(e&&!u.package.name.toLowerCase().includes(e)&&!m.includes(e))return!1;if("direct"===t&&!u.usage.direct)return!1;if("transitive"===t&&u.usage.direct)return!1;if("all"!==n&&u.usage.scope!==n)return!1;if("all"!==a&&!E(u).includes(a))return!1;if(s&&!I(u))return!1;if(r&&!O(u))return!1;if(i&&!F(u))return!1;if(o&&!W(u))return!1;const v=G(g.value);return!("permissive"===v&&!c||"weakCopyleft"===v&&!l||"strongCopyleft"===v&&!d||"unknown"===v&&!p)})}()),s=e.summary?.dependencyCount||C.length;n.innerHTML="Showing <strong>"+a.length+"</strong> of <strong>"+s+"</strong> dependencies","all"!==(u.workspace?.value||"all")&&(n.innerHTML+=" in <strong>"+Z(u.workspace.value)+"</strong>"),0!==a.length?(t.innerHTML=a.map(e=>function(e,t){const n=function(e,t,n=0){const a=e.execution?.risk||"green",s=n>0||(e.packaging?.signals?.length||0)>0?"amber":"green",r=(e.supplyChain?.registry?.signals?.length||0)>0?"amber":"green",i=e.maintenance?.status,o="deprecated"===i||"archived"===i?"red":"unmaintained"===i?"amber":"green";return(c=[t.risk,e.compliance.licenseRisk,a,s,r,o]).includes("red")?"red":c.includes("amber")?"amber":"green";var c}(e,K(e).summary,t?.length||0),a=fe(e.package.name,e.package.version),s=be(a),r=ce(e),i=['<summary class="dep-summary">','<span class="expand-icon" aria-hidden="true"></span>','<span class="dep-name">'+Z(e.package.name)+'<span class="dep-version">@'+Z(e.package.version)+"</span></span>",'<div class="dep-indicators" style="--column-count: '+U+'">',r,"</div>","</summary>"].join("");return['<details class="dep-card" data-risk="'+n+'" data-dep-key="'+Z(a)+'" id="'+Z(s)+'">',i,'<div class="dep-details" data-rendered="false"></div>',"</details>"].join("")}(e,A.get(fe(e.package.name,e.package.version)))).join(""),N.clear(),t.querySelectorAll("details.dep-card").forEach(e=>{const t=e.dataset.depKey;t&&N.set(t,e)}),Y.forEach(e=>{const t=N.get(e);t&&(t.open||(t.open=!0),j(t))})):t.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}function J(e){const t=D.get(e)||[];return 1===t.length?t[0]:null}function Q(e){if(P.has(e))return e;const t=ke(e);if(!t)return J(e);if(t.version.startsWith("npm:")){const e=t.version.slice(4),n=t.name+(e.startsWith("@")?e:"@"+e);if(P.has(n))return n}return J(t.name)}function ee(t){if(!u.listViewPanel||!u.graphViewPanel)return void console.warn("Dependency Radar: view panels are missing from the report DOM.");const n="list"===t;n||Boolean(u.graphWorkspaceSelect&&u.graphWorkspaceWrap&&u.graphControls&&u.graphCanvas&&u.graphCanvasShell&&u.graphPopover&&u.graphPopoverName&&u.graphPopoverVersion&&u.graphPopoverLicense&&u.graphPopoverVulns&&u.graphPopoverAmplification&&u.graphOpenList)?(u.listViewPanel.classList.toggle("active",n),u.graphViewPanel.classList.toggle("active",!n),u.listViewPanel.setAttribute("aria-hidden",String(!n)),u.graphViewPanel.setAttribute("aria-hidden",String(n)),u.viewGraphButton&&(u.viewGraphButton.style.display=n?"":"none"),u.graphBackButton&&(u.graphBackButton.style.display=n?"none":""),u.reportFooter?.classList.toggle("hidden",!n),document.body.classList.toggle("graph-mode",!n),n?g?.setActive(!1):(m||(g=L({report:e,knownDepKeys:B,resolveDepKey:Q,workspaceSelect:u.graphWorkspaceSelect,workspaceWrap:u.graphWorkspaceWrap,controlsRoot:u.graphControls,canvas:u.graphCanvas,canvasHost:u.graphCanvasShell,popover:u.graphPopover,popoverName:u.graphPopoverName,popoverVersion:u.graphPopoverVersion,popoverLicense:u.graphPopoverLicense,popoverVulns:u.graphPopoverVulns,popoverAmplification:u.graphPopoverAmplification,popoverOpenButton:u.graphOpenList,onOpenList:e=>{!function(e){ee("list");let t=document.getElementById(be(e));!t&&P.has(e)&&(X.add(e),q(),t=document.getElementById(be(e)));if(!t)return;if(t instanceof HTMLDetailsElement){const e=t.dataset.depKey;e&&Y.add(e),t.open||(t.open=!0),j(t)}t.classList.add("dep-list-highlight"),re(t,!0),window.setTimeout(()=>{t?.classList.remove("dep-list-highlight")},2e3)}(e)}}),g.initGraphView(),m=!0),g?.setActive(!0),g?.requestRender())):console.warn("Dependency Radar: graph view DOM nodes are missing; graph view disabled.")}function re(e,t=!1){const n=()=>{const n=window.scrollY+e.getBoundingClientRect().top-function(){const e=document.querySelector(".filter-bar");return!e||document.body.classList.contains("graph-mode")?0:Math.ceil(e.getBoundingClientRect().height+8)}();if(window.scrollTo({top:Math.max(0,n),behavior:"smooth"}),t){const t=e.querySelector("summary");t&&t.focus({preventScroll:!0})}};requestAnimationFrame(()=>{n(),window.setTimeout(n,60)})}const ie=[u.search,u.direct,u.runtime,u.sort,u.hasVulns,u.maintenanceConcerns,u.licenseIssues,u.upgradeBlockers,u.workspace,u.licensePermissive,u.licenseWeakCopyleft,u.licenseStrongCopyleft,u.licenseUnknown],oe=()=>{X.clear(),q()};ie.forEach(e=>{e&&(e.addEventListener("input",oe),e.addEventListener("change",oe))}),u.activeFilterChips?.addEventListener("click",e=>{const t=e.target.closest("[data-filter-chip]");if(!t)return;const n=H().find(e=>e.id===t.dataset.filterChip);n&&(n.remove(),oe())});const de=()=>{u.search.value="",\$(),oe()};function ue(e){const t=e.getAttribute("data-dep-key");if(!t)return;const n=Q(t);if(!n)return;let a=N.get(n);a||(X.add(n),q(),a=N.get(n)),a&&(Y.add(n),a.open||(a.open=!0),j(a),re(a,!0))}u.activeFilterClear?.addEventListener("click",de),u.clearAllFilters?.addEventListener("click",de),u.viewGraphButton?.addEventListener("click",()=>{ee("graph")}),u.graphBackButton?.addEventListener("click",()=>{ee("list")}),t.addEventListener("toggle",e=>{const t=e.target;if(!(t instanceof HTMLDetailsElement))return;if(!t.classList.contains("dep-card"))return;const n=t.dataset.depKey;n&&(t.open?(Y.add(n),j(t)):Y.delete(n))},!0),t.addEventListener("click",e=>{const t=e.target,n=t.closest(".root-package-link");if(n)return e.preventDefault(),void ue(n);const a=t.closest(".copy-json-btn");a&&(e.preventDefault(),async function(e){const t=(e.closest(".raw-data-toggle")?.querySelector("pre"))?.textContent??"";if(t)try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(t);else{const e=document.createElement("textarea");e.value=t,e.setAttribute("readonly","true"),e.style.position="absolute",e.style.left="-9999px",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}const n=e.dataset.label||e.textContent||"Copy JSON";e.dataset.label=n,e.textContent="Copied",e.classList.add("copied"),T.textContent="Copied JSON to clipboard.",window.setTimeout(()=>{e.textContent=n,e.classList.remove("copied")},1500)}catch{T.textContent="Copy failed."}}(a))}),t.addEventListener("keydown",e=>{const t=e.target.closest(".root-package-link");t&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),ue(t)))}),b(),q(),ee("list")}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",je):je()}();`; | |||
| export const JS_CONTENT = `!function(){var e=[{signalType:"git-dependency",type:"install-scripts-git-source",severity:"error",title:"Install scripts from a git-sourced package",detail:"This package runs code at install time AND is installed from a git source, so its content can change without a version bump or registry publish."},{signalType:"non-registry-tarball",type:"install-scripts-non-registry-tarball",severity:"error",title:"Install scripts from a non-registry tarball",detail:"This package runs code at install time AND is fetched from a tarball outside the configured registry, bypassing registry review surfaces."},{signalType:"unexpected-registry-host",type:"install-scripts-unexpected-registry-host",severity:"error",title:"Install scripts from an unexpected registry host",detail:"This package runs code at install time AND resolves from a registry host that does not match the expected hosts for this project."},{signalType:"missing-integrity",type:"install-scripts-missing-integrity",severity:"warning",title:"Install scripts without lockfile integrity",detail:"This package runs code at install time AND has no lockfile integrity hash, so a substituted artifact would not be detected at install."}];function t(t,n){const a=t.execution?.scripts?.hooks||[];if(0===a.length||!n||0===n.size)return[];const s=[];for(const r of e)n.has(r.signalType)&&s.push({type:r.type,severity:r.severity,signalType:r.signalType,hooks:[...a].sort(),title:r.title,detail:r.detail});return s}var n={"network-access":"Accesses network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"};function a(e){return e.critical+e.high+e.moderate+e.low}function s(e,t){if(t&&0!==t.length)return function(e){const t=new Map;for(const n of e||[]){let e=n.packageName;if(!e&&n.packageId){const t=n.packageId.lastIndexOf("@");t>0&&(e=n.packageId.slice(0,t))}if(!e)continue;const a=t.get(e)||new Set;a.add(n.type),t.set(e,a)}return t}(t).get(e)}function r(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e.split(/[-_\\s]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function i(e,i,o){const c=[],l=a(i),d=e.security.advisories?.some(e=>e.fixAvailable);if(i.critical||i.high){const e=i.critical+i.high;c.push(\`\${e} critical/high \${1===e?"vulnerability":"vulnerabilities"}\${d?", fix available":""}\`)}if(i.moderate||i.low){const e=i.moderate+i.low;c.push(\`\${function(e){const t=[];return e.moderate&&t.push(\`\${e.moderate} moderate\`),e.low&&t.push(\`\${e.low} low\`),t.join(", ")}(i)} \${1===e?"vulnerability":"vulnerabilities"}\${d?", fix available":""}\`)}"deprecated"===e.maintenance?.status?c.push(e.maintenance.deprecated&&!e.maintenance.deprecated.installedVersion?"Latest version deprecated by the author":"Deprecated by the author"):"archived"===e.maintenance?.status?c.push("Source repository is archived"):"unmaintained"===e.maintenance?.status?c.push(void 0!==e.maintenance.monthsSinceRepoPush?"Registry and source repository have both gone quiet":"No registry activity for 3+ years"):"stale"===e.maintenance?.status?c.push(void 0!==e.maintenance.monthsSinceRepoPush?"Publishing and source activity have slowed to a trickle":"No registry activity for 18+ months"):"slowing"===e.maintenance?.status&&c.push("No registry publishes for 12+ months"),"green"!==e.compliance.licenseRisk&&c.push("Licence status: "+function(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}(e.compliance.license.status)),e.upgrade.blocksNodeMajor&&c.push("Blocks Node major upgrade"),e.upgrade.blockers?.length&&c.push(\`\${e.upgrade.blockers.length} upgrade \${1===e.upgrade.blockers.length?"blocker":"blockers"} detected\`),t(e,s(e.package.name,o)).forEach(e=>c.push(e.title)),e.replacement&&c.push("Community-suggested replacement available (e18e)");const u=e.execution?.risk||"green";var p;if("green"!==u&&c.push(("red"===(p=u)?"High":"amber"===p?"Medium":"Low")+" install-time execution risk"),e.execution?.scripts?.hooks?.length&&c.push("Runs "+e.execution.scripts.hooks.slice(0,2).join(", ")+" lifecycle script"+(1===e.execution.scripts.hooks.length?"":"s")),function(e){return Array.from(new Set([...e.execution?.scripts?.signals||[],...e.execution?.signals||[]]))}(e).slice(0,3).forEach(e=>c.push(n[e])),e.packaging?.signals?.length&&c.push(\`\${e.packaging.signals.length} package content \${1===e.packaging.signals.length?"signal":"signals"}\`),e.supplyChain?.registry?.signals?.length&&c.push(\`\${e.supplyChain.registry.signals.length} registry metadata \${1===e.supplyChain.registry.signals.length?"signal":"signals"}\`),e.usage.direct)c.push(\`Direct \${r(e.usage.scope).toLowerCase()} dependency\`);else{const t=e.usage.origins.topParentPackages?.[0]?\` introduced by \${e.usage.origins.topParentPackages[0]}\`:"";c.push(\`Transitive \${r(e.usage.scope).toLowerCase()} dependency\${t}\`)}return e.usage.depth>1&&c.push(\`Dependency depth \${e.usage.depth}\`),(0===c.length||0===l&&"green"===u&&"green"===e.compliance.licenseRisk&&c.length<3)&&["No known vulnerabilities","No install-time execution signals detected","Licence status appears consistent",e.usage.direct?\`Direct \${r(e.usage.scope).toLowerCase()} dependency\`:\`Transitive \${r(e.usage.scope).toLowerCase()} dependency\`].forEach(e=>{c.includes(e)||c.push(e)}),Array.from(new Set(c)).slice(0,8)}function o(e){if(!e.workspaces.enabled)return[];const t=new Set;return(e.workspaces.workspacePackages||[]).forEach(e=>{e.name&&t.add(e.name)}),Object.values(e.dependencies||{}).forEach(e=>{(e.usage.origins.workspaces||[]).forEach(e=>{e&&t.add(e)})}),Array.from(t).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t))}var c=2.8,l='500 11.5px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function d(e,t,n){return Math.min(n,Math.max(t,e))}function u(e,t=!1){return t?e.length:Math.min(e.length,34)}function p(e){const t=u(e);return e.length<=34?t:Math.max(1,t-6)}function h(e){const{labelGraphemes:t}=e;if(t.length<=34)return e.ref.name;const n=d(Math.round(e.renderLabelChars),1,t.length);return n>=t.length?e.ref.name:\`\${t.slice(0,n-1).join("")}…\`}function g(e,t,n){const a=function(e){const t=e.trim(),n=t.match(/^#([0-9a-f]{3}|[0-9a-f]{6})\$/i);if(n){const e=n[1];return 3===e.length?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16)}:{r:parseInt(e.slice(0,2),16),g:parseInt(e.slice(2,4),16),b:parseInt(e.slice(4,6),16)}}const a=t.match(/^rgba?\\(([^)]+)\\)\$/i);if(!a)return null;const s=a[1].replace(/\\//g," ").split(/[\\s,]+/).filter(Boolean).slice(0,3);if(3!==s.length)return null;const r=e=>{if(e.endsWith("%")){const t=Number(e.slice(0,-1));return Number.isFinite(t)?d(Math.round(t/100*255),0,255):null}const t=Number(e);return Number.isFinite(t)?d(Math.round(t),0,255):null},i=r(s[0]),o=r(s[1]),c=r(s[2]);return null===i||null===o||null===c?null:{r:i,g:o,b:c}}(e);if(!a)return n;const s=d(t,0,1);return\`rgb(\${Math.round(a.r+(255-a.r)*s)}, \${Math.round(a.g+(255-a.g)*s)}, \${Math.round(a.b+(255-a.b)*s)})\`}function m(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function v(e,t,n){if(0===t.length)return;if(e.moveTo(t[0].x,t[0].y),1===t.length)return;if(2===t.length)return void e.lineTo(t[1].x,t[1].y);for(let s=1;s<t.length-1;s+=1){const a=t[s-1],r=t[s],i=t[s+1],o=r.x-a.x,c=r.y-a.y,l=i.x-r.x,d=i.y-r.y,u=Math.hypot(o,c),p=Math.hypot(l,d);if(u<.001||p<.001){e.lineTo(r.x,r.y);continue}const h=Math.min(n,.45*u,.45*p),g=r.x-o/u*h,m=r.y-c/u*h,v=r.x+l/p*h,f=r.y+d/p*h;e.lineTo(g,m),e.quadraticCurveTo(r.x,r.y,v,f)}const a=t[t.length-1];e.lineTo(a.x,a.y)}function f(e){const t=new Map;return e.nodes.forEach(e=>{const n=t.get(e.depth);n?n.push(e):t.set(e.depth,[e])}),t.forEach(e=>{e.sort((e,t)=>e.renderY-t.renderY)}),t}function y(e,t,n,a){const s=t.renderX,r=t.renderY,i=n.renderX,o=n.renderY,c=n.depth-t.depth,l=Math.abs(c);if(0===l){const n=Math.abs(s-i)<a.sameColumnXThreshold,c=Math.abs(r-o),l=t.depth<a.maxDepth;if(n&&c>a.minDetourVerticalSpan&&l){const n=a.paddingX+t.depth*a.layerGap,l=a.paddingX+(t.depth+1)*a.layerGap,u=.5*(n+l);let p=u+a.detourInset;const h=Math.min(r,o)-12,g=Math.max(r,o)+12;(function(e,t,n,a,s){const r=e.depthNodeIndex.get(t);if(!r||0===r.length)return!1;const i=function(e,t){let n=0,a=e.length;for(;n<a;){const s=n+(a-n>>1);e[s].renderY<t?n=s+1:a=s}return n}(r,n);for(let o=i;o<r.length&&r[o].renderY<=a;o+=1)if(Math.abs(r[o].renderX-s)<e.detourNodeClearance)return!0;return!1})(a,t.depth+1,h,g,p)&&(p+=12);p=d(p,u+8,l-24);const m=Math.max(1,p-s);return void v(e,[{x:s,y:r},{x:p,y:r},{x:p,y:o},{x:i,y:o}],d(.42*Math.min(m,c),16,52))}e.moveTo(s,r);const u=s+.5*(i-s),p=r+(o-r)*a.edgeCurve;return void e.quadraticCurveTo(u,p,i,o)}if(1===l){const c=Math.min(t.depth,n.depth),l=a.paddingX+c*a.layerGap+.5*a.layerGap;return e.moveTo(s,r),void e.bezierCurveTo(l,r,l,o,i,o)}const u=Math.sign(c),p=o-r,h=[{x:s,y:r}],g=a.paddingX+t.depth*a.layerGap+u*(.5*a.layerGap);h.push({x:g,y:r});for(let d=1;d<l;d+=1){const e=t.depth+u*d,n=a.paddingX+e*a.layerGap+u*(.5*a.layerGap),s=d/l;h.push({x:n,y:r+p*s})}const m=a.paddingX+n.depth*a.layerGap-u*(.5*a.layerGap);h.push({x:m,y:o}),h.push({x:i,y:o}),v(e,h,14)}function k(e,t,n,a){a&&t.highlighted?function(e,t,n){const a=t.renderX,s=t.renderY,r=n.renderX,i=n.renderY,o=r-a,c=i-s;if(e.moveTo(a,s),Math.abs(o)<18){const t=a+(s<=i?26:-26);return void e.bezierCurveTo(t,s,t,i,r,i)}const l=d(.44*Math.abs(o),42,150),u=Math.sign(o),p=d(.12*Math.abs(c),0,24);e.bezierCurveTo(a+u*l,s+p*Math.sign(c),r-u*l,i-p*Math.sign(c),r,i)}(e,t.from,t.to):y(e,t.from,t.to,n)}function b(e,t){return\`\${e}@\${t}\`}function w(e,t){return\`\${e}->\${t}\`}function C(e){if(!e||"object"!=typeof e)return!1;const t=e;if(!Array.isArray(t.workspaces))return!1;if(!t.dependencies||"object"!=typeof t.dependencies)return!1;const n=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e);return!!t.workspaces.every(e=>(e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&!!Array.isArray(t.directDependencies)&&!!Array.isArray(t.directDevDependencies)})(e))&&(!!t.workspaces.every(e=>n(e.directDependencies)&&n(e.directDevDependencies))&&!!Object.entries(t.dependencies).every(([,e])=>{if(!e||"object"!=typeof e)return!1;const t=e;return!(void 0!==t.dependencies&&!Array.isArray(t.dependencies))&&!(void 0!==t.workspaceOrigins&&!Array.isArray(t.workspaceOrigins))}))}function E(e){const t=e.compliance.license.declared?.valid?e.compliance.license.declared.spdxId:void 0;return t||(e.compliance.license.inferred?.spdxId||"Unknown")}function x(e){const t=e.security?.summary;return t?Number(t.critical||0)+Number(t.high||0)+Number(t.moderate||0)+Number(t.low||0):0}function S(e){const t=e.security?.summary?.highest;return"critical"===t||"high"===t?"high":"moderate"===t?"moderate":"none"}function L(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.parents.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function I(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.children.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function M(e,t,n){const a=new Map,s=[{slug:t,distance:0}];let r=0;for(;r<s.length;){const t=s[r++],i=e.nodes.get(t.slug);i&&i[n].forEach(e=>{a.has(e)||(a.set(e,t.distance+1),s.push({slug:e,distance:t.distance+1}))})}return a}function P(e){const t=function(e,t,n){const a=window.__DEPENDENCY_DATA__;if(C(a)){const e={};return Object.entries(a.dependencies).forEach(([t,n])=>{const a=n,s=a.vulnerabilitySeverity||a.vulnerabilityHighest||a.highestSeverity||"none",r=String(s).trim().toLowerCase();let i="none";"critical"===r||"high"===r?i="high":"moderate"!==r&&"medium"!==r||(i="moderate"),e[t]={slug:String(a.slug||t),name:String(a.name||t),version:String(a.version||""),dependencies:Array.isArray(a.dependencies)?a.dependencies.map(e=>String(e)):[],license:String(a.license||"Unknown"),vulnerabilityCount:Number(a.vulnerabilityCount||0),vulnerabilitySeverity:i,isDevOnly:Boolean(a.isDevOnly),workspaceOrigins:Array.isArray(a.workspaceOrigins)?a.workspaceOrigins.map(e=>String(e)):[]}}),{workspaces:a.workspaces,dependencies:e}}const s={},r=Object.values(e.dependencies||{});r.forEach(e=>{const t=b(e.package.name,e.package.version);s[t]={slug:t,name:e.package.name,version:e.package.version,dependencies:[],license:E(e),vulnerabilityCount:x(e),vulnerabilitySeverity:S(e),isDevOnly:"dev"===e.usage.scope,workspaceOrigins:e.usage.origins.workspaces||[]}}),r.forEach(e=>{const a=b(e.package.name,e.package.version),r=e.graph.subDeps;if(!r)return;const i=new Set;["dep","dev","opt","peer"].forEach(e=>{const o=r[e];o&&Object.values(o).forEach(e=>{const r=e[1];if(!r)return;const o=n(r);o&&t.has(o)&&s[o]&&o!==a&&i.add(o)})}),s[a].dependencies=[...i]});const i=new Map,o=e=>{const t=i.get(e);if(t)return t;const n={directDependencies:new Set,directDevDependencies:new Set};return i.set(e,n),n};return o("root"),(e.workspaces.workspacePackages||[]).forEach(e=>{o(e.name)}),r.forEach(e=>{if(!e.usage.direct)return;const t=b(e.package.name,e.package.version);(e.usage.origins.workspaces?.length?e.usage.origins.workspaces:["root"]).forEach(n=>{const a=o(n);"dev"===e.usage.scope?a.directDevDependencies.add(t):a.directDependencies.add(t)})}),{workspaces:[...i.entries()].map(([e,t])=>({name:e,directDependencies:[...t.directDependencies],directDevDependencies:[...t.directDevDependencies]})).sort((e,t)=>e.name.localeCompare(t.name)),dependencies:s}}(e.report,e.knownDepKeys,e.resolveDepKey),n=new Map(t.workspaces.map(e=>[e.name,e])),a=new Map,s=new Map;Object.values(t.dependencies).forEach(e=>{const n=(e.dependencies||[]).filter(n=>n!==e.slug&&Boolean(t.dependencies[n]));s.set(e.slug,n),n.forEach(t=>{const n=a.get(t)||[];n.push(e.slug),a.set(t,n)})});let r=null,i="",o=null,v=null,y=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,X=new Set,N=new Set,T=null,R=1,j=0,V=0,\$=1,H=.1,O=0,F=0,W=null,U=null,G=!1,_=!0,q=0,z=Math.max(1,Math.floor(window.devicePixelRatio||1)),K=1,J=1,Z=50;const Q={down:!1,moved:!1,startX:0,startY:0,startPanX:0,startPanY:0},ee={active:!1,startX1:0,startY1:0,startX2:0,startY2:0,startPanX:0,startPanY:0,startDist:0,startZoom:0,anchorX:null,anchorY:null},te={active:!1,velocityX:0,velocityY:0,lastSampleX:0,lastSampleY:0,lastSampleTime:0,lastFrameTime:0},ne=e.canvas.getContext("2d"),ae=Boolean(ne);let se=!1,re=!1,ie=!1,oe=null,ce=null,le=null,de=!1;const ue="function"==typeof window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null;let pe={runtime:"#10b981",runtimeHighlight:"#34d399",dev:"#f59e0b",devHighlight:"#fcd34d",transitive:"#06b6d4",transitiveHighlight:"#67e8f9",edge:"#64748b",highlight:"#22d3ee",muted:"#64748b",ringHigh:"#ef4444",ringModerate:"#f59e0b",label:"#e8edf5",backgroundPrimary:"#0c1222"};function he(){const e=m("--graph-direct-runtime")||"#10b981",t=m("--graph-direct-dev")||"#f59e0b",n=m("--graph-transitive")||"#06b6d4";pe={runtime:e,runtimeHighlight:g(e,.2,"#34d399"),dev:t,devHighlight:g(t,.28,"#fcd34d"),transitive:n,transitiveHighlight:g(n,.38,"#67e8f9"),edge:m("--graph-edge")||"#64748b",highlight:m("--graph-highlight")||"#22d3ee",muted:m("--graph-muted")||"#64748b",ringHigh:m("--graph-vuln-high")||"#ef4444",ringModerate:m("--graph-vuln-medium")||"#f59e0b",label:m("--text-primary")||"#e8edf5",backgroundPrimary:m("--bg-primary")||"#0c1222"}}function ge(){if(de)return;de=!0,console.warn("Dependency Radar: unable to initialize 2D canvas; graph rendering disabled."),e.controlsRoot.classList.add("hidden"),e.workspaceWrap.classList.add("hidden"),e.canvas.style.display="none";const t=document.createElement("div");t.className="empty-state";const n=document.createElement("div");n.className="empty-state-text",n.textContent="Graph view is unavailable in this browser context.",t.appendChild(n),e.canvasHost.appendChild(t)}function me(e){return(e-j)/R}function ve(e){return(e-V)/R}function fe(e,t){if(!r)return{x:e,y:t};const n=r.bounds.minX-120,a=r.bounds.maxX+120,s=r.bounds.minY-90,i=r.bounds.maxY+90,o=Math.min(.22*K,220),c=Math.min(.22*J,180),l=o-a*R,u=K-o-n*R,p=c-i*R,h=J-c-s*R;return{x:l>u? .5*(l+u):d(e,l,u),y:p>h? .5*(p+h):d(t,p,h)}}function ye(e,t){const n=fe(e,t);j=n.x,V=n.y}function ke(){W=null,U=null}function be(e,t,n){Ee(),ke();const a=d(e,H,c),s=me(t),r=ve(n);R=a,ye(t-s*R,n-r*R),_=!0,ze()}function we(e,t){Ee(),ke(),ye(j+e,V+t),_=!0,ze()}function Ce(){return!ue?.matches}function Ee(){te.active=!1,te.velocityX=0,te.velocityY=0,te.lastFrameTime=0}function xe(e,t,n){te.lastSampleX=e,te.lastSampleY=t,te.lastSampleTime=n}function Se(e,t,n){const a=n-te.lastSampleTime;if(a<=0)return void xe(e,t,n);const s=(e-te.lastSampleX)/a,r=(t-te.lastSampleY)/a;te.velocityX+=.22*(s-te.velocityX),te.velocityY+=.22*(r-te.velocityY),xe(e,t,n)}function Le(){Ce()?Math.hypot(te.velocityX,te.velocityY)<.08?Ee():(te.active=!0,te.lastFrameTime=performance.now(),Ve(!1),ze()):Ee()}function Ie(){const t=e.canvasHost.getBoundingClientRect();K=Math.max(1,Math.floor(t.width)),J=Math.max(1,Math.floor(t.height)),z=Math.max(1,Math.floor(window.devicePixelRatio||1)),e.canvas.width=K*z,e.canvas.height=J*z,e.canvas.style.width=\`\${K}px\`,e.canvas.style.height=\`\${J}px\`;const n=e.canvasHost.querySelector(".graph-overlay-top");Z=n?Math.ceil(n.getBoundingClientRect().height):50,e.canvasHost.style.setProperty("--graph-toolbar-height",\`\${Z}px\`),_=!0,ze()}function Me(){if(!r)return;const e=r.bounds;let t=e.maxX;ne&&(ne.save(),ne.font=l,r.nodes.forEach(e=>{const n=h(e);if(!n)return;const a=ne.measureText(n).width;t=Math.max(t,e.baseX+e.radius+6+a)}),ne.restore());const n=Math.max(1,e.maxY-e.minY),a=Math.max(1,K-32),s=Math.max(1,J-Z-24),i=a/Math.max(1,t-e.minX),o=s/n;\$=d(Math.min(i,o),.05,c),H=d(.64*\$,.05,c),O=16+.5*(a-Math.max(1,t-e.minX)*\$)-e.minX*\$,F=Z+12+.5*(s-n*\$)-e.minY*\$}function Pe(t,n){if(!r)return null;const a=e.canvas.getBoundingClientRect();if(t<a.left||t>a.right||n<a.top||n>a.bottom)return null;const s=me(t-a.left),i=ve(n-a.top);let o=null,c=1/0;return r.nodes.forEach(e=>{const t=s-e.renderX,n=i-e.renderY,a=Math.sqrt(t*t+n*n);a<=e.renderRadius+5&&a<c&&(c=a,o=e)}),o}function Be(t){e.canvas.classList.toggle("is-clickable",t&&!Q.down&&!ee.active)}function De(t=!1){Be(!1),t&&e.canvas.classList.remove("is-panning")}function Ae(e,t){const n=Pe(e,t);return He(n?n.slug:null),Be(Boolean(n)),n}function Ye(e){const r=n.get(e);if(!r)return null;const i=new Set(r.directDependencies.filter(e=>Boolean(t.dependencies[e]))),o=new Set(r.directDevDependencies.filter(e=>Boolean(t.dependencies[e]))),c=new Set([...i,...o]);0===c.size&&Object.keys(t.dependencies).filter(e=>0===(a.get(e)||[]).length).slice(0,40).forEach(e=>{c.add(e)});const l=new Set,d=[...c];let h=0;for(;h<d.length;){const e=d[h++];e&&(l.has(e)||t.dependencies[e]&&(l.add(e),(s.get(e)||[]).forEach(e=>{l.has(e)||d.push(e)})))}if(0===l.size)return null;const g=new Map;l.forEach(e=>{const n=i.has(e)?"direct-runtime":o.has(e)?"direct-dev":"transitive",a=Array.from(t.dependencies[e].name);g.set(e,{slug:e,ref:t.dependencies[e],labelGraphemes:a,parents:new Set,children:new Set,depth:Number.POSITIVE_INFINITY,order:0,amplification:0,kind:n,baseX:0,baseY:0,targetX:0,targetY:0,renderX:0,renderY:0,radius:8,targetRadius:8,renderRadius:8,targetLabelChars:u(a),renderLabelChars:p(a)})}),g.forEach(e=>{(a.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.parents.add(t)}),(s.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.children.add(t)})});const m=[];for(c.forEach(e=>{const t=g.get(e);t&&(t.depth=0,m.push(e))});m.length>0;){const e=m.shift();if(!e)continue;const t=g.get(e);t&&t.children.forEach(e=>{const n=g.get(e);if(!n)return;const a=t.depth+1;a>=n.depth||(n.depth=a,m.push(e))})}g.forEach(e=>{if(Number.isFinite(e.depth))return;let t=Number.POSITIVE_INFINITY;e.parents.forEach(e=>{const n=g.get(e);n&&Number.isFinite(n.depth)&&(t=Math.min(t,n.depth+1))}),e.depth=Number.isFinite(t)?t:0});const v=[...g.values()].reduce((e,t)=>Math.max(e,t.depth),0),f=Array.from({length:v+1},()=>[]);g.forEach(e=>{f[e.depth].push(e.slug)});const y=[];g.forEach(e=>{e.children.forEach(t=>{y.push({from:e.slug,to:t,direct:0===e.depth})})});const k={workspaceName:e,nodes:g,edges:y,layers:f,directRuntime:i,directDev:o,directAll:new Set([...i,...o]),bounds:{minX:0,maxX:1,minY:0,maxY:1}};return Xe(k),Ne(k),k}function Xe(e){e.nodes.forEach(e=>{e.amplification=0}),e.nodes.forEach(t=>{if(0!==t.depth)return;if(!e.directAll.has(t.slug))return;const n=new Set,a=[...t.children];for(;a.length>0;){const s=a.pop();if(!s)continue;if(s===t.slug)continue;if(n.has(s))continue;n.add(s);const r=e.nodes.get(s);r&&r.children.forEach(e=>{n.has(e)||a.push(e)})}t.amplification=n.size})}function Ne(e){const t=new Map;e.layers.forEach((n,a)=>{0===a?n.sort((t,n)=>{const a=e.nodes.get(t),s=e.nodes.get(n);if(!a&&!s)return 0;if(!a)return 1;if(!s)return-1;if(a.amplification!==s.amplification)return s.amplification-a.amplification;if(a.kind!==s.kind){if("direct-runtime"===a.kind)return-1;if("direct-runtime"===s.kind)return 1}return a.ref.name.localeCompare(s.ref.name)}):n.sort((n,a)=>{const s=e.nodes.get(n),r=e.nodes.get(a);if(!s&&!r)return 0;if(!s)return 1;if(!r)return-1;const i=(()=>{let e=0,n=0;return s.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})(),o=(()=>{let e=0,n=0;return r.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})();return i!==o?i-o:s.ref.name.localeCompare(r.ref.name)}),n.forEach((e,n)=>{t.set(e,n)})});const n=e.layers.reduce((e,t)=>Math.max(e,t.length),1);e.bounds={minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY},e.layers.forEach((t,a)=>{const s=Math.max(0,43*(t.length-1)),r=64+.5*(43*n-s);t.forEach((t,n)=>{const s=e.nodes.get(t);if(!s)return;s.order=n,s.baseX=96+240*a,s.baseY=r+43*n,s.targetX=s.baseX,s.targetY=s.baseY,s.renderX=s.baseX,s.renderY=s.baseY;const i=.55*Math.log(s.children.size+s.parents.size+1),o=0===s.depth&&e.directAll.has(s.slug)?1.05*Math.log(s.amplification+1):0;s.radius=6.7+i+o,s.targetRadius=s.radius,s.renderRadius=s.radius,s.targetLabelChars=u(s.labelGraphemes),s.renderLabelChars=p(s.labelGraphemes),e.bounds.minX=Math.min(e.bounds.minX,s.baseX),e.bounds.maxX=Math.max(e.bounds.maxX,s.baseX),e.bounds.minY=Math.min(e.bounds.minY,s.baseY),e.bounds.maxY=Math.max(e.bounds.maxY,s.baseY)})}),Number.isFinite(e.bounds.minX)||(e.bounds={minX:0,maxX:1,minY:0,maxY:1})}function Te(e,t){if(!r)return;const n=d(Math.max(R,1.35*\$),H,c);R+=(n-R)*(ue?.matches?1:.35),function(e,t){const n=fe(e,t);W=n.x,U=n.y}(.46*K-e*R,.5*J-t*R)}function Re(e){if(!r||!r.nodes.has(e))return;Ee(),o=e;const t=L(r,e),n=I(r,e);y=new Set([e]),t.forEach(e=>{y.add(e)}),n.forEach(e=>{y.add(e)}),P=new Set;const a=[e],s=new Set([e]);for(;a.length>0;){const e=a.pop();if(!e)continue;const t=r.nodes.get(e);t&&t.parents.forEach(t=>{P.add(w(t,e)),s.has(t)||(s.add(t),a.push(t))})}const i=[e],c=new Set([e]);for(;i.length>0;){const e=i.pop();if(!e)continue;const t=r.nodes.get(e);t&&t.children.forEach(t=>{P.add(w(e,t)),c.has(t)||(c.add(t),i.push(t))})}B=new Set(y);const l=r.nodes.get(e);l.parents.forEach(e=>{B.add(e)}),l.children.forEach(e=>{B.add(e)});const u=null===A||null===Y,p=!u&&Boolean(T)&&y.has(T);!u&&p||(A=l.renderX,Y=l.renderY),D=function(e,t,n,a){const s=new Map,r=M(e,t,"parents"),i=M(e,t,"children"),o=new Map;return s.set(t,{x:n,y:a}),y.forEach(a=>{if(a===t)return;const s=e.nodes.get(a);if(!s)return;const c=r.get(a),l=i.get(a);let d=0;"number"==typeof c&&("number"!=typeof l||c<=l)?d=-c:"number"==typeof l&&(d=l),0===d&&(d=s.baseX<n?-1:1);const u=o.get(d)||[];u.push(s),o.set(d,u)}),o.forEach((e,t)=>{e.sort((e,n)=>{const a=t<0?r.get(e.slug)||0:i.get(e.slug)||0,s=t<0?r.get(n.slug)||0:i.get(n.slug)||0;return a!==s?a-s:e.baseY!==n.baseY?e.baseY-n.baseY:e.ref.name.localeCompare(n.ref.name)});const o=d(760/Math.max(1,e.length-1),34,54),c=a-(e.length-1)*o*.5;e.forEach((e,a)=>{const r=170*(1+.78*Math.max(0,Math.abs(t)-1));s.set(e.slug,{x:n+Math.sign(t)*r,y:c+a*o})})}),s}(r,e,A??l.renderX,Y??l.renderY),Te(A??l.renderX,Y??l.renderY),_=!0,ze()}function je(){o=null,y=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,ke(),_=!0,ze()}function Ve(e=!0){v=null,X=new Set,N=new Set,e&&(_=!0,ze())}function \$e(){if(!r)return;const e=o&&r.nodes.get(o)||null;r.nodes.forEach(t=>{t.targetRadius=function(e){const t=o===e.slug,n=y.has(e.slug);let a=e.radius;t?a*=1.85:o&&n?a*=1.22:o&&!n?a*=.84:v&&X.has(e.slug)?a*=1.1:v&&(a*=.9);return a}(t),t.targetLabelChars=u(t.labelGraphemes,Boolean(o)&&y.has(t.slug)||!o&&Boolean(v)&&X.has(t.slug));const n=D.get(t.slug);if(e&&n)return t.targetX=n.x,void(t.targetY=n.y);if(!e||!B.has(t.slug))return t.targetX=t.baseX,void(t.targetY=t.baseY);const a=t.baseX-e.baseX,s=t.baseY-e.baseY,r=1+120/(Math.sqrt(a*a+s*s)+1);t.targetX=e.baseX+a*r,t.targetY=e.baseY+s*r})}function He(e){if(o)return;if(v=e,X=new Set,N=new Set,!r||!e||!r.nodes.has(e))return _=!0,void ze();const t=L(r,e),n=I(r,e);X=new Set([e]),t.forEach(e=>{X.add(e)}),n.forEach(e=>{X.add(e)});const a=r.nodes.get(e);a&&(a.parents.forEach(e=>{X.add(e)}),a.children.forEach(e=>{X.add(e)})),r.edges.forEach(e=>{X.has(e.from)&&X.has(e.to)&&N.add(w(e.from,e.to))}),_=!0,ze()}function Oe(t){if(!r)return;const n=r.nodes.get(t);if(!n)return;const a=0===n.depth&&r.directAll.has(n.slug);T=t,e.popoverName.textContent=n.ref.name,e.popoverVersion.textContent=\`Version: \${n.ref.version}\`,e.popoverLicense.textContent=\`License: \${n.ref.license||"Unknown"}\`,e.popoverVulns.textContent=\`Vulnerabilities: \${n.ref.vulnerabilityCount||0}\`,e.popoverAmplification.textContent=a?\`Amplification: \${n.amplification}\`:\`Dependencies: \${n.children.size} • Dependents: \${n.parents.size}\`,e.popover.hidden=!1,We()}function Fe(){T=null,e.popover.hidden=!0}function We(){if(!r||!T||e.popover.hidden)return;const t=r.nodes.get(T);if(!t)return void Fe();const n=t.renderX*R+j,a=t.renderY*R+V,s=e.canvasHost.getBoundingClientRect(),i=e.popover.getBoundingClientRect(),o=Math.max(8,s.width-i.width-8),c=Math.max(8,s.height-i.height-8),l=d(n+14,8,o),u=d(a+14,8,c);e.popover.style.left=\`\${l}px\`,e.popover.style.top=\`\${u}px\`}function Ue(e){return o?y.has(e)?1:.14:v?X.has(e)?1:.16:.95}function Ge(){if(!ne)return;if(ne.setTransform(z,0,0,z,0,0),ne.clearRect(0,0,K,J),!r)return;const e=r,t=me(0)-80,n=me(K)+80,a=ve(0)-80,s=ve(J)+80;ne.setTransform(z*R,0,0,z*R,z*j,z*V);const i=pe.runtime,c=pe.dev,u=pe.transitive,p=pe.edge,g=pe.highlight,m=pe.muted,b=pe.ringHigh,C=pe.ringModerate,E=pe.label,x=pe.backgroundPrimary,S=new Set;e.nodes.forEach(e=>{const r=Math.max(e.radius,e.renderRadius);e.renderX+r>=t&&e.renderX-r<=n&&e.renderY+r>=a&&e.renderY-r<=s&&S.add(e.slug)});const L=[];let I=0;e.nodes.forEach(e=>{if(!S.has(e.slug))return;let t=0;o===e.slug?t=2:(y.has(e.slug)||X.has(e.slug))&&(t=1),L.push({node:e,priority:t,order:I++})}),L.sort((e,t)=>e.priority-t.priority||e.order-t.order);const M=Math.max(0,e.layers.length-1),B={depthNodeIndex:f(e),maxDepth:M,sameColumnXThreshold:6,minDetourVerticalSpan:80,detourInset:14,detourNodeClearance:26,paddingX:96,layerGap:240,edgeCurve:.2},D=[];e.edges.forEach(t=>{const n=e.nodes.get(t.from),a=e.nodes.get(t.to);if(!n||!a)return;if(!S.has(n.slug)&&!S.has(a.slug))return;const s=w(t.from,t.to);D.push({from:n,to:a,highlighted:P.has(s)||!o&&N.has(s),span:Math.abs(a.depth-n.depth)})}),D.sort((e,t)=>t.span-e.span),ne.globalCompositeOperation="source-over",ne.strokeStyle=o||v?m:p,ne.lineWidth=1.05,ne.globalAlpha=o||v? .04*d((R-.35)/.9,.75,1):.25*d((R-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted||k(ne,e,B,Boolean(o))}),ne.stroke(),ne.globalCompositeOperation="lighter",ne.strokeStyle=g,ne.lineWidth=1.2,ne.globalAlpha=.36*d((R-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted&&k(ne,e,B,Boolean(o))}),ne.stroke(),ne.globalCompositeOperation="source-over";const A=e=>{const t=o===e.slug,n=e.renderRadius;ne.globalAlpha=1,ne.fillStyle=x,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),ne.globalAlpha=Ue(e.slug);const a=ne.createRadialGradient(e.renderX-.3*n,e.renderY-.3*n,0,e.renderX,e.renderY,1.2*n);"direct-runtime"===e.kind?(a.addColorStop(0,pe.runtimeHighlight),a.addColorStop(1,i)):"direct-dev"===e.kind?(a.addColorStop(0,pe.devHighlight),a.addColorStop(1,c)):(a.addColorStop(0,pe.transitiveHighlight),a.addColorStop(1,u)),ne.fillStyle=a,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),t&&(ne.globalAlpha=.95,ne.strokeStyle=g,ne.lineWidth=1.5,ne.beginPath(),ne.arc(e.renderX,e.renderY,n+4,0,2*Math.PI),ne.stroke())},Y=e=>{if(!e.ref.vulnerabilityCount||e.ref.vulnerabilityCount<=0)return;if("none"===e.ref.vulnerabilitySeverity)return;const t=e.renderRadius,n="high"===e.ref.vulnerabilitySeverity?b:C;var a;ne.save(),ne.translate(e.renderX,e.renderY),ne.globalAlpha=(a=e.slug,o?y.has(a)? .78:.11:v?X.has(a)? .76:.12:.8),ne.strokeStyle=n;const s=t/e.radius,r=t/3*1.2/12,i=1.2*r+3*(s-1),c=Math.max(.5*r,.15),l=Math.max(1*r,.3),d=Math.max(3*r,.8),u=Math.max(1*r,.3),p=Math.max(.5*r,.15),h=t+(2+6*(s-1))+c/2,g=h+c/2+i+l/2,m=g+l/2+i+d/2,f=m+d/2+i+u/2,k=f+u/2+i+p/2;ne.setLineDash([]),ne.lineWidth=p,ne.beginPath(),ne.arc(0,0,k,0,2*Math.PI),ne.stroke(),ne.lineWidth=u,ne.beginPath(),ne.arc(0,0,f,0,2*Math.PI),ne.stroke(),ne.lineWidth=d,ne.beginPath(),ne.arc(0,0,m,0,2*Math.PI),ne.stroke(),ne.lineWidth=l,ne.beginPath(),ne.arc(0,0,g,0,2*Math.PI),ne.stroke(),ne.lineWidth=c,ne.beginPath(),ne.arc(0,0,h,0,2*Math.PI),ne.stroke(),ne.restore()};for(const r of[0,1,2])L.forEach(({node:e,priority:t})=>{t===r&&A(e)}),L.forEach(({node:e,priority:t})=>{t===r&&Y(e)});ne.textBaseline="middle",ne.font=l,ne.fillStyle=E,L.forEach(({node:e})=>{(e=>{const t=h(e);t&&(ne.globalAlpha=Ue(e.slug),ne.fillText(t,e.renderX+e.renderRadius+6,e.renderY))})(e)}),ne.globalAlpha=1,We()}function _e(){if(!G)return void(q=0);\$e();const e=function(){if(!r)return!1;let e=!1;const t=ue?.matches;return r.nodes.forEach(n=>{if(t)return n.renderX=n.targetX,n.renderY=n.targetY,n.renderRadius=n.targetRadius,void(n.renderLabelChars=n.targetLabelChars);const a=o? .18:.15;n.renderX+=(n.targetX-n.renderX)*a,n.renderY+=(n.targetY-n.renderY)*a,n.renderRadius+=.18*(n.targetRadius-n.renderRadius),n.renderLabelChars+=.32*(n.targetLabelChars-n.renderLabelChars),Math.abs(n.targetX-n.renderX)<.06&&Math.abs(n.targetY-n.renderY)<.06&&Math.abs(n.targetRadius-n.renderRadius)<.04&&Math.abs(n.targetLabelChars-n.renderLabelChars)<.12||(e=!0)}),e}(),t=function(e){if(!te.active)return!1;if(!Ce())return Ee(),!1;const t=d(e-te.lastFrameTime||16,1,32);te.lastFrameTime=e,ye(j+te.velocityX*t,V+te.velocityY*t);const n=Math.exp(-.0042*t);return te.velocityX*=n,te.velocityY*=n,_=!0,!(Math.hypot(te.velocityX,te.velocityY)<.02&&(Ee(),1))}(performance.now()),n=null!==W&&null!==U&&(ue?.matches?(ye(W,U),ke(),_=!0,!1):(j+=.12*(W-j),V+=.12*(U-V),ye(j,V),Math.abs((W??j)-j)<.35&&Math.abs((U??V)-V)<.35?(ye(W,U),ke(),_=!0,!1):(_=!0,!0)));if(_||e||t||n)return Ge(),_=!1,void(q=G&&(_||e||t||n)?window.requestAnimationFrame(_e):0);q=0}function qe(){G&&!q&&_&&(q=window.requestAnimationFrame(_e))}function ze(){_=!0,G&&qe()}function Ke(e){const t=Ye(e);t&&(Ee(),i=e,r=t,je(),Fe(),v=null,X=new Set,N=new Set,De(!0),r&&(Ee(),ke(),Me(),R=\$,ye(O,F)),_=!0,ze())}function Je(t){0===t.button&&(Ee(),ke(),Q.down=!0,Q.moved=!1,Q.startX=t.clientX,Q.startY=t.clientY,Q.startPanX=j,Q.startPanY=V,xe(t.clientX,t.clientY,t.timeStamp),De(),e.canvas.classList.add("is-panning"))}function Ze(e){if(!Q.down)return void Ae(e.clientX,e.clientY);const t=e.clientX-Q.startX,n=e.clientY-Q.startY;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(Q.startPanX+t,Q.startPanY+n),Se(e.clientX,e.clientY,e.timeStamp),ze()}function Qe(t){if(!Q.down)return;e.canvas.classList.remove("is-panning");const n=Q.moved;if(Q.down=!1,Q.moved=!1,n)return Le(),te.active?void Be(!1):void Ae(t.clientX,t.clientY);const a=Ae(t.clientX,t.clientY);if(!a)return Ve(!1),je(),void Fe();Re(a.slug),Oe(a.slug)}function et(t){if(!e.canvasHost.contains(t.target))return;t.preventDefault(),Ee();const n=e.canvas.getBoundingClientRect(),a=t.clientX-n.left,s=t.clientY-n.top,r=t.ctrlKey||t.metaKey? .015*t.deltaY:.002*t.deltaY,i=Math.exp(-r);be(R*i,a,s)}function tt(t){if(0===t.touches.length)return;t.preventDefault(),Ee(),ke(),De();const n=e.canvas.getBoundingClientRect();if(1===t.touches.length)ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startPanX=j,ee.startPanY=V,xe(t.touches[0].clientX,t.touches[0].clientY,t.timeStamp),e.canvas.classList.add("is-panning");else if(2===t.touches.length){ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startX2=t.touches[1].clientX,ee.startY2=t.touches[1].clientY;const e=ee.startX2-ee.startX1,a=ee.startY2-ee.startY1;ee.startDist=Math.sqrt(e*e+a*a),ee.startZoom=R;const s=(ee.startX1+ee.startX2)/2,r=(ee.startY1+ee.startY2)/2,i=s-n.left,o=r-n.top;ee.anchorX=i,ee.anchorY=o}}function nt(e){if(ee.active)if(e.preventDefault(),1===e.touches.length){const t=e.touches[0].clientX-ee.startX1,n=e.touches[0].clientY-ee.startY1;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(ee.startPanX+t,ee.startPanY+n),Se(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp),ze()}else if(2===e.touches.length){Ee(),Q.moved=!0;const t=e.touches[0].clientX,n=e.touches[0].clientY,a=e.touches[1].clientX-t,s=e.touches[1].clientY-n,r=Math.sqrt(a*a+s*s);if(ee.startDist>0){const e=r/ee.startDist;be(ee.startZoom*e,ee.anchorX??K/2,ee.anchorY??J/2)}}}function at(e){if(ee.active){if(e.preventDefault(),"touchcancel"===e.type)return Ee(),De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,void(Q.moved=!1);if(0===e.touches.length){if(De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,Q.moved||1!==e.changedTouches.length)Q.moved&&Le();else{const t=Pe(e.changedTouches[0].clientX,e.changedTouches[0].clientY);t?(Re(t.slug),Oe(t.slug)):(Ve(!1),je(),Fe())}Q.moved=!1}else 1===e.touches.length&&(ee.startX1=e.touches[0].clientX,ee.startY1=e.touches[0].clientY,ee.startPanX=j,ee.startPanY=V,xe(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp))}}function st(){He(null),De()}function rt(t){if(!G)return;const n=t.target;e.popover.hidden||e.popover.contains(n)||e.canvasHost.contains(n)||Fe()}function it(e){const t=e.target.closest("button[data-action]");if(!t)return;const n=t.dataset.action;n&&("zoom-in"!==n?"zoom-out"!==n?"pan-left"!==n?"pan-right"!==n?"pan-up"!==n?"pan-down"!==n?"reset"===n&&(Ee(),R=\$,ye(O,F),je(),Fe(),ze()):we(0,52):we(0,-52):we(52,0):we(-52,0):be(R/1.18,.5*K,.5*J):be(1.18*R,.5*K,.5*J))}function ot(){T&&e.onOpenList(T)}function ct(){Ke(e.workspaceSelect.value)}function lt(){G&&(Ie(),K<=1||J<=1||(Me(),R=d(R,H,c),ye(j,V),ze()))}function dt(){ie||(e.workspaceSelect.addEventListener("change",ct),ie=!0),re||(e.controlsRoot.addEventListener("click",it),e.popoverOpenButton.addEventListener("click",ot),re=!0)}return{initGraphView:function(){const a=t.workspaces.length?t.workspaces:[{name:"root",directDependencies:[],directDevDependencies:[]}],s=a.find(e=>"root"===e.name),r=s?[s,...a.filter(e=>"root"!==e.name)]:a;e.workspaceSelect.textContent="",r.forEach((t,n)=>{const a=document.createElement("option");if(a.value=t.name,a.textContent="root"===t.name?"Workspace root":t.name,e.workspaceSelect.appendChild(a),"root"===t.name&&r.length>1&&0===n){const t=document.createElement("option");t.disabled=!0,t.textContent="──────────────",e.workspaceSelect.appendChild(t)}}),e.workspaceWrap.classList.toggle("hidden",a.length<=1),n.has("root")||1!==a.length||n.set("root",a[0]),i=r[0].name,e.workspaceSelect.value=i,he(),function(){if(oe&&oe.disconnect(),oe=new MutationObserver(()=>{he(),ze()}),oe.observe(document.documentElement,{attributes:!0,attributeFilter:["class","data-theme"]}),ce&&(ce.disconnect(),ce=null),le&&(window.removeEventListener("resize",le),le=null),"undefined"!=typeof ResizeObserver)return ce=new ResizeObserver(lt),void ce.observe(e.canvasHost);le=lt,window.addEventListener("resize",le)}(),dt(),ae?(Ie(),Ke(i)):ge()},buildWorkspaceGraph:Ye,computeAmplification:Xe,layoutGraph:Ne,renderLoop:qe,applyFocus:Re,clearFocus:je,showPopover:Oe,hidePopover:Fe,switchWorkspace:Ke,setActive:function(t){if(G=t,G)return ae?(!se&&ae&&(e.canvas.addEventListener("mousedown",Je),window.addEventListener("mousemove",Ze),window.addEventListener("mouseup",Qe),e.canvas.addEventListener("wheel",et,{passive:!1}),e.canvas.addEventListener("touchstart",tt,{passive:!1}),window.addEventListener("touchmove",nt,{passive:!1}),window.addEventListener("touchend",at,{passive:!1}),window.addEventListener("touchcancel",at,{passive:!1}),e.canvas.addEventListener("mouseleave",st),document.addEventListener("mousedown",rt),se=!0),Ie(),K>1&&J>1&&(Me(),R=d(R,H,c),ye(j,V)),qe(),void ze()):void ge();se&&(e.canvas.removeEventListener("mousedown",Je),window.removeEventListener("mousemove",Ze),window.removeEventListener("mouseup",Qe),e.canvas.removeEventListener("wheel",et),e.canvas.removeEventListener("touchstart",tt),window.removeEventListener("touchmove",nt),window.removeEventListener("touchend",at),window.removeEventListener("touchcancel",at),e.canvas.removeEventListener("mouseleave",st),document.removeEventListener("mousedown",rt),De(!0),Q.down=!1,Q.moved=!1,ee.active=!1,ee.anchorX=null,ee.anchorY=null,Ee(),se=!1),Ee(),q&&(window.cancelAnimationFrame(q),q=0)},requestRender:ze}}var B={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]},D={"network-access":"Accesses the network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"},A={"bundled-dependencies":"Declares bundled dependencies","embedded-shrinkwrap":"Contains embedded npm-shrinkwrap.json"},Y={"recent-package":"Recently created package","recent-version":"Recently published installed version","low-release-history":"Low release history","reactivated-package":"Reactivated after dormancy","old-major-new-patch":"Recent patch on older major line"};function X(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function N(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function T(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function R(e){return e?.highest||"none"}function j(e){return e&&e.risk||"green"}var V={permissive:"green",weakCopyleft:"amber",strongCopyleft:"red",unknown:"gray"},\$={none:0,low:1,moderate:2,high:3,critical:4},H=[{id:"type",label:"Type",sortKey:"type",getValue:e=>e.usage.direct?"Dependency":"Sub-Dependency",getTone:e=>e.usage.direct?"green":"amber",sortFn:(e,t)=>e.usage.direct===t.usage.direct?0:e.usage.direct?-1:1},{id:"scope",label:"Scope",sortKey:"scope",getValue:e=>{return"runtime"===(t=e.usage.scope)?"Runtime":"dev"===t?"Dev":"optional"===t?"Optional":"peer"===t?"Peer":t;var t},getTone:e=>"runtime"===e.usage.scope?"green":"dev"===e.usage.scope||"optional"===e.usage.scope?"amber":"gray",sortFn:(e,t)=>e.usage.scope.localeCompare(t.usage.scope)},{id:"license",label:"License",sortKey:"license",getValue:e=>{const t=N(e),n=t.isInferred?\`\${t.value} (inferred)\`:t.value;return"mismatch"===e.compliance.license.status?\`\${n} *\`:n},getTone:e=>{const t=function(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(B))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}(N(e).value);return V[t]},sortFn:(e,t)=>{const n=N(e).value,a=N(t).value;return n.localeCompare(a)}},{id:"vulns",label:"Vulnerabilities",sortKey:"severity",getValue:e=>X(R(T(e).summary)),getTone:e=>T(e).summary.risk,sortFn:(e,t)=>\$[R(T(t).summary)]-\$[R(T(e).summary)]},{id:"install",label:"Install",sortKey:"install",getValue:e=>{return(t=e.execution)?X(t.risk||"low"):"Low";var t},getTone:e=>j(e.execution),sortFn:(e,t)=>{const n={green:0,amber:1,red:2},a=j(e.execution),s=j(t.execution);return n[a]-n[s]}},{id:"maintenance",label:"Maintenance",sortKey:"maintenance",getValue:e=>F(e.maintenance?.status),getTone:e=>{return t=e.maintenance?.status,"deprecated"===t||"archived"===t?"red":"unmaintained"===t||"stale"===t||"slowing"===t?"amber":"active"===t?"green":"gray";var t},sortFn:(e,t)=>W(t.maintenance?.status)-W(e.maintenance?.status)}],O={deprecated:"Deprecated",archived:"Archived",unmaintained:"Unmaintained",stale:"Stale",slowing:"Slowing",active:"Active",unknown:"—"};function F(e){return e&&O[e]||"—"}function W(e){return e&&{deprecated:6,archived:5,unmaintained:4,stale:3,slowing:2,active:1}[e]||0}function U(e){const t=e.maintenance?.status;return"deprecated"===t||"archived"===t||"unmaintained"===t||"stale"===t||"slowing"===t}function G(e){return Boolean(e.replacement?.replacements?.length)}function _(e){return"green"!==e.compliance.licenseRisk}function q(e){return Boolean(e.upgrade.blocksNodeMajor||e.upgrade.blockers?.length)}var z=H.length;function K(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(B))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}function J(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function Z(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}var Q={none:0,low:1,moderate:2,high:3,critical:4};function ee(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function te(e){return e?"Yes":"No"}function ne(e){return e?String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}function ae(e){return null!=e&&("string"==typeof e?e.trim().length>0:Array.isArray(e)?e.length>0:"object"!=typeof e||Object.keys(e).length>0)}function se(e){return Array.isArray(e)?e.map(e=>se(e)).join(", "):"boolean"==typeof e?e?"Yes":"No":"object"==typeof e&&null!==e?Object.entries(e).filter(([,e])=>ae(e)).map(([e,t])=>ne(e)+": "+se(t)).join("<br>"):ne(String(e))}function re(e,t){return ae(t)?'<div class="metadata-row"><div class="metadata-row-label">'+ne(e)+'</div><div class="metadata-row-value">'+se(t)+"</div></div>":""}function ie(e,t){const n=t.filter(Boolean);return 0===n.length?"":'<section class="metadata-section"><div class="metadata-section-title">'+ne(e)+'</div><div class="metadata-grid">'+n.join("")+"</div></section>"}function oe(e){const t=e.workspaces;if(!t||!t.enabled)return ie("Workspaces",[re("Enabled",!1),re("Type",t?.type)]);const n=t.workspacePackages||[],a=n.length?'<div class="metadata-list">'+n.map(e=>'<div class="metadata-list-item"><div class="metadata-row-value">'+ne(e.name)+'</div><div class="metadata-muted">'+ne(e.relativePath)+" · runtime "+ne(String(e.directExternal.runtime))+" · dev "+ne(String(e.directExternal.dev))+"</div></div>").join("")+"</div>":"";return ie("Workspaces",[re("Enabled",t.enabled),re("Type",t.type),re("Package count",t.packageCount),a?'<div class="metadata-row"><div class="metadata-row-label">Packages</div><div>'+a+"</div></div>":""])}function ce(e){const t=e.supplyChain;if(!t)return"";const n=t.signatureAudit;return ie("Supply Chain",[re("Signals",t.signals?.length),n?re("Signature audit",{attempted:n.attempted,ok:n.ok,status:n.status,error:n.error}):""])}function le(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e}function de(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function ue(e){return e.split(/[\\s-_]+/).map(e=>e?de(e):e).join(" ")}function pe(e){return H.map(t=>{return n=t.label,a=t.getValue(e),'<div class="badge-card '+t.getTone(e)+'"><span class="badge-label">'+ne(n)+'</span><span class="badge-value">'+ne(a)+"</span></div>";var n,a}).join("")}function he(e,t){const n=H.map(n=>function(e,t,n,a){const s=n===e,r=s?a?" ▲":" ▼":"",i=s?a?" sorted-asc":" sorted-desc":"";return'<button type="button" class="column-header'+(s?" sorted":"")+i+'" data-sort="'+ne(e)+'"><span class="column-header-label">'+ne(t)+'</span><span class="sort-indicator">'+r+"</span></button>"}(n.sortKey,n.label,e,t)).join("");return'<div class="column-headers" style="--column-count: '+z+'">'+n+"</div>"}function ge(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+ne(e)+"</span>",a+='<span class="kv-value">'+ne(String(t))+"</span>",n&&(a+='<span class="kv-hint">'+ne(n)+"</span>"),a+="</div>",a}function me(e,t){return'<span class="kv-value risk-value"><span class="risk-dot '+t+'"></span>'+ne(String(e))+"</span>"}function ve(e,t="neutral"){return'<span class="status-chip '+t+'">'+ne(e)+"</span>"}function fe(e,t,n){const s=a(t),r=e.execution?.risk||"green",i=e.upgrade.blocksNodeMajor||!!e.upgrade.blockers?.length;return'<div class="status-chip-strip">'+[ve(e.usage.direct?"Direct dependency":"Transitive dependency"),ve(le(e.usage.scope)),ve(s>0?"Vulnerability: "+ue(t.highest):"Vulnerability: None","green"===t.risk?"neutral":t.risk),ve("Licence: "+n,"green"===e.compliance.licenseRisk?"neutral":e.compliance.licenseRisk),ve("Install risk: "+Ye(r),"green"===r?"neutral":r),ve(i?"Upgrade blocker":"No upgrade blocker",i?"amber":"neutral")].join("")+"</div>"}function ye(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+ne(e)+"</span>",a+=t,n&&(a+='<span class="kv-hint">'+ne(n)+"</span>"),a+="</div>",a}function ke(e,t){if(!e||0===e.length)return'<span class="kv-value">None</span>';const n=e.slice(0,t),a=e.length-t;let s='<div class="package-list">';return n.forEach(e=>{s+='<span class="package-tag">'+ne(e)+"</span>"}),a>0&&(s+='<span class="package-tag">+'+a+" more</span>"),s+="</div>",s}function be(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{const t=Ie(e,n,a);i+=t?'<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(t))+'" data-dep-key="'+ne(t)+'" aria-label="Jump to dependency '+ne(t)+'">'+ne(e)+"</a>":'<span class="package-tag">'+ne(e)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function we(e,t){return e+"@"+t}var Ce=new WeakMap;function Ee(e){const t=e.lastIndexOf("@npm:");if(t>0)return{name:e.slice(0,t),version:e.slice(t+1)};const n=e.lastIndexOf("@");return n<=0?null:{name:e.slice(0,n),version:e.slice(n+1)}}function xe(e){return\`dep-\${e}\`}function Se(e){const t=Ce.get(e);if(t)return t;const n=new Map;return e.forEach(e=>{const t=Ee(e);if(!t)return;const a=n.get(t.name)||[];a.push(e),n.set(t.name,a)}),Ce.set(e,n),n}function Le(e,t,n){const a=((n||Se(t)).get(e)||[]).filter(e=>t.has(e));return 1===a.length?a[0]:null}function Ie(e,t,n){if(t.has(e))return e;const a=Ee(e);if(!a)return Le(e,t,n);if(a.version.startsWith("npm:")){const e=a.version.slice(4),n=a.name+(e.startsWith("@")?e:"@"+e);if(t.has(n))return n}return Le(a.name,t,n)}function Me(e,t){if(t.has(e))return e;const n=Ee(e);if(!n)return null;if(n.version.startsWith("npm:")){const e=n.version.slice(4),a=n.name+(e.startsWith("@")?e:"@"+e);if(t.has(a))return a}return null}function Pe(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{if("string"==typeof e){const t=Ie(e,n,a);return t?void(i+='<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(t))+'" data-dep-key="'+ne(t)+'" aria-label="Jump to dependency '+ne(t)+'">'+ne(e)+"</a>"):void(i+='<span class="package-tag">'+ne(e)+"</span>")}const t=we(e.name,e.version),s=e.name+"@"+e.version,r=Ie(t,n,a);i+=r?'<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(r))+'" data-dep-key="'+ne(r)+'" aria-label="Jump to dependency '+ne(r)+'">'+ne(s)+"</a>":'<span class="package-tag">'+ne(s)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function Be(e,t,n){const a=e.graph.subDeps;if(!a)return"";const s=[{title:"Dependencies",key:"dep"},{title:"Optional",key:"opt"},{title:"Peer",key:"peer"},{title:"Dev Dependencies",key:"dev"}];let r=0,i=0;for(const l of s){const e=a[l.key];if(e)for(const t of Object.values(e))r+=1,t[1]&&(i+=1)}if(0===r)return"";const o='<div class="declared-summary">Total: '+r+" • Installed: "+i+" • Not installed: "+(r-i)+"</div>",c=s.map(e=>{const s=a[e.key];if(!s||0===Object.keys(s).length)return"";let r=0,i=0;const o=Object.entries(s).sort(([e],[t])=>e.localeCompare(t)).map(([e,[a,s]])=>{r+=1,s&&(i+=1);const o='<div class="declared-name">'+ne(e)+"</div>",c='<div class="declared-range">'+ne(a)+"</div>",l=s?function(e,t,n){const a=Ie(e,t,n);return a?'<a class="status-pill installed root-package-link" href="#'+ne(xe(a))+'" data-dep-key="'+ne(a)+'" aria-label="Jump to dependency '+ne(a)+'">Installed</a>':'<span class="status-pill installed">Installed</span>'}(s,t,n):'<span class="status-pill missing">Not installed</span>';return'<div class="declared-row">'+o+c+l+"</div>"}),c=i+" of "+r+" installed";return['<details class="declared-group">','<summary class="declared-group-summary"><span class="expand-icon" aria-hidden="true"></span><span class="declared-group-title">'+ne(e.title)+' <span class="declared-count">('+c+")</span></span></summary>",'<div class="declared-table">'+o.join("")+"</div>","</details>"].join("")}).filter(Boolean);return De("Declared Dependencies","Dependencies declared by this package",o+'<div class="declared-deps">'+c.join("")+"</div>")}function De(e,t,n){let a='<div class="section">';return a+='<div class="section-header">',a+='<span class="section-title">'+ne(e)+"</span>",t&&(a+='<span class="section-desc">'+ne(t)+"</span>"),a+="</div>",a+=n,a+="</div>",a}function Ae(e,t,n,a){let s='<div class="subsection'+(a?" "+a:"")+'">';return s+='<div class="subsection-header">',s+='<span class="subsection-title">'+ne(e)+"</span>",n&&(s+='<span class="subsection-desc">'+ne(n)+"</span>"),s+="</div>",s+=t,s+="</div>",s}function Ye(e){return"red"===e?"High":"amber"===e?"Medium":"Low"}var Xe={native:"Native platform functionality",documented:"Lighter community alternative",simple:"Small inline snippet"};function Ne(e){return e&&0!==e.length?Ae("Supply chain source",'<div class="section-note">Shown only when lockfile source metadata is unusual or incomplete.</div><div class="kv-grid">'+e.map(e=>{return ge({"git-dependency":"Git dependency source","file-dependency":"Local dependency source","non-registry-tarball":"Non-registry tarball","missing-integrity":"Missing lockfile integrity","unexpected-registry-host":"Unexpected registry host"}[t=e.type]||ue(t),e.source,e.detail);var t}).join("")+"</div>","Lockfile source signals","warning"):""}function Te(e){if(!e)return;const t=e.trim();if(!t)return;const n=e=>e.replace(/\\.git\$/i,"");if(/^https?:\\/\\//i.test(t))return n(t);if(/^git\\+https?:\\/\\//i.test(t))return n(t.replace(/^git\\+/,""));if(/^git:\\/\\/github\\.com\\//i.test(t))return n(t.replace(/^git:\\/\\//i,"https://"));if(/^github:/i.test(t)){const e=t.slice(7).replace(/^\\/+/,"");return e?\`https://github.com/\${n(e)}\`:void 0}if(/^git@github\\.com:/i.test(t)){const e=t.slice(15);return e?\`https://github.com/\${n(e)}\`:void 0}return/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\$/.test(t)?\`https://github.com/\${n(t)}\`:void 0}function Re(e,t){const n=Te(e);if(!n)return;let a;try{a=new URL(n)}catch{return}if("github.com"!==a.hostname.toLowerCase())return;const s=a.pathname.split("/").filter(Boolean);if(s.length<2)return;const r=s[0],i=s[1].replace(/\\.git\$/i,"");return r&&i?\`https://github.com/\${r}/\${i}/blob/HEAD/\${t}\`:void 0}function je(e,t){return t?ne(e)+' <a class="kv-inline-link" href="'+ne(t)+'" target="_blank" rel="noopener noreferrer">GitHub<svg class="kv-inline-link-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M7 17 17 7"/><path d="M9 7h8v8"/></svg></a>':ne(e)}function Ve(e){if(e)try{const t=new URL(e);if("https:"!==t.protocol&&"http:"!==t.protocol)return;return t.username="",t.password="",t.toString()}catch{return}}function \$e(e){const t='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';if(!(e.npm||e.repository||e.homepage||e.issues))return"";let r='<div class="package-links">';const i=Ve(e.npm),o=Ve(e.repository),c=Ve(e.homepage),l=Ve(e.issues);return i||o||c||l?(i&&(r+='<a href="'+ne(i)+'" target="_blank" rel="noopener" class="package-link">'+t+"npm</a>"),o&&(r+='<a href="'+ne(o)+'" target="_blank" rel="noopener" class="package-link">'+n+"Repository</a>"),c&&(r+='<a href="'+ne(c)+'" target="_blank" rel="noopener" class="package-link">'+s+"Homepage</a>"),l&&(r+='<a href="'+ne(l)+'" target="_blank" rel="noopener" class="package-link">'+a+"Issues</a>"),r+="</div>",r):""}function He(e,n){const a=function(e,n,a=0,r){const i=e.execution?.risk||"green",o=t(e,s(e.package.name,r)),c=o.some(e=>"error"===e.severity)?"red":o.length>0?"amber":"green",l=a>0||(e.packaging?.signals?.length||0)>0?"amber":"green",d=(e.supplyChain?.registry?.signals?.length||0)>0?"amber":"green",u=e.maintenance?.status,p="deprecated"===u||"archived"===u?"red":"unmaintained"===u?"amber":"green";return(h=[n.risk,e.compliance.licenseRisk,i,l,c,d,p]).includes("red")?"red":h.includes("amber")?"amber":"green";var h}(e,ee(e).summary,n?.length||0,n),r=we(e.package.name,e.package.version),i=xe(r),o=pe(e),c=['<summary class="dep-summary">','<span class="expand-icon" aria-hidden="true"></span>','<span class="dep-name">'+ne(e.package.name)+'<span class="dep-version">@'+ne(e.package.version)+"</span></span>",'<div class="dep-indicators" style="--column-count: '+z+'">',o,"</div>","</summary>"].join("");return['<details class="dep-card" data-risk="'+a+'" data-dep-key="'+ne(r)+'" id="'+ne(i)+'">',c,'<div class="dep-details" data-rendered="false"></div>',"</details>"].join("")}function Oe(e,t,n,s){const r=ee(e),o=r.summary,c=J(e),l=c.isInferred?\`\${c.value} (inferred)\`:c.value,d=function(e){const t=e.package?.links||{},n=e.links||{},a=Te(t.repository||n.repository||n.repo);return{npm:t.npm||n.npm,repository:a||t.repository||n.repository||n.repo,homepage:t.homepage||n.homepage,issues:t.bugs||t.issues||n.bugs||n.issues}}(e),u=JSON.stringify(e,null,2),p=e.usage.origins.workspaces?.length?'<div class="micro-sublist"><div class="micro-subtitle">Workspaces</div>'+ke(e.usage.origins.workspaces,8)+"</div>":"",h=e.package.description?'<p class="dep-description"><span>Description: </span>'+ne(e.package.description)+"</p>":"";var g,m;const v=De("Overview",void 0,'<div class="definition-grid">'+[ge("Dependency status",e.usage.direct?"Direct dependency":"Transitive dependency"),ge("Scope",le(e.usage.scope)),e.usage.introduction?ge("Introduced by",ue(e.usage.introduction)):"",e.usage.runtimeImpact?ge("Runtime impact",(m=e.usage.runtimeImpact,m?ue(m):"")):"",ge("Dependency depth",e.usage.depth),e.usage.direct?"":ye("Introduced via root packages",Pe(e.usage.origins.topRootPackages,8,t,n)),e.usage.direct?"":ge("Direct roots",e.usage.origins.rootPackageCount),e.usage.direct?"":ye("Direct parents",be(e.usage.origins.topParentPackages,8,t,n)),e.usage.direct?"":ge("Direct parents count",e.usage.origins.parentPackageCount??0),ge("TypeScript types",(g=e.usage.tsTypes,"bundled"===g?"Bundled":"definitelyTyped"===g?"DefinitelyTyped":"none"===g?"None":"Unknown"))].filter(Boolean).join("")+"</div>"+p+function(e,t,n,a){if(!t||0===t.length)return"";const s=t.slice(0,n),r=t.length-n;let i='<div class="detail-list">';return i+='<div class="detail-title">'+ne(e)+"</div>",i+='<ul class="detail-items'+(a?" "+a:"")+'">',s.forEach(e=>{i+='<li class="detail-item">'+ne(e)+"</li>"}),r>0&&(i+='<li class="detail-item muted">+'+r+" more</li>"),i+="</ul></div>",i}("Top import locations",e.usage.importUsage?.topFiles,5,"mono")),f=e.compliance.license,y=Re(d.repository,"package.json"),k=Re(d.repository,"LICENSE"),b=[ye("Primary license",me(l,e.compliance.licenseRisk)),ge("Status",Z(f.status))];if(f.declared){const e=[f.declared.valid?"valid":"invalid",f.declared.expression?"expression":void 0,f.declared.deprecated?"deprecated":void 0].filter(Boolean).join(", "),t=f.exception?.id?\` WITH \${f.exception.id}\`:"";b.push(ye("Declared SPDX in package.json",'<span class="kv-value">'+je(\`\${f.declared.spdxId}\${t}\${e?\` (\${e})\`:""}\`,y)+"</span>"))}f.inferred&&b.push(ye("Inferred from LICENSE file",'<span class="kv-value">'+je(\`\${f.inferred.spdxId} (\${f.inferred.confidence})\`,k)+"</span>")),"mismatch"===f.status&&b.push(ge("Mismatch","Declared SPDX and LICENSE text do not match")),"invalid-spdx"===f.status&&b.push(ge("Invalid SPDX","Package.json license is not a valid SPDX identifier or expression"));const w=Ae("License",'<div class="kv-grid">'+b.join("")+"</div>"),C=a(o),E=[ye("Vulnerability status",me(0===C?"No known vulnerabilities":String(C),o.risk)),ge("Highest severity","none"===o.highest?"None":ue(o.highest))],x=C>0?'<div class="kv-grid kv-grid-tight">'+[ge("Critical",o.critical),ge("High",o.high),ge("Moderate",o.moderate),ge("Low",o.low)].join("")+"</div>":"",S=function(e){if(!e||0===e.length)return"";let t='<table class="vuln-table"><thead><tr>';return t+="<th>Title</th><th>Severity</th><th>Affected range</th><th>Fix available</th><th>Reference</th>",t+="</tr></thead><tbody>",e.forEach(e=>{const n=ne(e.title),a=Ve(e.url),s=a?'<a href="'+ne(a)+'" target="_blank" rel="noopener">Link</a>':"";t+='<tr data-severity="'+ne(e.severity)+'">',t+='<td data-label="Title">'+n+"</td>",t+='<td data-label="Severity">'+ne(de(e.severity))+"</td>",t+='<td data-label="Affected range">'+ne(e.vulnerableRange)+"</td>",t+='<td data-label="Fix available">'+ne(e.fixAvailable?"Yes":"No")+"</td>",t+='<td data-label="Reference">'+s+"</td>",t+="</tr>"}),t+="</tbody></table>",t}(r.advisories),L=Ae("Vulnerabilities",['<div class="kv-grid">'+E.join("")+"</div>",x||"",S||""].join(""),"Known security issues from npm audit","vuln-block"),I=e.execution?function(e){const t=[ye("Execution risk",me(Ye(e.risk),e.risk))];if(e.native&&t.push(ge("Native build tooling detected (native)","Yes")),e.scripts?.hooks?.length&&t.push(ye("Lifecycle hooks",ke(e.scripts.hooks,6))),"number"==typeof e.scripts?.complexity&&t.push(ge("Heuristic complexity","Script complexity: "+e.scripts.complexity+" (complexity)")),e.scripts?.signals?.length){const n=e.scripts.signals.map(e=>\`\${D[e]} (\${e})\`);t.push(ye("Install-time signals",ke(n,6)))}const n=(e.signals||[]).filter(t=>!(e.scripts?.signals||[]).includes(t));if(n.length){const e=n.map(e=>\`\${D[e]} (\${e})\`);t.push(ye("Local execution signals",ke(e,6)))}return Ae("Install-time execution behaviour",'<div class="section-note">Execution behaviour signals are local static review cues from lifecycle scripts, entry files, package bins, or a small bounded set of package files. They do not imply compromise.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.execution):"",M=function(e){if(!e?.signals?.length)return"";const t=[ye("Packaging signals",ke(e.signals.map(e=>\`\${A[e]} (\${e})\`),6))];return e.bundledDependencies?.length&&t.push(ye("Bundled dependencies",ke(e.bundledDependencies,8))),Ae("Package contents",'<div class="section-note">Packaging signals describe local package structure that may warrant review; they are not malware verdicts.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.packaging),P=function(e){if(!e?.attempted)return"";const t=[ge("Lookup",e.ok?"Available":"Unavailable"),ye("Candidate reasons",ke(e.candidateReasons||[],6))];if(e.error&&t.push(ge("Error",e.error)),e.signals?.length){const n=e.signals.map(e=>\`\${Y[e]} (\${e})\`);t.push(ye("Registry signals",ke(n,6)))}return e.installedVersionPublishedAt&&t.push(ge("Installed version published",e.installedVersionPublishedAt)),e.packageCreatedAt&&t.push(ge("Package created",e.packageCreatedAt)),"number"==typeof e.versionCount&&t.push(ge("Published versions",e.versionCount)),e.latestVersion&&t.push(ge("Latest dist-tag",e.latestVersion)),Ae("Registry metadata",'<div class="section-note">Targeted npm registry metadata is collected only for packages that already show local review signals, and is skipped in offline scans.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.supplyChain?.registry),B=De("Risk & Compliance",void 0,w+L+function(e){if(!e?.attempted)return"";const t=[ge("Status",F(e.status))];if(e.deprecated){const n=e.deprecated.installedVersion?"Installed version":"Latest version";t.push(ge("Deprecated",n,e.deprecated.message))}void 0!==e.repoArchived&&t.push(ge("Repository archived",te(e.repoArchived),e.repoCheckedAt?\`Checked \${e.repoCheckedAt}\`:void 0)),e.packageModifiedAt&&t.push(ge("Last registry activity",e.packageModifiedAt,"number"==typeof e.monthsSinceModified?\`~\${e.monthsSinceModified} months ago\`:void 0)),e.repoPushedAt&&t.push(ge("Last repository push",e.repoPushedAt,"number"==typeof e.monthsSinceRepoPush?\`~\${e.monthsSinceRepoPush} months ago\`:void 0)),e.latestVersion&&t.push(ge("Latest version",e.latestVersion)),e.fetchedAt&&t.push(ge("Data fetched",e.fetchedAt+(e.fromCache?" (cached)":""))),e.error&&t.push(ge("Error",e.error));const n="deprecated"===e.status||"archived"===e.status?"warning":void 0;return Ae("Maintenance",'<div class="section-note">Conservative registry heuristics: "last registry activity" updates on any packument write, so age-based statuses under-flag rather than over-flag. When a repository push timestamp is also known, both surfaces must be quiet before a package escalates past "slowing". Review cues, not verdicts.</div><div class="kv-grid">'+t.join("")+"</div>",void 0,n)}(e.maintenance)+I+M+P+Ne(s)),N=[ge("Outdated status",(T=e.upgrade.outdatedStatus,T?"unknown"===T?"Unknown":ue(T):"Not reported"))];var T;e.upgrade.latestVersion&&N.push(ge("Latest version",e.upgrade.latestVersion)),e.upgrade.risk&&N.push(ge("Upgrade risk",X(e.upgrade.risk),"Derived from outdated status and known blockers"));const R=Ae("Version",'<div class="section-note">Based on npm outdated findings and registry metadata.</div><div class="kv-grid">'+N.join("")+"</div>"),j=e.package.deprecated&&!e.maintenance?.deprecated?Ae("Deprecated",'<div class="kv-grid">'+ge("Deprecated","Yes","Declared by the package author.")+"</div>",void 0,"warning"):"",V=[ge("Node engine constraint",e.upgrade.nodeEngine||"Any")];void 0!==e.upgrade.blocksNodeMajor&&V.push(ge("Blocks Node major upgrade",te(e.upgrade.blocksNodeMajor)));const \$=Ae("Constraints",'<div class="kv-grid">'+V.join("")+"</div>"),H=Ae("Blast radius",'<div class="kv-grid">'+[ge("Used by other packages (fanIn)",e.graph.fanIn),ge("Depends on packages (fanOut)",e.graph.fanOut)].join("")+"</div>"),O={nodeEngine:"Node engine constraint",peerDependency:"Peer dependency constraints",nativeBindings:"Native bindings/build tooling",installScripts:"Install lifecycle scripts",deprecated:"Deprecated by author"},W='<div class="subsection"><div class="subsection-header"><span class="subsection-title">Upgrade blockers</span></div>'+(e.upgrade.blockers?.length?'<ul class="bullet-list">'+e.upgrade.blockers.map(e=>"<li>"+ne(O[e]||e)+"</li>").join("")+"</ul>":'<div class="status-row">No upgrade blockers detected</div>')+"</div>",U=De("Upgrade & Change Impact","Currency, constraints, and blast radius",function(e){if(!e?.replacements?.length)return"";const t=[ge("Suggested",e.replacements.join(", ")),ge("Replacement type",Xe[e.type]||e.type)],n=e.docUrl?'<div class="section-note"><a href="'+ne(e.docUrl)+'" target="_blank" rel="noopener noreferrer">Migration guidance for this replacement</a></div>':"";return Ae("Replacement available",'<div class="kv-grid">'+t.join("")+"</div>"+n+'<div class="section-note">Suggestion from the community-maintained <a href="https://github.com/es-tooling/module-replacements" target="_blank" rel="noopener noreferrer">module-replacements</a> catalogue, part of the <a href="https://e18e.dev" target="_blank" rel="noopener noreferrer">e18e</a> ecosystem performance initiative. Guidance to review, not a drop-in instruction.</div>',"Community-suggested lighter or native alternative")}(e.replacement)+R+j+\$+H+W),G=Be(e,t,n);return[\$e(d),h,fe(e,o,l),(_=i(e,o,s),['<div class="key-points">','<div class="section-header compact"><span class="section-title">Key points</span></div>','<ul class="key-points-list">',_.map(e=>"<li>"+ne(e)+"</li>").join(""),"</ul>","</div>"].join("")),v,B,U,G,'<details class="raw-data-toggle"><summary><span class="expand-icon" aria-hidden="true"></span>View raw data</summary><div class="raw-data-pane"><pre>'+ne(u)+'</pre><button type="button" class="copy-json-btn" aria-label="Copy raw JSON">Copy JSON</button></div></details>'].join("");var _}async function Fe(){const e=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}();void 0===window.__DEPENDENCY_DATA__&&(window.__DEPENDENCY_DATA__=e);const t=document.getElementById("dependency-list"),n=document.getElementById("results-summary"),a=document.getElementById("scan-status-banner");if(a&&e.scanStatus?.warnings.length){a.hidden=!1;const t=document.createElement("strong");t.textContent=e.scanStatus.complete?"Some analysis was intentionally skipped":"Scan evidence is incomplete",a.appendChild(t);const n=document.createElement("ul");e.scanStatus.warnings.slice(0,8).forEach(e=>{const t=document.createElement("li");t.textContent=e.length>300?\`\${e.slice(0,297)}…\`:e,n.appendChild(t)}),a.appendChild(n)}const s=document.getElementById("project-path");s&&(s.textContent=e.project.name||e.project.projectDir,s.title=e.project.projectDir);const r=document.getElementById("metadata-toggle"),i=document.getElementById("metadata-panel"),c=document.getElementById("formatted-date");let l=e.generatedAt||"";if(c&&e.generatedAt)try{const t=new Date(e.generatedAt);Number.isNaN(t.getTime())?(l=e.generatedAt,c.textContent=e.generatedAt):(l=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(t),c.textContent=l)}catch{l=e.generatedAt,c.textContent=e.generatedAt}i&&(i.innerHTML=function(e,t){const n=e.environment||{},a=n.minRequiredMajor,s=a&&a>0?"Node requirement derived from dependency engine ranges.":"";return[ie("Report",[re("Dependency Radar",e.dependencyRadarVersion),re("Schema",e.schemaVersion),re("Generated",t||e.generatedAt),re("Generated raw",e.generatedAt)]),ie("Project",[re("Name",e.project.name),re("Version",e.project.version),re("Path",e.project.projectDir),re("Description",e.project.description),re("License",e.project.license),re("Homepage",e.project.homepage),re("Repository",e.project.repository),re("Constraints",e.project.constraints),re("Dependency policy",e.project.dependencyPolicySummary)]),ie("Git",[re("Branch",e.git?.branch)]),ie("Environment",[re("Node",n.nodeVersion),re("Runtime",n.runtimeVersion),re("Minimum required Node major",n.minRequiredMajor),re("Target Node major",n.targetNodeMajor),re("Platform",n.platform),re("Architecture",n.arch),re("CI",n.ci),re("packageManager field",n.packageManagerField),re("Package manager",n.packageManager),re("Package manager version",n.packageManagerVersion),re("Tool versions",n.toolVersions),re("Node note",s)]),oe(e),ie("Summary",[re("Dependencies",e.summary?.dependencyCount),re("Direct",e.summary?.directCount),re("Transitive",e.summary?.transitiveCount),re("Findings",e.summary?.findingCount)]),ie("Scan evidence",[re("Complete",e.scanStatus?.complete),re("Collectors",e.scanStatus?.collectors),re("Warnings",e.scanStatus?.warnings)]),ce(e)].filter(Boolean).join("")}(e,l),i.hidden=!1,i.inert=!0,i.setAttribute("aria-hidden","true"));const d=e=>{r&&i&&(i.classList.toggle("open",e),i.inert=!e,i.setAttribute("aria-hidden",String(!e)),r.classList.toggle("open",e),r.setAttribute("aria-expanded",String(e)))};r?.addEventListener("click",()=>{const e=!i?.classList.contains("open");d(e)}),document.addEventListener("click",e=>{if(!r||!i)return;if(!i.classList.contains("open"))return;const t=e.target;r.contains(t)||i.contains(t)||d(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&d(!1)});const u={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),workspace:document.getElementById("workspace-filter"),workspaceWrap:document.getElementById("workspace-filter-wrap"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),maintenanceConcerns:document.getElementById("maintenance-concerns"),licenseIssues:document.getElementById("license-issues"),upgradeBlockers:document.getElementById("upgrade-blockers"),hasReplacement:document.getElementById("has-replacement"),hasReplacementWrap:document.getElementById("has-replacement-wrap"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly"),filtersToggle:document.getElementById("filters-toggle"),filterCountBadge:document.getElementById("filter-count-badge"),filterControls:document.getElementById("filter-controls"),activeFiltersRow:document.getElementById("active-filters-row"),activeFilterChips:document.getElementById("active-filter-chips"),activeFilterClear:document.getElementById("active-filter-clear"),clearAllFilters:document.getElementById("clear-all-filters"),licensePermissiveLabel:document.getElementById("license-permissive-label"),licenseWeakCopyleftLabel:document.getElementById("license-weak-copyleft-label"),licenseStrongCopyleftLabel:document.getElementById("license-strong-copyleft-label"),licenseUnknownLabel:document.getElementById("license-unknown-label"),hasVulnsLabel:document.getElementById("has-vulns-label"),maintenanceConcernsLabel:document.getElementById("maintenance-concerns-label"),licenseIssuesLabel:document.getElementById("license-issues-label"),upgradeBlockersLabel:document.getElementById("upgrade-blockers-label"),hasReplacementLabel:document.getElementById("has-replacement-label"),columnHeadersContainer:document.getElementById("column-headers-container"),packageHeader:document.getElementById("package-header"),viewGraphButton:document.getElementById("view-graph-btn"),graphBackButton:document.getElementById("graph-back-btn"),listViewPanel:document.getElementById("list-view"),graphViewPanel:document.getElementById("graph-view"),graphWorkspaceSelect:document.getElementById("graph-workspace"),graphWorkspaceWrap:document.getElementById("graph-workspace-wrap"),graphControls:document.getElementById("graph-controls"),graphCanvas:document.getElementById("graph-canvas"),graphCanvasShell:document.getElementById("graph-canvas-shell"),graphPopover:document.getElementById("graph-popover"),graphPopoverName:document.getElementById("graph-popover-name"),graphPopoverVersion:document.getElementById("graph-popover-version"),graphPopoverLicense:document.getElementById("graph-popover-license"),graphPopoverVulns:document.getElementById("graph-popover-vulns"),graphPopoverAmplification:document.getElementById("graph-popover-amplification"),graphOpenList:document.getElementById("graph-open-list"),reportFooter:document.querySelector(".report-footer")};let p="name",h=!0,g=null,m=!1;document.documentElement.setAttribute("data-theme","dark"),"light"===localStorage.getItem("dependency-radar-theme")?(document.documentElement.classList.add("light"),u.themeSwitch.classList.add("light"),u.themeSwitch.setAttribute("aria-pressed","true"),document.documentElement.setAttribute("data-theme","light")):(document.documentElement.classList.remove("light"),u.themeSwitch.classList.remove("light"),u.themeSwitch.setAttribute("aria-pressed","false"),document.documentElement.setAttribute("data-theme","dark")),u.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),u.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");document.documentElement.setAttribute("data-theme",e?"light":"dark"),u.themeSwitch.setAttribute("aria-pressed",String(e)),localStorage.setItem("dependency-radar-theme",e?"light":"dark"),g?.requestRender()});const v=window.matchMedia("(max-width: 768px)");let f=v.matches;const y=e=>{u.filterControls&&u.filtersToggle&&(u.filterControls.classList.toggle("open",e),u.filterControls.inert=!e,u.filterControls.setAttribute("aria-hidden",String(!e)),u.filtersToggle.classList.toggle("open",e),u.filtersToggle.setAttribute("aria-expanded",String(e)),e&&d(!1))},k=()=>{if(v.matches)return y(!1),void(f=!0);f&&y(!1),f=!1};function b(){if(u.columnHeadersContainer&&(u.columnHeadersContainer.innerHTML=he(p,h)),u.packageHeader){const e=u.packageHeader.querySelector(".sort-indicator");e&&("name"===p?(e.textContent=h?" ▲":" ▼",u.packageHeader.classList.add("sorted")):(e.textContent="",u.packageHeader.classList.remove("sorted")))}}function w(e){const t=e.target.closest(".column-header");if(!t)return;const n=t.dataset.sort;n&&(p===n?h=!h:(p=n,h=!0),u.sort&&(u.sort.value=p,u.sortDirection.textContent=h?"↑":"↓"),b(),O())}u.filtersToggle&&u.filterControls&&u.filtersToggle.addEventListener("click",()=>{const e=!u.filterControls.classList.contains("open");y(e)}),document.addEventListener("click",e=>{if(!u.filterControls||!u.filtersToggle)return;const t=e.target;u.filterControls.contains(t)||u.filtersToggle.contains(t)||y(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&y(!1)}),y(!1),window.addEventListener("resize",k),k(),u.sortDirection.addEventListener("click",()=>{h=!h,u.sortDirection.textContent=h?"↑":"↓",b(),O()}),u.sort.addEventListener("change",()=>{p=u.sort.value,b(),O()}),u.columnHeadersContainer&&u.columnHeadersContainer.addEventListener("click",w),u.packageHeader&&u.packageHeader.addEventListener("click",w),b(),u.licenseAll.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0,X.clear(),O()}),u.licenseFriendly.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!1,u.licenseStrongCopyleft.checked=!1,u.licenseUnknown.checked=!1,X.clear(),O()});const C=Object.values(e.dependencies||{}),E=e=>{const t=e.usage.origins.workspaces||[];return t.length>0?t:["root"]},x=Array.from(new Set([...o(e),...C.flatMap(E)])).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t)),S=(e,t)=>e+" ("+t+")",L=e=>{return Q[t=ee(e).summary,t?.highest||"none"]>0;var t},I=e=>C.reduce((t,n)=>t+(e(n)?1:0),0);if(u.workspace&&u.workspaceWrap&&x.length>1){u.workspace.textContent="";const e=document.createElement("option");e.value="all",e.textContent=S("All workspaces",C.length),u.workspace.appendChild(e),x.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=S("root"===e?"Workspace root":e,I(t=>E(t).includes(e))),u.workspace.appendChild(t)}),u.workspaceWrap.classList.remove("hidden")}!function(){const e=C.length;u.direct.options[0].textContent=S("All",e),u.direct.options[1].textContent=S("Direct",I(e=>e.usage.direct)),u.direct.options[2].textContent=S("Transitive",I(e=>!e.usage.direct));const t={all:"All",runtime:"Production",dev:"Development",optional:"Optional",peer:"Peer"};Array.from(u.runtime.options).forEach(n=>{n.textContent=S(t[n.value]||n.textContent||n.value,"all"===n.value?e:I(e=>e.usage.scope===n.value))});const n={permissive:0,weakCopyleft:0,strongCopyleft:0,unknown:0};C.forEach(e=>{n[K(J(e).value)]+=1}),u.licensePermissiveLabel&&(u.licensePermissiveLabel.textContent=S("Permissive",n.permissive)),u.licenseWeakCopyleftLabel&&(u.licenseWeakCopyleftLabel.textContent=S("Weak Copyleft",n.weakCopyleft)),u.licenseStrongCopyleftLabel&&(u.licenseStrongCopyleftLabel.textContent=S("Strong Copyleft",n.strongCopyleft)),u.licenseUnknownLabel&&(u.licenseUnknownLabel.textContent=S("Other / Unknown",n.unknown)),u.hasVulnsLabel&&(u.hasVulnsLabel.textContent=S("Has vulnerabilities",I(L))),u.maintenanceConcernsLabel&&(u.maintenanceConcernsLabel.textContent=S("Maintenance concerns",I(U))),u.licenseIssuesLabel&&(u.licenseIssuesLabel.textContent=S("Licence issues",I(_))),u.upgradeBlockersLabel&&(u.upgradeBlockersLabel.textContent=S("Upgrade blockers",I(q)));const a=I(G);u.hasReplacementWrap&&(u.hasReplacementWrap.hidden=0===a),u.hasReplacementLabel&&a>0&&(u.hasReplacementLabel.textContent=S("Has replacement suggestion",a))}(),function(){const t=document.getElementById("header-stats");if(!t)return;let n=0,a=0,s=0,r=!1,i=0,o=0,c=0;C.forEach(e=>{if(L(e)&&(n+=1),G(e)&&(c+=1),e.maintenance?.attempted&&(r=!0),U(e)){a+=1;const t=e.maintenance?.status;"deprecated"!==t&&"archived"!==t||(s+=1)}_(e)&&(i+=1),q(e)&&(o+=1)});const l=(e,t,n,a)=>{const s=document.getElementById(e);if(!s)return;const r=s.querySelector("strong");r&&(r.textContent=String(t)),s.classList.remove("red","amber"),n&&t>0&&s.classList.add(n),a&&(s.title=a)};l("stat-total",e.summary.dependencyCount,void 0,\`\${e.summary.directCount} direct, \${e.summary.transitiveCount} transitive\`),l("stat-vulnerable",n,"red","Dependencies with known vulnerabilities — click to filter");const d=(e,t,n)=>{const a=document.getElementById(e);if(!a)return;a.hidden=!1,a.disabled=!0,a.classList.remove("red","amber");const s=a.querySelector("strong");s&&(s.textContent="?"),a.title=\`\${n} is unknown because its collector is \${t}\`},p=e.scanStatus?.collectors.audit;p&&"available"!==p&&d("stat-vulnerable",p,"Vulnerability status"),l("stat-license",i,"amber","Dependencies with licence review flags — click to filter"),l("stat-blockers",o,"amber","Dependencies with upgrade blockers — click to filter");const h=document.getElementById("stat-replacements");h&&(0===c?h.hidden=!0:(h.hidden=!1,l("stat-replacements",c,void 0,"Dependencies with community-suggested replacements (e18e) — click to filter")));const g=document.getElementById("stat-maintenance");if(g){const t=e.scanStatus?.collectors.maintenance;t&&"available"!==t?d("stat-maintenance",t,"Maintenance status"):r?l("stat-maintenance",a,s>0?"red":"amber","Deprecated, archived, unmaintained, or stale dependencies — click to filter"):g.hidden=!0}t.addEventListener("click",e=>{const t=e.target.closest("[data-stat-filter]");if(!t)return;if(t.disabled)return;const n={"has-vulns":u.hasVulns,"maintenance-concerns":u.maintenanceConcerns,"license-issues":u.licenseIssues,"upgrade-blockers":u.upgradeBlockers,"has-replacement":u.hasReplacement}[t.dataset.statFilter||""];if(!n)return;const a=n.checked;u.search.value="",V(),n.checked=!a,n.dispatchEvent(new Event("change"))})}();const M=new Map;C.forEach(e=>{M.set(we(e.package.name,e.package.version),e)});const B=new Set(M.keys()),D=Se(B),A=function(e,t,n){const a=new Map,s=(e,t)=>{const n=a.get(e)||[];n.push(t),a.set(e,n)};for(const r of e.supplyChain?.signals||[]){const e=[r.packageId,r.packageName&&r.packageVersion?we(r.packageName,r.packageVersion):void 0].filter(Boolean);let a=!1;for(const n of e){const e=Me(n,t);if(e){s(e,r),a=!0;break}}if(!a&&r.packageName&&!r.packageVersion){const e=Le(r.packageName,t,n);e&&s(e,r)}}return a}(e,B,D),Y=new Set,X=new Set,N=new Map,T=(()=>{const e=document.getElementById("copy-announcer");if(e)return e;const t=document.createElement("div");return t.id="copy-announcer",t.className="sr-only",t.setAttribute("aria-live","polite"),document.body.appendChild(t),t})();function R(e){const t=e.dataset.depKey;if(!t)return;const n=e.querySelector(".dep-details");if(!n||"true"===n.dataset.rendered)return;const a=M.get(t);a&&(n.setAttribute("aria-busy","true"),n.innerHTML=['<div class="dep-loading" role="presentation">','<div class="dep-loading-bar"></div>',"</div>"].join(""),requestAnimationFrame(()=>{n.innerHTML=Oe(a,B,D,A.get(t)),n.dataset.rendered="true",n.removeAttribute("aria-busy")}))}function j(e){return(e.selectedOptions[0]?.textContent||"").replace(/\\s+\\(\\d+\\)\$/,"")}function V(){u.direct.value="all",u.runtime.value="all",u.workspace&&(u.workspace.value="all"),u.hasVulns.checked=!1,u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1),u.licenseIssues&&(u.licenseIssues.checked=!1),u.upgradeBlockers&&(u.upgradeBlockers.checked=!1),u.hasReplacement&&(u.hasReplacement.checked=!1),u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0}function \$(){const e=[],t=u.search.value.trim();return t&&e.push({id:"search",label:"Search: "+t,remove:()=>{u.search.value=""}}),"all"!==u.direct.value&&e.push({id:"type",label:"Type: "+j(u.direct),remove:()=>{u.direct.value="all"}}),"all"!==u.runtime.value&&e.push({id:"scope",label:"Scope: "+j(u.runtime),remove:()=>{u.runtime.value="all"}}),u.workspace&&"all"!==u.workspace.value&&e.push({id:"workspace",label:"Workspace: "+j(u.workspace),remove:()=>{u.workspace.value="all"}}),[{id:"license-permissive",checked:u.licensePermissive.checked,label:"License: Permissive",reset:()=>{u.licensePermissive.checked=!0}},{id:"license-weak-copyleft",checked:u.licenseWeakCopyleft.checked,label:"License: Weak Copyleft",reset:()=>{u.licenseWeakCopyleft.checked=!0}},{id:"license-strong-copyleft",checked:u.licenseStrongCopyleft.checked,label:"License: Strong Copyleft",reset:()=>{u.licenseStrongCopyleft.checked=!0}},{id:"license-unknown",checked:u.licenseUnknown.checked,label:"License: Other / Unknown",reset:()=>{u.licenseUnknown.checked=!0}}].forEach(t=>{t.checked||e.push({id:t.id,label:t.label,remove:t.reset})}),u.hasVulns.checked&&e.push({id:"has-vulns",label:"Has vulnerabilities",remove:()=>{u.hasVulns.checked=!1}}),u.maintenanceConcerns?.checked&&e.push({id:"maintenance-concerns",label:"Maintenance concerns",remove:()=>{u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1)}}),u.licenseIssues?.checked&&e.push({id:"license-issues",label:"Licence issues",remove:()=>{u.licenseIssues&&(u.licenseIssues.checked=!1)}}),u.upgradeBlockers?.checked&&e.push({id:"upgrade-blockers",label:"Upgrade blockers",remove:()=>{u.upgradeBlockers&&(u.upgradeBlockers.checked=!1)}}),u.hasReplacement?.checked&&e.push({id:"has-replacement",label:"Has replacement suggestion",remove:()=>{u.hasReplacement&&(u.hasReplacement.checked=!1)}}),e}function O(){!function(){const e=\$(),t=e.length;u.filtersToggle.classList.toggle("has-active-filters",t>0),u.filterCountBadge&&(u.filterCountBadge.hidden=0===t,u.filterCountBadge.textContent=String(t)),u.activeFiltersRow&&u.activeFilterChips&&(u.activeFiltersRow.hidden=0===t,u.activeFilterChips.innerHTML=e.map(e=>'<span class="active-filter-chip">'+ne(e.label)+'<button type="button" class="active-filter-remove" data-filter-chip="'+ne(e.id)+'" aria-label="Remove '+ne(e.label)+'">×</button></span>').join(""))}();const a=function(e){const t=[...e];if("name"===p)t.sort((e,t)=>e.package.name.localeCompare(t.package.name));else if("depth"===p)t.sort((e,t)=>e.usage.depth-t.usage.depth);else{const e=H.find(e=>e.sortKey===p||e.id===p);e?.sortFn?t.sort(e.sortFn):e&&t.sort((t,n)=>e.getValue(t).localeCompare(e.getValue(n)))}return h||t.reverse(),t}(function(){const e=(u.search.value||"").toLowerCase(),t=u.direct.value,n=u.runtime.value,a=u.workspace?.value||"all",s=u.hasVulns.checked,r=u.maintenanceConcerns?.checked??!1,i=u.licenseIssues?.checked??!1,o=u.upgradeBlockers?.checked??!1,c=u.hasReplacement?.checked??!1,l=u.licensePermissive.checked,d=u.licenseWeakCopyleft.checked,p=u.licenseStrongCopyleft.checked,h=u.licenseUnknown.checked;return C.filter(u=>{const g=we(u.package.name,u.package.version);if(X.has(g))return!0;const m=J(u),v=[m.value,u.compliance.license.declared?.spdxId,u.compliance.license.inferred?.spdxId].filter(Boolean).join(" ").toLowerCase();if(e&&!u.package.name.toLowerCase().includes(e)&&!v.includes(e))return!1;if("direct"===t&&!u.usage.direct)return!1;if("transitive"===t&&u.usage.direct)return!1;if("all"!==n&&u.usage.scope!==n)return!1;if("all"!==a&&!E(u).includes(a))return!1;if(s&&!L(u))return!1;if(r&&!U(u))return!1;if(i&&!_(u))return!1;if(o&&!q(u))return!1;if(c&&!G(u))return!1;const f=K(m.value);return!("permissive"===f&&!l||"weakCopyleft"===f&&!d||"strongCopyleft"===f&&!p||"unknown"===f&&!h)})}()),s=e.summary?.dependencyCount||C.length;n.innerHTML="Showing <strong>"+a.length+"</strong> of <strong>"+s+"</strong> dependencies","all"!==(u.workspace?.value||"all")&&(n.innerHTML+=" in <strong>"+ne(u.workspace.value)+"</strong>"),0!==a.length?(t.innerHTML=a.map(e=>He(e,A.get(we(e.package.name,e.package.version)))).join(""),N.clear(),t.querySelectorAll("details.dep-card").forEach(e=>{const t=e.dataset.depKey;t&&N.set(t,e)}),Y.forEach(e=>{const t=N.get(e);t&&(t.open||(t.open=!0),R(t))})):t.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}function F(e){const t=D.get(e)||[];return 1===t.length?t[0]:null}function W(e){if(M.has(e))return e;const t=Ee(e);if(!t)return F(e);if(t.version.startsWith("npm:")){const e=t.version.slice(4),n=t.name+(e.startsWith("@")?e:"@"+e);if(M.has(n))return n}return F(t.name)}function z(t){if(!u.listViewPanel||!u.graphViewPanel)return void console.warn("Dependency Radar: view panels are missing from the report DOM.");const n="list"===t;n||Boolean(u.graphWorkspaceSelect&&u.graphWorkspaceWrap&&u.graphControls&&u.graphCanvas&&u.graphCanvasShell&&u.graphPopover&&u.graphPopoverName&&u.graphPopoverVersion&&u.graphPopoverLicense&&u.graphPopoverVulns&&u.graphPopoverAmplification&&u.graphOpenList)?(u.listViewPanel.classList.toggle("active",n),u.graphViewPanel.classList.toggle("active",!n),u.listViewPanel.setAttribute("aria-hidden",String(!n)),u.graphViewPanel.setAttribute("aria-hidden",String(n)),u.viewGraphButton&&(u.viewGraphButton.style.display=n?"":"none"),u.graphBackButton&&(u.graphBackButton.style.display=n?"none":""),u.reportFooter?.classList.toggle("hidden",!n),document.body.classList.toggle("graph-mode",!n),n?g?.setActive(!1):(m||(g=P({report:e,knownDepKeys:B,resolveDepKey:W,workspaceSelect:u.graphWorkspaceSelect,workspaceWrap:u.graphWorkspaceWrap,controlsRoot:u.graphControls,canvas:u.graphCanvas,canvasHost:u.graphCanvasShell,popover:u.graphPopover,popoverName:u.graphPopoverName,popoverVersion:u.graphPopoverVersion,popoverLicense:u.graphPopoverLicense,popoverVulns:u.graphPopoverVulns,popoverAmplification:u.graphPopoverAmplification,popoverOpenButton:u.graphOpenList,onOpenList:e=>{!function(e){z("list");let t=document.getElementById(xe(e));!t&&M.has(e)&&(X.add(e),O(),t=document.getElementById(xe(e)));if(!t)return;if(t instanceof HTMLDetailsElement){const e=t.dataset.depKey;e&&Y.add(e),t.open||(t.open=!0),R(t)}t.classList.add("dep-list-highlight"),Z(t,!0),window.setTimeout(()=>{t?.classList.remove("dep-list-highlight")},2e3)}(e)}}),g.initGraphView(),m=!0),g?.setActive(!0),g?.requestRender())):console.warn("Dependency Radar: graph view DOM nodes are missing; graph view disabled.")}function Z(e,t=!1){const n=()=>{const n=window.scrollY+e.getBoundingClientRect().top-function(){const e=document.querySelector(".filter-bar");return!e||document.body.classList.contains("graph-mode")?0:Math.ceil(e.getBoundingClientRect().height+8)}();if(window.scrollTo({top:Math.max(0,n),behavior:"smooth"}),t){const t=e.querySelector("summary");t&&t.focus({preventScroll:!0})}};requestAnimationFrame(()=>{n(),window.setTimeout(n,60)})}const te=[u.search,u.direct,u.runtime,u.sort,u.hasVulns,u.maintenanceConcerns,u.licenseIssues,u.upgradeBlockers,u.hasReplacement,u.workspace,u.licensePermissive,u.licenseWeakCopyleft,u.licenseStrongCopyleft,u.licenseUnknown],ae=()=>{X.clear(),O()};te.forEach(e=>{e&&(e.addEventListener("input",ae),e.addEventListener("change",ae))}),u.activeFilterChips?.addEventListener("click",e=>{const t=e.target.closest("[data-filter-chip]");if(!t)return;const n=\$().find(e=>e.id===t.dataset.filterChip);n&&(n.remove(),ae())});const se=()=>{u.search.value="",V(),ae()};function le(e){const t=e.getAttribute("data-dep-key");if(!t)return;const n=W(t);if(!n)return;let a=N.get(n);a||(X.add(n),O(),a=N.get(n)),a&&(Y.add(n),a.open||(a.open=!0),R(a),Z(a,!0))}u.activeFilterClear?.addEventListener("click",se),u.clearAllFilters?.addEventListener("click",se),u.viewGraphButton?.addEventListener("click",()=>{z("graph")}),u.graphBackButton?.addEventListener("click",()=>{z("list")}),t.addEventListener("toggle",e=>{const t=e.target;if(!(t instanceof HTMLDetailsElement))return;if(!t.classList.contains("dep-card"))return;const n=t.dataset.depKey;n&&(t.open?(Y.add(n),R(t)):Y.delete(n))},!0),t.addEventListener("click",e=>{const t=e.target,n=t.closest(".root-package-link");if(n)return e.preventDefault(),void le(n);const a=t.closest(".copy-json-btn");a&&(e.preventDefault(),async function(e){const t=(e.closest(".raw-data-toggle")?.querySelector("pre"))?.textContent??"";if(t)try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(t);else{const e=document.createElement("textarea");e.value=t,e.setAttribute("readonly","true"),e.style.position="absolute",e.style.left="-9999px",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}const n=e.dataset.label||e.textContent||"Copy JSON";e.dataset.label=n,e.textContent="Copied",e.classList.add("copied"),T.textContent="Copied JSON to clipboard.",window.setTimeout(()=>{e.textContent=n,e.classList.remove("copied")},1500)}catch{T.textContent="Copy failed."}}(a))}),t.addEventListener("keydown",e=>{const t=e.target.closest(".root-package-link");t&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),le(t)))}),b(),O(),z("list")}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",Fe):Fe()}();`; | |||
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Keep supply-chain combinations version-qualified.
The bundle indexes source signals by package name, discarding packageId versions before deriving combinations. If foo@1 is git-sourced and foo@2 is registry-sourced, both can receive the same install-script combination finding. Index by packageId first and only fall back to name when the source signal is genuinely unversioned; then regenerate this asset.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/report-assets.ts` at line 16, Update the source-signal indexing logic in
function s so packageId is used as the primary key, preserving its
version-qualified identity when deriving install-script combinations; fall back
to packageName only when packageId is absent. Ensure combination lookup in
function i uses the same packageId-first keying, then regenerate the JS_CONTENT
bundle asset.
…der, 1.7 in UI types - Supply-chain combo signals are now indexed by version-qualified package identity (packageId, falling back to name@version, then bare name only for version-less signals), so a source signal on one installed version no longer implicates a different version's install hooks. Callers in findings, failOn, and reportDetailRules look up via the dependency's own id; added cross-version regression coverage at both the combo and fail-on level. - Header stat grid uses column auto-flow so the optional Replacements chip renders as a sixth equal column on desktop instead of wrapping; the mobile two-column layout is unchanged. - report-ui schemaVersion type now includes '1.7'. - Rebuilt dist/ and the embedded report assets. Not changed: applyUpgradeRisk already runs unconditionally inside aggregateData, so upgrade.risk is derived from local outdated/blocker data even when no enrichment runs; the cli.ts call is only the post-enrichment recompute. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The validate-output-schemas CI fixture hardcoded schemaVersion '1.6' and failed against the 1.7 const in the report schema. Use the exported REPORT_SCHEMA_VERSION so the fixture can never drift from the schema again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… ajv) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The final console.log interpolated values CodeQL traces back to fetched manifest data. Coerce the count to a number and log the static output path so the new error-level alert stops blocking merges under the code-scanning ruleset. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The flagged sink was console.error(err) in the catch handler, not the success log: fetch/parse errors can embed response-derived text. Log the message with newlines removed, the sanitizer the query recognizes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itizer The query's StringReplaceSanitizer only matches a replace of the literal newline with an empty string; the previous character-class-with-space form satisfied neither condition, so the alert reappeared on the new line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports the worthwhile analysis from the retired Dependency Radar SaaS into the CLI as one PR. The SaaS composite risk score is deliberately not ported — the individual signals below are surfaced as explainable findings instead of a 0–100 number.
Replacement suggestions (e18e)
scripts/build-replacements.ts→src/generated/replacements.ts(same pattern as the SPDX data; refresh withnpm run update:replacements). Zero runtime dependencies, works with--offline.dependencies[id].replacement, the report's Upgrade & Change Impact detail panel (with credit and links to e18e / module-replacements),explain <pkg>output, and info-levelmodernizationfindings for direct dependencies only.util.styleText,picocolors,ansis) sonpm run dev:reportshows the feature.Supply-chain combination flags
Install lifecycle scripts paired with a mutable or unverifiable source now produce dedicated findings that explain why the pairing matters:
Shared logic in
src/supplyChainCombos.tsfeeds findings, report key points, overall dependency risk (error combos escalate to red), and a new opt-insupply-chain-combo--fail-onrule.Maintenance drift tiers + upgrade risk
slowingstatus: 12+ months without any registry write.pushed_attimestamp already returned by the existing bounded ecosyste.ms lookups (no new hosts): registry and repo must both be quiet before a package is called stale (12mo/6mo) or unmaintained (24mo/12mo). An actively developed package that just stopped publishing staysslowing.--offlineand degraded scans are unchanged.upgrade.riskband (high/medium/low/unknown) from outdated status and blockers, recomputed after registry enrichment.Housekeeping
compare).dist/includes a catch-up rebuild: Harden Dependency Radar for v1.0.0 #86 changedsrc/but shipped without rebuildingdist/, so part of this diff is that drift.Testing
tscclean; report-ui typecheck shows only the 3 errors that pre-exist on master.test-repos/cal.diy: 301 replacement matches, 16 modernization findings, upgrade-risk bands populated, output validates against schema 1.7, and the generated HTML contains the new UI elements.🤖 Generated with Claude Code
Summary by CodeRabbit
high/medium/low/unknown).--fail-on supply-chain-combo.--fail-on(includingsupply-chain-combo).