@preventive/triage 1.0.0-alpha.34 → 1.0.0-alpha.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/client-managed.js +1 -1
- package/out/terminal.js +320 -212
- package/out/view.js +18 -18
- package/package.json +1 -1
package/out/client-managed.js
CHANGED
|
@@ -263,7 +263,7 @@ ${f.join(`
|
|
|
263
263
|
@container scan-page (max-width: 34rem) { .bundle-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem .65rem; } .scope-head { flex-wrap: wrap; } .scope-head p { flex-basis: 100%; justify-content: start; margin-left: 1.4rem; text-align: left; } .scope-head p span { white-space: normal; } .scope-head p span + span { padding-left: 0; border-left: 0; } .scan-row { grid-template-columns: 1fr; gap: .55rem; } .scan-actions { justify-content: flex-start; } .head-tabs { margin-left: 0; } }
|
|
264
264
|
`;S();var Fa=[{key:"metro",label:"metro",subtitle:"Metro bundle contents"},{key:"run",label:"run",subtitle:"Node.js CLI"},{key:"add",label:"add",subtitle:"Manually added files"}];function Ha(r){let e=r.filter(i=>i.id!=="all");if(e.length===0)return null;let t=new Map(e.map(i=>[String(i.id).replace(/^reason:/u,""),i]));return t.size!==e.length||[...t.keys()].some(i=>!Fa.some(s=>s.key===i))?null:[{id:"",label:"All files",subtitle:"Everything"},...Fa.filter(i=>t.has(i.key)).map(({key:i,...s})=>({...s,id:t.get(i).id,subtitle:i==="run"&&t.has("metro")?"Bundler and Node.js CLI":s.subtitle}))]}var ss=class extends A{static properties={reasons:{attribute:!1},value:{attribute:!1},label:{type:String}};constructor(){super(),this.reasons=[],this.value="",this.label="Choose scope"}_select(e){this.dispatchEvent(new CustomEvent("scope-change",{detail:{value:e},bubbles:!0,composed:!0}))}render(){let e=this.reasons.filter(s=>s.id!=="all");if(e.length===0)return m;let t=Ha(e);if(!t)return c`<label class="scope-field"><span>Scope</span><select aria-label="${this.label}" .value="${G(this.value==="all"?"":this.value)}" @change="${s=>this._select(s.target.value)}"><option value="">All files</option>${e.map(s=>c`<option value="${s.id}">${s.label??s.id}</option>`)}</select></label>`;let i=t.find(s=>s.id===this.value)??t[0];return c`<div class="scope-toggle"><div class="scope-options" role="radiogroup" aria-label="${this.label}" aria-describedby="scope-description">${t.map(s=>c`<label class="scope-option"><input type="radio" name="scope" value="${s.id}" .checked="${i.id===s.id}" @change="${()=>this._select(s.id)}"><span>${s.label}</span></label>`)}</div><span class="scope-description" id="scope-description">${i.subtitle}</span></div>`}static styles=z`:host{display:block;min-width:0}*{box-sizing:border-box}.scope-toggle,.scope-field{cursor:default;user-select:none;-webkit-user-select:none}.scope-toggle{display:flex;align-items:center;justify-content:end;flex-wrap:wrap;gap:.4rem .7rem;min-width:0;min-height:2rem}.scope-options{display:flex;flex-shrink:0;min-width:0;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);overflow:hidden;background:var(--bg)}.scope-option{position:relative;flex:1 0 auto}.scope-option+.scope-option{border-left:1px solid var(--border)}.scope-option input{position:absolute;width:1px;height:1px;opacity:0}.scope-option span{display:grid;place-items:center;height:calc(2rem - 2px);padding:.3rem .55rem;color:var(--muted);font-size:.74rem;white-space:nowrap}.scope-option:hover span{color:var(--text);background:var(--surface-active)}.scope-option input:checked+span{color:var(--text);background:var(--surface-active);font-weight:500}.scope-option input:focus-visible+span{outline:2px solid var(--accent);outline-offset:-2px}.scope-description{order:-1;min-width:0;color:var(--muted);font-size:.66rem;line-height:1rem;text-align:right}.scope-field{display:flex;align-items:center;justify-content:end;gap:.5rem;min-width:0;max-width:100%;margin-left:auto;color:var(--muted);font-size:.7rem}select{width:13rem;min-width:0;max-width:100%;padding:.35rem .5rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg);color:var(--text);font:inherit;font-size:.76rem}:host([compact]) .scope-toggle{min-height:0;gap:.3rem .5rem}:host([compact]) .scope-option span{height:auto;padding:2px 8px;font-size:.68rem;line-height:1.2}:host([compact]) .scope-field{font-size:.68rem}:host([compact]) .scope-description{display:none}:host([compact]) select{width:auto;max-width:22ch;padding:2px 6px;font-size:.68rem;line-height:1.2}`};customElements.get("bundle-scope-selector")||customElements.define("bundle-scope-selector",ss);var qa={code:P(lr),report:P(et)},os=class extends A{static properties={hideHeading:{type:Boolean,attribute:"hide-heading"},sourceLoading:{type:Boolean,attribute:!1},selection:{attribute:!1},scopeLabel:{type:String,attribute:"scope-label"},createBundleHref:{attribute:!1},source:{attribute:!1},loadBundle:{attribute:!1},loadModels:{attribute:!1},loadReportSources:{attribute:!1},canRun:{attribute:!1},_loadingBundle:{state:!0},_bundleError:{state:!0},_tab:{state:!0},_mode:{state:!0},_bundles:{state:!0},_repositories:{state:!0},_reportMode:{state:!0},_reportInput:{state:!0},_reportRestore:{state:!0},_scans:{state:!0},_selectedRepoId:{state:!0},_selectedBundleId:{state:!0},_reason:{state:!0},_excluded:{state:!0},_excludedModules:{state:!0},_prompts:{state:!0},_options:{state:!0},_regimes:{state:!0},_regimesReady:{state:!0},_appModel:{state:!0},_appModelAutomatic:{state:!0},_notice:{state:!0}};static styles=Ua;constructor(){super(),this.loadModels=ot,this.canRun=!0,this.hideHeading=!1,this._tab="new",this._mode="code",this.source=null,this.selection=null,this.scopeLabel="Repository",this._pendingSelection=null,this.sourceLoading=!1,this.loadBundle=null,this._loadingBundle=!1,this._bundleError=null,this._bundles=[],this._repositories=[],this._reportMode="link",this._reportInput=null,this._reportRestore=null,this._scans=[],this._selectedRepoId=null,this._selectedBundleId=this._bundles[0]?.id??null,this._reason=this._bundles[0]?.reasons[0]?.id??"",this._excluded=new Set,this._excludedModules=new Set,this._nextPromptId=1,this._prompts=[{id:1,text:""}],this._options={analyzer:"generic",model:null,effort:null,cached:!1,isolate:!1},this._regimes=[],this._appModel=null,this._appModelAutomatic=!0,this._regimesReady=!1,this._notice=null,this._timers=new Set}willUpdate(e){if(e.has("selection")&&(this._pendingSelection=this.selection),e.has("source")&&(this._bundles=this.source?.bundles??[],this._repositories=this.source?.repositories??[],this._scans=this.source?.scans??[]),e.has("source")||e.has("selection")){this._excluded=new Set,this._excludedModules=new Set;let t=this._repositories.find(o=>o.id===this._selectedRepoId),i=this._pendingSelection,s=i?this._bundles.find(o=>o.id===i.bundleId&&(i.repoId==null||o.repoId===i.repoId)):this._bundles.find(o=>o.id===this._selectedBundleId&&o.repoId===this._selectedRepoId)??(this.scopeLabel==="Workspace"?null:this._bundles.find(o=>o.id===this._selectedBundleId))??(t?this._bundles.find(o=>o.repoId===t.id):this._bundles[0]);this._selectedRepoId=s?.repoId??i?.repoId??t?.id??this._repositories[0]?.id??"unattached",this._selectedBundleId=s?.id??null,this._reason=s?.reasons?.[0]?.id??"",i&&(this._tab="new",this._mode=i.mode==="report"?"report":"code",i.mode==="report"&&(this._reportMode="link",this._reportRestore=null,this._reportInput=null,this._pendingSelection=null),this._notice=i.mode==="report"||s||this.source==null?null:"The selected bundle is no longer available in this source. Choose another bundle.",s&&(this._pendingSelection=null))}}updated(e){(e.has("source")||e.has("selection")||e.has("loadBundle"))&&this._loadSelectedBundle()}async _loadSelectedBundle(){this._bundleController?.abort(),this._loadingBundle=!1,this._bundleError=null;let e=this._bundle;if(!this.loadBundle||!e||Array.isArray(e.files))return;let t=this._bundleController=new AbortController;this._loadingBundle=!0;try{let i=await this.loadBundle(e,t.signal);if(t.signal.aborted)return;this._bundles=this._bundles.map(s=>s.id===e.id?{...i,repoId:s.repoId,repo:s.repo}:s),this._reason=i.reasons?.[0]?.id??""}catch(i){t.signal.aborted||(this._bundleError=String(i?.message??i))}finally{t.signal.aborted||(this._loadingBundle=!1)}}disconnectedCallback(){super.disconnectedCallback(),this._bundleController?.abort();for(let e of this._timers)clearTimeout(e);this._timers.clear()}get _repoBundles(){return this._bundles.filter(e=>e.repoId===this._selectedRepoId)}get _bundle(){return this._repoBundles.find(e=>e.id===this._selectedBundleId)}get _reasonData(){return this._bundle?.reasons.find(e=>e.id===this._reason)??this._bundle?.reasons[0]}_packageLabel(e){return e==="__own__"?"Own code":e}get _scopeFiles(){let e=this._reasonData,t=e?.fileModules,i=e?.filePaths?new Set(e.filePaths):null;return(this._bundle?.files??[]).filter(s=>(t==null||t.includes(s.module))&&(i==null||i.has(s.path))).toSorted((s,o)=>o.bytes-s.bytes)}get _files(){return Zi(this._scopeFiles)}render(){return c`<div class="wrap">${this.hideHeading?c`<h1 class="sr-only">Scans</h1>`:c`<div class="head"><div class="head-title"><slot name="navigation"></slot><h1>Scans</h1></div></div>`}<div class="intro-row"><p class="intro">${this._tab==="history"?"Review past scans and save completed results as reports.":this._mode==="report"?"Choose inputs and start a scan. Save the report when it finishes.":"Choose a bundle and start a scan. Save the report when it finishes."}</p><div class="head-tabs" role="tablist" aria-label="Scan views"><button class="${this._tab==="new"?"active":""}" role="tab" aria-selected="${this._tab==="new"}" @click="${()=>{this._tab="new"}}">New scan</button> <button class="${this._tab==="history"?"active":""}" role="tab" aria-selected="${this._tab==="history"}" @click="${()=>{this._tab="history"}}">Scan history</button></div></div>${this._notice?c`<p class="notice" role="status">${this._notice}</p>`:m} ${this._bundleError?c`<p class="notice" role="alert">Couldn’t load bundle: ${this._bundleError}<button @click="${()=>{this._loadSelectedBundle()}}">Retry</button></p>`:m} ${this._tab==="new"?this._newScan():this._history()}</div>`}_newScan(){let e=this._mode,t=this._bundle,i=e==="code"?this._files:e==="dependencies"?this._scopeFiles:t?.files??[],s=this._excluded,o=this._excludedModules,n=i.filter(f=>!s.has(f.path)&&!o.has(f.module)),a=At(t?.files?n:null),l=new Map;for(let f of i){let b=l.get(f.module)??{bytes:0,count:0,included:0};b.bytes+=f.bytes,b.count++,s.has(f.path)||b.included++,l.set(f.module,b)}let d=[...l.keys()].toSorted((f,b)=>l.get(b).bytes-l.get(f).bytes||this._packageLabel(f).localeCompare(this._packageLabel(b))),u=i.slice(0,80),p=d.filter(f=>!o.has(f)).length,h=this._reportInput?.mode===this._reportMode?this._reportInput.inputs:[];return c`<div class="setup"><scan-mode-selector .mode="${e}" .analyzer="${this._options.analyzer}" .reportMode="${this._reportMode}" @scan-mode-change="${f=>this._changeMode(f.detail.mode)}" @scan-analyzer-change="${f=>this._setOption("analyzer",f.detail.analyzer)}" @scan-report-mode-change="${f=>{this._reportMode=f.detail.mode,this._reportRestore=null}}"></scan-mode-selector>${e==="report"?c`<scan-report-inputs .mode="${this._reportMode}" .loadSources="${this.loadReportSources}" .restore="${this._reportRestore}" @report-inputs-change="${f=>{this._reportInput=f.detail}}"></scan-report-inputs>`:this._sourcePanel(t,i)} ${e==="code"?c`<details class="panel scope-panel"><summary class="scope-head"><svg class="scope-chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 3 5 5-5 5"/></svg><h2>Source filter</h2><p><span>${n.length} of ${i.length} files · ${p} of ${d.length} packages</span> <span>${se(a.bytes)} · ${a.lines==null?"\u2014":a.lines.toLocaleString()} LoC</span></p></summary><div class="scope-grid"><section class="scope-pane package-pane" aria-label="Packages in bundle"><div class="pane-head"><strong>Packages</strong><span>${d.length} total · sorted by size</span></div><div class="package-list">${d.map(f=>{let{bytes:b,count:v,included:y}=l.get(f),g=!o.has(f);return c`<label class="${`package-row ${g?"":"excluded"}`}"><input type="checkbox" .checked="${g}" @change="${k=>this._toggleModule(f)}"><span class="package-name" data-tooltip-truncated data-tooltip="${this._packageLabel(f)}">${this._packageLabel(f)}</span><span class="package-size">${se(b)} · ${y}/${v}</span></label>`})}</div></section><section class="scope-pane file-panel" aria-label="Largest files in bundle"><div class="pane-head"><strong>Largest files</strong><span>showing ${u.length} of ${i.length}</span></div>${i.length===0?c`<p class="empty">No files in this selection.</p>`:c`<div class="file-list">${u.map(f=>{let b=!s.has(f.path)&&!o.has(f.module);return c`<label class="${`file ${b?"":"excluded"}`}"><input type="checkbox" .checked="${b}" @change="${v=>this._toggleFile(f,v.target.checked)}"><span class="file-copy"><span class="file-path" data-tooltip-truncated data-tooltip="${f.path}">${f.path}</span><span class="file-meta">${f.size} · ${this._packageLabel(f.module)}</span></span></label>`})}</div>`}</section></div></details>`:m} ${e==="agentic"?this._agenticPanel():m}<slot name="access"></slot>${this._optionsPanel(e,t,e==="report"?h.length:n.length)}</div>`}_sourcePanel(e,t){if(this.sourceLoading)return c`<section class="panel source-panel" aria-busy="true"><div class="panel-head"><h2>Source</h2></div><p class="empty" role="status">Loading scan sources…</p></section>`;let i=this._mode==="code"?this._repoBundles.map(d=>d.files?{...d,files:Zi(d.files)}:d.summary?{...d,summary:{...d.summary,files:d.summary.codeFiles}}:d):this._repoBundles,{lines:s}=At(e?.files?t:null),o=new Map;for(let d of this._bundles)o.set(d.repoId,(o.get(d.repoId)??0)+1);let n=this._repositories.length>1,a=["code","agentic","dependencies"].includes(this._mode)&&e!=null&&(!e.filename.toLowerCase().endsWith(".map")||e.reasons?.some(d=>d.id!=="all")),l=this._repositories.map(d=>{let u=o.get(d.id)??0;return{value:d.id,label:d.label,detail:`${u} ${u===1?"bundle":"bundles"}`,special:d.id==="unattached"}});return c`<section class="panel source-panel" aria-busy="${this._loadingBundle}"><div class="panel-head"><h2>Source</h2></div><div class="${`source-choice ${n?"":"single-repository"}`}">${n?c`<div class="field"><span>${this.scopeLabel}</span>${this.scopeLabel==="Workspace"?c`<workspace-selector .options="${l}" .value="${this._selectedRepoId}" @workspace-change="${d=>this._selectRepoById(d.detail.value)}"></workspace-selector>`:c`<repository-selector .options="${l}" .value="${this._selectedRepoId}" @repository-change="${d=>this._selectRepoById(d.detail.value)}"></repository-selector>`}</div>`:m}<div class="field">${n||this.createBundleHref?this._bundleLabel():m}${i.length>0?c`<bundle-selector .bundles="${i}" .value="${e?.id??null}" @bundle-change="${d=>this._selectBundleById(d.detail.value)}"></bundle-selector>`:this._emptyBundles()}</div><div class="source-footer"><div class="bundle-stats" aria-label="Bundle statistics"><div class="metric"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="8" cy="4" rx="5" ry="2"/><path d="M3 4v8c0 1.1 2.2 2 5 2s5-.9 5-2V4M3 8c0 1.1 2.2 2 5 2s5-.9 5-2"/></svg><strong>${e?.size??"\u2014"}</strong><span>bundle size</span></div><div class="metric">${qa.report}<strong>${t.length}</strong><span>files</span></div><div class="metric">${qa.code}<strong>${s==null?"\u2014":s.toLocaleString()}</strong><span>LoC</span></div><div class="metric">${P(we)}<strong>${new Set(t.map(d=>d.module)).size}</strong><span>packages</span></div></div>${a?c`<div class="scope-slot">${this._scopeField(e)}</div>`:m}</div></div></section>`}_bundleLabel(){let e=this.createBundleHref?.(this._selectedRepoId);return c`<div class="bundle-label"><span>Bundle</span>${e?c`<a class="create-bundle-button" href="${e}">Create a bundle</a>`:m}</div>`}_emptyBundles(){let e=this.createBundleHref?.(this._selectedRepoId);return c`<div class="choice-empty"><span>${this._bundles.length===0?"No stored bundles.":`No stored bundles for this ${this.scopeLabel.toLowerCase()}.`}</span>${e?c`<a href="${e}">Create?</a>`:m}</div>`}_scopeField(e){if(!["code","agentic","dependencies"].includes(this._mode))return m;let t=(e?.reasons??[]).filter(i=>i.id!=="all");return t.length===0?m:c`<bundle-scope-selector .reasons="${t}" .value="${this._reason}" label="${this._mode==="agentic"?"Choose agentic scope":"Choose scan scope"}" @scope-change="${i=>this._changeReason(i.detail.value)}"></bundle-scope-selector>`}_optionsPanel(e,t,i){let s=e==="report"?`${i} ${this._reportMode==="merge"?"scan results":"reports"} selected`:`${t?.filename??"No bundle selected"} \xB7 ${i} files will be analyzed`,o=e==="code"&&this._options.analyzer==="advanced",n=!this.canRun||(e==="report"?i===0:t==null||i===0||o&&(!this._regimesReady||this._regimes.length===0));return c`<section class="panel options"><div class="options-grid">${o?c`<scan-regime-editor .loadModels="${this.loadModels}" .value="${this._regimes}" .appModel="${this._appModel}" .appModelAutomatic="${this._appModelAutomatic}" @regimes-change="${a=>{this._regimesReady=a.detail.ready,this._regimes=a.detail.value,this._appModel=a.detail.appModel,this._appModelAutomatic=a.detail.appModelAutomatic}}"></scan-regime-editor>`:c`<scan-model-picker .loadModels="${this.loadModels}" ?has-extra="${e==="code"}" .value="${this._options.model}" .effort="${this._options.effort}" @model-change="${a=>{this._options={...this._options,model:a.detail.model,effort:a.detail.effort}}}">${e==="code"?c`<scan-depth-toggle slot="effort-extra" .isolate="${this._options.isolate}" @depth-change="${a=>this._setOption("isolate",a.detail.isolate)}"></scan-depth-toggle>`:m}</scan-model-picker>`}</div><div class="options-footer"><slot name="before-run"></slot><button type="button" class="run" ?disabled="${n}" @click="${()=>this._runScan()}">${e==="report"?this._reportMode==="merge"?"Merge results":"Link reports":"Run scan"}</button><span class="summary">${s}</span></div><div class="checks"><label class="switch"><input type="checkbox" aria-describedby="${this._options.cached?"offline-help":m}" .checked="${this._options.cached}" @change="${a=>this._setOption("cached",a.target.checked)}"><span class="switch-track" aria-hidden="true"></span><span>Offline</span></label>${this._options.cached?c`<small class="offline-help" id="offline-help">Cache only, no new model requests</small>`:m}</div></section>`}_history(){return c`<section class="panel history"><div class="panel-head"><h2>Scan history</h2><p>${this._scans.length} scans</p></div>${this._scans.length===0?c`<p class="empty">No scans yet.</p>`:this._scans.map(e=>this._scanRow(e))}</section>`}_scanRow(e){let t=e.status==="completed"?e.reportSaved?c`<button type="button" class="action" @click="${()=>this._deleteSavedReport(e)}">Delete saved report</button>`:c`<button type="button" class="action" @click="${()=>this._saveReport(e)}">Save report</button>`:m;return c`<div class="scan-row"><div class="scan-main"><div class="scan-title"><strong data-tooltip-truncated data-tooltip="${e.bundleName}">${e.bundleName}</strong><span class="${`status ${e.status}`}">${e.status}</span></div><span class="scan-meta">${e.reason} · ${e.files} ${e.mode==="report"?e.reportMode==="merge"?"results":"reports":"files"} · ${e.createdAt}${e.duration?` \xB7 ${e.duration}`:""}${e.reportSaved?" \xB7 Report saved":e.status==="completed"?" \xB7 Report available":""}</span></div><span class="scan-actions">${t}${e.status==="running"?c`<button type="button" class="action" @click="${()=>this._stopScan(e)}">Stop</button>`:m}${e.status==="stopped"?c`<button type="button" class="action" @click="${()=>this._restartScan(e)}">Restart as new scan</button>`:m}</span><span aria-hidden="true"></span></div>`}_selectBundle(e){this._pendingSelection=null,this._selectedRepoId=e.repoId,this._selectedBundleId=e.id,this._reason=e.reasons?.[0]?.id??"",this._excluded=new Set,this._excludedModules=new Set,this._notice=null,this._loadSelectedBundle()}_selectBundleById(e){let t=this._repoBundles.find(i=>i.id===e);t!=null&&this._selectBundle(t)}_selectRepoById(e){if(e===this._selectedRepoId||!this._repositories.some(i=>i.id===e))return;this._selectedRepoId=e,this._pendingSelection=null;let t=this._bundles.find(i=>i.repoId===e);this._selectedBundleId=t?.id??null,this._reason=t?.reasons[0]?.id??"",this._excluded=new Set,this._excludedModules=new Set,this._notice=null,this._loadSelectedBundle()}_changeMode(e){!["dependencies","code","agentic","report"].includes(e)||e===this._mode||(this._mode=e,this._reportInput=null,this._reportRestore=null,this._excluded=new Set,this._excludedModules=new Set,this._notice=null)}_changeReason(e){this._reason=e,this._excluded=new Set,this._excludedModules=new Set}_toggleFile(e,t){let i=new Set(this._excluded);t?i.delete(e.path):i.add(e.path),this._excluded=i}_toggleModule(e){let t=new Set(this._excludedModules);t.has(e)?t.delete(e):t.add(e),this._excludedModules=t}_setOption(e,t){this._options[e]!==t&&(e==="analyzer"&&t==="advanced"&&(this._regimesReady=!1,this._regimes.length===0&&(this._regimes=[{mode:this._options.analyzer,model:this._options.model,effort:this._options.effort,isolate:this._options.isolate}])),this._options={...this._options,[e]:t})}_agenticPanel(){return c`<section class="panel agentic-panel"><div class="panel-head"><h2>Agentic instructions</h2><button type="button" class="row-action" aria-label="Add prompt" @click="${()=>this._addPrompt()}">${fr}</button></div><div class="agentic-fields">${hr(this._prompts,e=>e.id,(e,t)=>c`<div class="prompt-row"><textarea aria-label="${`Prompt ${t+1}`}" rows="3" placeholder="${this._promptPlaceholder(t)}" .value="${G(e.text)}" @input="${i=>{this._prompts=this._prompts.map(s=>s.id===e.id?{...s,text:i.target.value}:s)}}"></textarea>${this._prompts.length>1?c`<button type="button" class="row-action" aria-label="${`Remove prompt ${t+1}`}" @click="${()=>this._removePrompt(e.id)}">${gr}</button>`:m}</div>`)}</div></section>`}_promptPlaceholder(e){let t=["","second","third","fourth","fifth","sixth","seventh","eighth","ninth","tenth"][e];return t!=null?`What should the ${t?`${t} `:""}agent focus on?`:`What should agent ${e+1} focus on?`}async _addPrompt(){this._prompts=[...this._prompts,{id:++this._nextPromptId,text:""}],await this.updateComplete,this.renderRoot?.querySelector(".prompt-row:last-child textarea")?.focus()}_removePrompt(e){this._prompts.length>1&&(this._prompts=this._prompts.filter(t=>t.id!==e))}_runScan(){if(!this.canRun)return;let e=this._mode,t=e==="code"&&this._options.analyzer==="advanced";if(t&&(!this._regimesReady||this._regimes.length===0))return;let i=this._bundle,s=this._reportInput?.mode===this._reportMode?this._reportInput:null,o=s?.inputs??[],n=e==="code"?this._files.filter(d=>!this._excluded.has(d.path)&&!this._excludedModules.has(d.module)):e==="dependencies"?this._scopeFiles:i?.files??[];if(e==="report"&&(!s?.source||o.length===0)||e!=="report"&&(!i||n.length===0))return;let a={id:`scan-${Date.now()}`,mode:e,bundleId:e==="report"?this._reportMode==="merge"?s.source.id:null:i?.id??null,bundleName:e==="report"?s.source.label:i.filename,reason:e==="report"?this._reportMode==="merge"?"Merge scan results":"Link saved reports":this._reasonData?.label??"All files",status:"running",createdAt:"Just now",duration:"",files:e==="report"?o.length:n.length,reportSaved:!1,cached:this._options.cached,isolate:e==="code"&&this._options.isolate,model:this._options.model,effort:this._options.effort};e!=="report"&&(a.repoId=this._selectedRepoId,a.scopeId=this._reason),e==="code"&&(a.analyzer=this._options.analyzer),t&&(a.regimes=this._regimes.map(d=>({...d})),a.appModel=this._appModel?{...this._appModel}:null,a.appModelAutomatic=this._appModelAutomatic,a.reason=`Advanced \xB7 ${a.regimes.length} regimes \xB7 ${a.reason}`,a.model=null,a.effort=null,a.isolate=!1),e==="agentic"&&(a.prompts=this._prompts.map(d=>d.text)),e==="report"&&(a.reportMode=this._reportMode,a.reportSource={...s.source},a.inputIds=o.map(d=>d.id)),this._scans=[a,...this._scans],this._tab="history",this._notice="Scan started. The server will update its status as work progresses.";let l=setTimeout(()=>{this._timers.delete(l),a.status==="running"&&(a.status="completed",a.duration="2m 14s",this._notice="Scan completed. Its report is ready to save.",this.requestUpdate())},2200);this._timers.add(l)}_stopScan(e){e.status==="running"&&(e.status="stopped",e.duration=e.duration||"stopped by user",this._notice="Scan stopped. It cannot continue, but you can restart it as a new scan.",this.requestUpdate())}_restartScan(e){if(this._options={...this._options,model:e.model??this._options.model,effort:e.effort??this._options.effort,cached:e.cached??!1,isolate:e.isolate??!1,analyzer:e.analyzer??"generic"},e.mode==="report"){this._mode="report",this._reportMode=e.reportMode==="link"?"link":"merge",this._reportInput=null,this._reportRestore={mode:this._reportMode,source:e.reportSource,inputIds:e.inputIds??[]},this._tab="new",this._notice="New report scan settings restored from the stopped run.";return}let t=this._bundles.find(i=>i.id===e.bundleId&&(e.repoId==null||i.repoId===e.repoId));t&&(this._selectBundle(t),this._mode=e.mode??"dependencies",e.mode==="agentic"&&(this._prompts=(e.prompts?.length>0?e.prompts:[""]).map(i=>({id:++this._nextPromptId,text:i}))),e.regimes?.length>0&&(this._options={...this._options,analyzer:"advanced"},this._regimes=e.regimes.map(i=>({...i})),this._appModel=e.appModel?{...e.appModel}:null,this._appModelAutomatic=e.appModelAutomatic!==!1,this._regimesReady=!1),this._reason=t.reasons.find(i=>i.label===e.reason)?.id??t.reasons[0]?.id??"",this._reason=e.scopeId??this._reason,this._tab="new",this._notice="New scan settings restored from the stopped run.")}_saveReport(e){e.reportSaved=!0,this._notice="Report saved. You can delete it from Reports and save this completed scan again.",this.requestUpdate()}_deleteSavedReport(e){e.reportSaved=!1,this._notice="Saved report deleted. The completed scan can be saved again.",this.requestUpdate()}};customElements.get("deepview-scan-page")||customElements.define("deepview-scan-page",os);S();te();var Se=r=>r??m;B();S();var _u={__proto__:null,js:"javascript",mjs:"javascript",cjs:"javascript",jsx:"jsx",ts:"typescript",mts:"typescript",cts:"typescript",tsx:"tsx",json:"json",css:"css",html:"markup",htm:"markup",xml:"markup",svg:"markup",yml:"yaml",yaml:"yaml",sh:"bash",bash:"bash",md:"markdown",markdown:"markdown",sol:"solidity",php:"php",phtml:"php",rs:"rust",rb:"ruby",py:"python",pyw:"python",pyi:"python",java:"java",cpp:"cpp",cc:"cpp",cxx:"cpp","c++":"cpp",hpp:"cpp",hh:"cpp",hxx:"cpp","h++":"cpp",h:"cpp",c:"c",m:"objectivec",mm:"objectivec"},Va={__proto__:null,module:"javascript",commonjs:"javascript","module-typescript":"typescript","commonjs-typescript":"typescript",json:"json",solidity:"solidity",php:"php",shell:"bash",rust:"rust",java:"java",objc:"objectivec",objcpp:"objectivec",c:"c","c-header":"c",cpp:"cpp","cpp-header":"cpp",ruby:"ruby",podspec:"ruby",podfile:"ruby",fastlane:"ruby","podfile-lock":"yaml",xml:"markup"};function vr(r,e){if(typeof e=="string"&&Va[e])return Va[e];if(typeof r!="string")return null;let t=r.slice(r.lastIndexOf("/")+1),i=t.lastIndexOf(".");return i<=0?null:_u[t.slice(i+1).toLowerCase()]??null}var xu=V`<path d="M8 1C4.5 1 4 1.5 4 3v1h4v1H3C1.5 5 1 6 1 8s.5 3 2 3h1V9c0-1.5 1-2 2.5-2H10c1.5 0 2-.5 2-2V3c0-1.5-.5-2-4-2Z" fill="#3776ab"/><path d="M8 1C4.5 1 4 1.5 4 3v1h4v1H3C1.5 5 1 6 1 8s.5 3 2 3h1V9c0-1.5 1-2 2.5-2H10c1.5 0 2-.5 2-2V3c0-1.5-.5-2-4-2Z" fill="#ffd43b" transform="rotate(180 8 8)"/><circle cx="6" cy="2.8" r=".65" fill="#fff"/><circle cx="10" cy="13.2" r=".65" fill="#fff"/>`,$u=V`<path d="m7 0 2 0 .4 1.6 1.3.5 1.4-.9 1.4 1.4-.9 1.4.5 1.3 1.6.4v2l-1.6.4-.5 1.3.9 1.4-1.4 1.4-1.4-.9-1.3.5-.4 1.6H7l-.4-1.6-1.3-.5-1.4.9-1.4-1.4.9-1.4-.5-1.3L1.3 9V7l1.6-.4.5-1.3-.9-1.4 1.4-1.4 1.4.9 1.3-.5Z" fill="#c97d5d"/><circle cx="8" cy="8" r="4.4" fill="var(--surface, #fff)"/><text x="8" y="10.8" text-anchor="middle" fill="currentColor" font-family="serif" font-size="8" font-weight="700">R</text>`;var ku=V`<g fill="#8892bf" transform="translate(0 .5) scale(.5)"><path d="M28 10a4 4 0 0 0-4-4h-6v6a6 6 0 0 1-6 6h-2v2h2v6h4v-6h8v6h4V16h2v-4a2 2 0 0 0-2-2"/><path d="M12 4H8v2a6 6 0 0 0-6 6v6a2 2 0 0 0 2 2v2H2.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5H6a2 2 0 0 0 2-2v-8h4a4 4 0 0 0 4-4V8a4 4 0 0 0-4-4M6 14H4v-2h2Z"/></g>`;function Su(r,e){let t=vr(r,e);return["javascript","jsx"].includes(t)?"js":["typescript","tsx"].includes(t)?"ts":["solidity","rust","php","python","json"].includes(t)?t:"generic"}function ns(r,e){let t=Su(r,e),i=t==="js"||t==="ts"?V`<rect x="1" y="1" width="14" height="14" rx="2" fill=${t==="js"?"#e6c84f":"#3178c6"}/><text x="8" y="11.5" text-anchor="middle" fill=${t==="js"?"#202020":"#fff"} font-family="sans-serif" font-size="8" font-weight="700">${t.toUpperCase()}</text>`:t==="solidity"?V`<path d="m8 1 4 6-4 2-4-2Z" fill="currentColor"/><path d="m4 8 4 2 4-2-4 7Z" fill="currentColor" opacity=".65"/>`:t==="rust"?$u:t==="php"?ku:t==="python"?xu:t==="json"?V`<path d="M3 1h6l5 5v8a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1Z" fill="#e6c84f"/><path d="M9 1v4a1 1 0 0 0 1 1h4Z" fill="#202020" opacity=".2"/><path d="M6.5 6.5h-.75a.75.75 0 0 0-.75.75v1.5L4 9.5l1 .75v1.5a.75.75 0 0 0 .75.75h.75m3-6h.75a.75.75 0 0 1 .75.75v1.5l1 .75-1 .75v1.5a.75.75 0 0 1-.75.75H9.5" fill="none" stroke="#202020" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"/>`:V`<path d="M4 1.5h5l3 3v10H4Zm5 0v3h3M6 8h4M6 10.5h4" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>`;return c`<svg class="source-file-icon" data-file-type="${t}" width="16" height="16" viewBox="0 0 16 16" style="flex: none" aria-hidden="true">${i}</svg>`}var Ga=c`<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.2" style="flex: none" aria-hidden="true"><path d="M1.5 4V2.5h5L8 4h6.5v9h-13Z" stroke-linejoin="round"/></svg>`,m1=c`<svg class="bundle-code-tree-npm" width="12" height="12" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M1 1h14v14H1Zm3 3v8h4V6h2v6h2V4Z"/></svg>`,f1=c`<svg class="bundle-code-tree-soldeer" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="m8 1 6 3.5v7L8 15l-6-3.5v-7Z" fill="none" stroke="currentColor" stroke-width="1"/><path d="m8 3 2.5 4L8 8.5 5.5 7Zm-2.5 5L8 9.5 10.5 8 8 13Z" fill="currentColor"/></svg>`,g1=c`<svg class="bundle-code-tree-composer" width="12" height="12" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 1 15 4.5v7L8 15l-7-3.5v-7Z" fill="#8892bf"/><path d="m1 4.5 7 3.5 7-3.5M8 8v7M4.5 2.75l7 3.5" fill="none" stroke="var(--surface, #fff)" stroke-width=".9"/></svg>`,b1=c`<svg class="bundle-code-tree-cargo" width="12" height="12" viewBox="9.25 6.14 14 14" aria-hidden="true"><path d="m16.264 11.547 6.2-2.446v8.16l-6.2 2.485Zm0-.019-6.2-2.481v8.123l6.2 2.522Z" fill="#e5ac3d" stroke="#73561f" stroke-miterlimit="10" stroke-width=".05430921534373718px"/><path d="m16.277 11.508 6.169-2.435-6.2-2.531-6.2 2.467Z" fill="#e3b04e" stroke="#73561f" stroke-miterlimit="10" stroke-width=".05430921534373718px"/><path d="m12.82 10.149 6.196-2.467" fill="none" stroke="#73561f" stroke-miterlimit="10" stroke-width=".05430921534373718px"/><path d="m18.301 7.395-6.24 2.484 1.482.593 6.196-2.466z" fill="#fff" stroke="#73561f" stroke-miterlimit="10" stroke-width=".04741218643894885px" opacity=".3"/><path d="m13.562 10.47-1.453-.565v1.645l.201-.136.18.285.104.04.138-.121.137.228.129.05.189-.166.238.332.137.053zm-1.423 7.576 1.461.545-.023-1.645-.2.139-.184-.282-.104-.039-.136.123-.14-.226-.131-.049-.186.169-.243-.329-.137-.051z" fill="#fff" stroke="#73561f" stroke-miterlimit="10" stroke-width=".06661495224335688px" opacity=".3"/><path d="m21.426 13.49-.172-.039V13.4l.148-.208a.1.1 0 0 0 .018-.065.035.035 0 0 0-.037-.03l-.189.006-.015-.045.118-.222a.07.07 0 0 0 .007-.063.04.04 0 0 0-.045-.018l-.2.051-.024-.037.084-.229a.06.06 0 0 0 0-.058.04.04 0 0 0-.051-.006l-.2.094-.032-.027.047-.227a.05.05 0 0 0-.016-.052.05.05 0 0 0-.056.007l-.2.133-.039-.017.007-.215a.04.04 0 0 0-.026-.043.07.07 0 0 0-.058.02l-.184.166-.045-.006-.033-.2a.036.036 0 0 0-.036-.032.08.08 0 0 0-.057.031l-.164.194-.049.005-.071-.168a.036.036 0 0 0-.044-.021.1.1 0 0 0-.055.042l-.138.214-.05.016-.107-.135a.04.04 0 0 0-.05-.008.1.1 0 0 0-.05.051l-.107.226-.05.026-.138-.1a.05.05 0 0 0-.055 0 .1.1 0 0 0-.044.058l-.071.228-.049.036-.164-.054a.06.06 0 0 0-.057.017.1.1 0 0 0-.036.063l-.033.223-.045.044-.184-.01a.08.08 0 0 0-.058.029.1.1 0 0 0-.026.065l.007.209-.039.05-.2.035a.1.1 0 0 0-.056.04.1.1 0 0 0-.016.065l.046.187-.032.054-.2.079a.1.1 0 0 0-.051.049.07.07 0 0 0 0 .062l.084.157-.024.057-.2.119a.1.1 0 0 0-.045.057.06.06 0 0 0 .007.057l.118.122-.015.058-.189.155a.1.1 0 0 0-.037.062.045.045 0 0 0 .018.05l.148.082v.055l-.172.185a.1.1 0 0 0-.028.065.04.04 0 0 0 .028.041l.172.039v.051l-.148.208a.1.1 0 0 0-.018.065.035.035 0 0 0 .037.03l.189-.006.015.045-.118.222a.07.07 0 0 0-.007.063.04.04 0 0 0 .045.018l.2-.051.024.037-.084.229a.06.06 0 0 0 0 .058.04.04 0 0 0 .051.006l.2-.094.032.027-.046.227a.05.05 0 0 0 .016.051.05.05 0 0 0 .056-.007l.2-.133.039.017-.007.215a.04.04 0 0 0 .026.043.07.07 0 0 0 .058-.02l.184-.166.045.006.033.2a.035.035 0 0 0 .036.032.08.08 0 0 0 .057-.031l.164-.194.049-.005.071.168a.036.036 0 0 0 .044.02.1.1 0 0 0 .055-.042l.138-.214.05-.016.107.135a.04.04 0 0 0 .05.008.1.1 0 0 0 .05-.051l.107-.226.05-.027.138.1a.05.05 0 0 0 .055 0 .1.1 0 0 0 .044-.058l.071-.228.049-.036.164.054a.06.06 0 0 0 .057-.017.1.1 0 0 0 .036-.063l.033-.223.045-.044.184.01a.08.08 0 0 0 .058-.029.1.1 0 0 0 .026-.065l-.007-.209.039-.05.2-.035a.1.1 0 0 0 .056-.04.1.1 0 0 0 .016-.065l-.046-.187.017-.053.2-.079a.1.1 0 0 0 .051-.049.07.07 0 0 0 0-.062l-.084-.157.024-.057.2-.119a.1.1 0 0 0 .045-.057.06.06 0 0 0-.007-.057l-.118-.122.015-.058.189-.155a.1.1 0 0 0 .037-.062.045.045 0 0 0-.018-.05l-.148-.082v-.055l.172-.185a.1.1 0 0 0 .028-.065.04.04 0 0 0-.014-.039m-1.153 1.988c-.066.013-.108-.037-.094-.112a.21.21 0 0 1 .145-.16c.066-.013.108.037.094.112a.21.21 0 0 1-.145.16m-.059-.39a.19.19 0 0 0-.132.146l-.061.325a2.3 2.3 0 0 1-.619.4 1.4 1.4 0 0 1-.632.123l-.061-.273c-.013-.057-.072-.072-.132-.033l-.252.164a1 1 0 0 1-.13-.106l1.226-.521q.022-.007.023-.026v-.455c0-.013-.009-.012-.023-.006l-.359.152v-.288l.388-.165a.16.16 0 0 1 .239.115c.015.057.049.249.072.3s.117.172.217.13l.611-.26.022-.012a3 3 0 0 1-.139.23Zm-1.7 1.13c-.066.043-.131.026-.145-.037a.2.2 0 0 1 .094-.192c.066-.043.131-.026.145.037a.2.2 0 0 1-.09.192Zm-.465-1.779a.18.18 0 0 1-.062.2c-.062.055-.134.056-.161 0a.18.18 0 0 1 .062-.2c.066-.051.138-.053.165 0Zm-.143.416.263-.234a.16.16 0 0 0 .057-.178l-.054-.105.213-.09v1l-.429.182a1.4 1.4 0 0 1-.057-.407c.001-.052.001-.11.011-.168Zm1.152-.587v-.3l.506-.215c.026-.011.185-.047.185.077 0 .1-.122.192-.222.234l-.47.2Zm1.84-.516v.118l-.154.065a.04.04 0 0 0-.022.036v.074a.31.31 0 0 1-.176.3c-.078.043-.165.036-.176-.01-.046-.253-.123-.278-.245-.327a1 1 0 0 0 .308-.578.3.3 0 0 0-.235-.315.57.57 0 0 0-.322.026l-1.592.677a2.7 2.7 0 0 1 .84-.853l.188.127c.042.029.113 0 .157-.063l.21-.3a.94.94 0 0 1 1.027.33l-.144.4c-.025.069 0 .128.057.13l.277.011q.004.073.004.152Zm-1.591-1.044c.049-.069.126-.1.172-.069s.045.113 0 .183-.126.1-.172.069-.044-.114.005-.184Zm1.427.6a.19.19 0 0 1 .161-.133c.062 0 .089.066.062.142a.19.19 0 0 1-.161.133c-.057-.006-.085-.07-.058-.15Z" opacity=".55"/><path d="M0 16.309h22.926v9.971L45.72 13.139 22.926 0v9.97H0z" fill="#231f20" transform="matrix(0 -.029 .022 .013 10.451 11.138)"/><path d="M0 16.309h22.926v9.971L45.72 13.139 22.926 0v9.97H0z" fill="#231f20" transform="matrix(0 -.029 .022 .013 15.013 12.984)"/></svg>`;var Wa=`:host{padding:0}.field,.browser,.entry-points{line-height:1.5}.note{color:var(--muted);font-size:.75rem}.source-fields{display:grid;grid-template-columns:minmax(12rem,1fr) minmax(0,1.6fr);align-items:end;gap:1rem;margin:1rem 0}.field{display:flex;flex-direction:column;gap:.4rem;min-width:0;font-size:.75rem;color:var(--muted)}.revision{display:flex;align-items:center;min-width:0;height:2rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg)}.revision:focus-within{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.revision-name{flex:1}.revision input{height:100%;min-height:0;padding:.3rem .6rem;min-width:0;border:0;border-radius:0;background:transparent;color:var(--text);font-size:.76rem}.revision input:focus-visible{outline:none}.revision-switch{display:flex;flex:none;align-self:stretch;padding:2px;gap:2px}.revision-switch button{display:grid;place-items:center;width:1.8rem;padding:0;border:0;border-radius:var(--ui-radius, 3px);background:transparent;color:var(--muted)}.revision-switch button:hover:not(:disabled){color:var(--text);background:var(--surface-active)}.revision-switch button:focus-visible{outline-offset:-2px}.revision-switch button[aria-pressed=true]{color:var(--accent);background:color-mix(in srgb,var(--accent) 15%,var(--bg))}.revision-switch svg{width:1rem;height:1rem}.revision-expand{display:grid;place-items:center;align-self:stretch;flex:none;width:2rem;padding:0;border:0;border-radius:var(--ui-radius, 4px);color:var(--muted);background:transparent}.revision-expand svg{width:.9rem;height:.9rem}.revision-expand:hover:not(:disabled){color:var(--text)}.revision-expand:focus-visible{outline-offset:-2px}.revision-menu{visibility:hidden;position:fixed;inset:auto;margin:0;padding:.45rem;overflow:auto;overscroll-behavior:contain;border:1px solid var(--border);border-radius:var(--ui-radius, 8px);background:var(--surface-active);color:var(--text);box-shadow:0 .65rem 1.8rem #00000073}.revision-menu[data-positioned]{visibility:visible}.revision-options{display:grid;grid-template-columns:repeat(var(--revision-columns, 1),minmax(0,1fr));gap:.15rem .5rem}.revision-options button{min-width:0;padding:.4rem .6rem;border:0;border-radius:var(--ui-radius, 4px);background:transparent;color:var(--text);text-align:left;font-size:.76rem}.revision-options button span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.revision-options button[aria-selected=true]{color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent)}.revision-options button:hover,.revision-options button[data-active]{background:color-mix(in srgb,var(--text) 8%,transparent)}.revision-options button[data-active]{outline:1px solid var(--accent);outline-offset:-1px}.revision-empty{margin:0;padding:.65rem;color:var(--muted);font-size:.75rem}button:disabled,input:disabled{opacity:.5}.browser{border:1px solid var(--border);border-radius:var(--ui-radius, 7px);overflow:hidden}.browser-head{display:flex;align-items:center;gap:.75rem;padding:.65rem .8rem;border-bottom:1px solid var(--border);background:var(--bg);font-size:.75rem}.commit-link{display:inline-flex;align-items:center;flex:none;gap:.3rem;margin-left:auto;color:var(--muted);text-decoration:none}.commit-link svg{width:1rem;height:1rem}.commit-link:hover{color:var(--accent)}.commit-link:focus-visible{outline:1px solid var(--accent);outline-offset:3px;border-radius:var(--ui-radius, 2px)}.breadcrumbs{display:flex;align-items:center;flex-wrap:wrap;gap:.35rem;min-width:0}.breadcrumbs button{border:0;padding:.1rem;background:transparent;color:var(--muted);overflow-wrap:anywhere}.breadcrumbs button[aria-current]{color:var(--text)}.breadcrumbs button:hover:not(:disabled){color:var(--accent)}.file-browser{min-height:18rem;max-height:50vh;overflow:auto;padding:.75rem}.file-browser:has(>.empty){display:grid;place-items:center}.file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,16rem),1fr));gap:.5rem}.file-tile{display:flex;align-items:center;gap:.5rem;min-width:0;height:2.05rem;padding:.4rem .6rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg);color:var(--text);font-size:.75rem}.file-tile>span:not(.arrow){overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.file-tile input{width:.85rem;height:.85rem;margin:0;accent-color:var(--accent);flex:none}.file-tile:hover,.file-tile:focus-within{border-color:var(--accent)}.file-tile.selected{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,var(--bg))}.directory{color:var(--muted)}.directory .arrow{margin-left:auto}.unsupported{opacity:.55}.empty{margin:0;padding:1rem;border:0;border-radius:0;text-align:center;color:var(--muted);font-size:.8rem;line-height:1.5}.error{color:var(--critical)}.message{padding:.5rem .8rem;color:var(--muted);font-size:.75rem;line-height:1.5}.text-action{border:0;padding:.1rem .2rem;color:var(--accent);background:transparent;font-size:.75rem}.entry-points{display:flex;align-items:center;gap:1rem;margin-top:1rem}.package-suggestions{display:flex;align-items:center;gap:1rem;margin-top:1rem;color:var(--muted);font-size:.75rem}.package-suggestions>div{flex:1;min-width:0}.package-suggestions p{margin:0 0 .4rem}.package-suggestions .suggestions-note{margin:.4rem 0 0}.package-suggestions ul{display:flex;flex-wrap:wrap;gap:.4rem .8rem;padding:0;margin:0;list-style:none;max-height:6rem;overflow:auto}.package-suggestions li{min-width:0;max-width:100%}.package-suggestions li code{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}.package-suggestions .btn{flex:none;font-size:.72rem}.selection{flex:1;min-width:0}.selection .note{margin:.5rem 0 0}.selection-head{display:flex;align-items:center;gap:.75rem}.btn.clear-selection{min-height:1.65rem;padding:.2rem .5rem;font-size:.72rem}h2{margin:0;font-size:.8rem;font-weight:500}h2 span{color:var(--muted);margin-left:.4rem}.entry-points ul{padding:0;display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;max-height:7rem;overflow:auto;margin:.6rem 0 0}.entry-points li{display:flex;align-items:center;gap:.4rem;min-width:0;max-width:100%;padding:.2rem .4rem;border:1px solid var(--border);border-radius:var(--ui-radius, 4px);background:var(--bg);font-size:.72rem}.entry-points li span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.entry-points li button{display:grid;place-items:center;flex:none;width:1.3rem;height:1.3rem;padding:0;border:0;border-radius:var(--ui-radius, 3px);background:transparent;color:var(--muted);cursor:default}.entry-points li button svg{width:1rem;height:1rem}.entry-points li button:hover{color:var(--critical);background:color-mix(in srgb,var(--critical) 12%,transparent)}.entry-points li button:focus-visible{outline:1px solid var(--accent);outline-offset:1px}@container (width <= 45rem){.source-fields{grid-template-columns:1fr}}
|
|
265
265
|
`;S();function Ka(r,e,t){return Ja(r,e,t,c`Entry points declared in <code>package.json</code>`,"Suggested entry points")}function Za(r,e,t,i){return Ja(r,e,t,"Suggested Solidity sources","Suggested Solidity sources",i)}function Ja(r,e,t,i,s,o=!1){let n=r.filter(a=>!e.has(a));return n.length===0&&!o?m:c`<aside class="package-suggestions" aria-label="${s}"><div><p>${i}</p>${n.length>0?c`<ul>${n.map(a=>c`<li><code data-tooltip-truncated data-tooltip="${a}">${a}</code></li>`)}</ul>`:m} ${o?c`<p class="suggestions-note">Suggestions are limited. Browse the source directories to select more files.</p>`:m}</div>${n.length>0?c`<button type="button" class="btn" @click="${()=>t(n)}">Use suggestions</button>`:m}</aside>`}S();var Ya=`:host{padding:0;margin:1.2rem 0}.conditions-head{display:flex;align-items:center;flex-wrap:wrap;gap:.65rem 1rem}.conditions-head[data-conditions-hidden]>:not(slot){visibility:hidden}slot[name=actions]::slotted(*){flex:none}h2{margin:0;font-size:.8rem;font-weight:500}.presets{display:flex;gap:2px;padding:3px;border:1px solid var(--border);border-radius:var(--ui-radius, 6px);background:var(--bg)}.presets button{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .65rem;border:0;border-radius:var(--ui-radius, 3px);background:transparent;color:var(--muted);font-size:.75rem}.presets button:hover{background:var(--surface-active);color:var(--text)}.presets button[aria-pressed=true]{background:color-mix(in srgb,var(--accent) 15%,var(--bg));color:var(--accent)}.presets button:focus-visible{outline-offset:-1px}svg{width:1rem;height:1rem;flex:none}.platforms{display:flex;align-items:center;flex-wrap:wrap;gap:.75rem;font-size:.75rem}.platforms>span{color:var(--muted)}.platforms label{display:inline-flex;align-items:center;gap:.35rem}.platforms input{margin:0;width:.85rem;height:.85rem}.manual-toggle{display:flex;align-items:center;gap:.25rem;margin-left:auto;padding:.25rem 0;border:0;border-radius:var(--ui-radius, 2px);background:transparent;color:var(--muted);font-size:.75rem;white-space:nowrap}.manual-toggle:hover{color:var(--text)}.manual-toggle[hidden]{visibility:hidden}.manual-toggle[aria-expanded=true] svg{transform:rotate(90deg)}#manual-conditions{margin-top:.75rem}.condition-editor{display:flex;align-items:center;flex-wrap:wrap;gap:.35rem;min-height:2.25rem;padding:.3rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg)}.condition-editor:focus-within{border-color:var(--accent)}ul{display:flex;flex-wrap:wrap;gap:.35rem;max-width:100%;margin:0;padding:0;list-style:none}li{display:inline-flex;align-items:center;gap:.35rem;min-width:0;max-width:100%;min-height:1.5rem;padding:0 .25rem 0 .5rem;border:1px solid var(--border);border-radius:var(--ui-radius, 4px);background:var(--surface);color:var(--text);font-size:.73rem}li.preset{padding-right:.5rem}li code{overflow-wrap:anywhere}li button{display:grid;place-items:center;flex:none;width:1.3rem;height:1.3rem;padding:0;border:0;border-radius:var(--ui-radius, 3px);background:transparent;color:var(--muted)}li button:hover{color:var(--critical);background:color-mix(in srgb,var(--critical) 12%,transparent)}.condition-input{display:flex;align-items:center;flex:1;min-width:9rem}.condition-editor input{flex:1;width:0;min-width:0;min-height:1.5rem;padding:.15rem .4rem;border:0;border-radius:0;background:transparent;font-size:.75rem}.condition-editor input:focus-visible{outline:none}p{margin:.5rem 0 0;color:var(--muted);font-size:.7rem}.error{color:var(--critical)}@container (width <= 30rem){.conditions-head{gap:.6rem}.presets{margin-left:auto}.presets button{padding-inline:.4rem}.platforms{flex-basis:100%}}
|
|
266
|
-
`;var ls=["import","require","default"],Eu=[...ls,"node","node-addons","module-sync"],It=[{id:"node",label:"Node.js",conditions:["node"],automatic:Eu,icon:V`<path d="m8 1.5 5.5 3.2v6.6L8 14.5l-5.5-3.2V4.7Z"/><path d="M6 10V6l4 4V6"/>`},{id:"browser",label:"Browser",conditions:["browser","module"],automatic:ls,icon:V`<rect x="1.5" y="2.5" width="13" height="11" rx="1.5"/><path d="M1.5 6h13M4 4.3h.1m2 0h.1"/>`},{id:"metro",label:"Metro",conditions:["react-native"],automatic:ls,icon:V`<rect x="4" y="1.5" width="8" height="13" rx="2"/><path d="M6.5 3.5h3M7 12.5h2"/>`}],Xa=16-Math.max(...It.map(r=>r.conditions.length)),as=[{id:"ios",label:"iOS"},{id:"android",label:"Android"}],Au=new Intl.ListFormat("en",{type:"conjunction"});function Qa(){return{preset:"node",conditions:["node"],platforms:[]}}var cs=class extends A{static styles=[x(N),x(Ya)];static properties={showConditions:{attribute:!1},_preset:{state:!0},_manual:{state:!0},_platforms:{state:!0},_draft:{state:!0},_error:{state:!0},_manualOpen:{state:!0}};constructor(){super(),this.showConditions=!0,this._preset="node",this._manual=[],this._platforms=["ios","android"],this._draft="",this._error="",this._manualOpen=!1}get value(){return{preset:this._preset,conditions:this.conditions,platforms:this._preset==="metro"?[...this._platforms]:[]}}get presetConditions(){return It.find(e=>e.id===this._preset).conditions}get automaticConditions(){return It.find(e=>e.id===this._preset).automatic}get conditions(){return[...new Set([...this.presetConditions,...this._preset==="metro"?[]:this._manual])]}notifyChange(){this.dispatchEvent(new CustomEvent("conditions-change",{detail:this.value,bubbles:!0,composed:!0}))}selectPreset(e){It.find(i=>i.id===e)&&(this._preset=e,this._draft="",this._error="",this.notifyChange())}togglePlatform(e){if(!as.some(i=>i.id===e))return;let t=this._platforms.includes(e);t&&this._platforms.length===1||(this._platforms=as.map(i=>i.id).filter(i=>i===e?!t:this._platforms.includes(i)),this.notifyChange())}addConditions(){if(this._preset==="metro")return;let e=this._draft.trim().split(/[\s,]+/u).filter(Boolean);if(e.length===0)return;if(e.some(i=>this.automaticConditions.includes(i)&&!this.presetConditions.includes(i))){this._error=`${Au.format(this.automaticConditions)} are handled automatically.`;return}if(e.some(i=>i.length>64||i.startsWith(".")||/^\d+$/u.test(i))){this._error="Use condition names of up to 64 characters, without a leading dot or an all-numeric name.";return}let t=[...new Set([...this._manual,...e.filter(i=>!this.presetConditions.includes(i))])];if(t.length>Xa){this._error=`Use up to ${Xa} manual conditions.`;return}this._manual=t,this._draft="",this._error="",this.notifyChange()}removeCondition(e){this.presetConditions.includes(e)||(this._manual=this._manual.filter(t=>t!==e),this._error="",this.notifyChange())}render(){let e=this._preset!=="metro",t=this.automaticConditions.filter(i=>i!=="import"&&i!=="require");return c`<section aria-label="${this.showConditions?"Conditions":"Bundle actions"}"><div class="conditions-head" ?data-conditions-hidden="${!this.showConditions}"><h2 id="conditions-heading">Conditions</h2><div class="presets" role="group" aria-label="Condition preset">${It.map(i=>c`<button type="button" aria-pressed="${this._preset===i.id}" @click="${()=>this.selectPreset(i.id)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${i.icon}</svg>${i.label}</button>`)}</div>${this._preset==="metro"?c`<div class="platforms" role="group" aria-label="Metro platforms"><span>Platforms</span>${as.map(({id:i,label:s})=>c`<label><input type="checkbox" .checked="${this._platforms.includes(i)}" ?disabled="${this._platforms.includes(i)&&this._platforms.length===1}" @change="${()=>this.togglePlatform(i)}">${s}</label>`)}</div>`:m} <button type="button" class="manual-toggle" ?hidden="${!e}" aria-expanded="${this._manualOpen}" aria-controls="manual-conditions" @click="${()=>{this._manualOpen=!this._manualOpen}}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 4 4 4-4 4"/></svg>Manual conditions</button><slot name="actions"></slot></div><div id="manual-conditions" ?hidden="${!this.showConditions||!e||!this._manualOpen}"><form class="condition-editor" @submit="${i=>{i.preventDefault(),this.addConditions()}}"><ul aria-label="Export conditions">${this.conditions.map(i=>this.presetConditions.includes(i)?c`<li class="preset"><code>${i}</code></li>`:c`<li><code>${i}</code><button type="button" aria-label="${`Remove condition ${i}`}" @click="${()=>this.removeCondition(i)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="m4 4 8 8m0-8-8 8"/></svg></button></li>`)}</ul><div class="condition-input"><input type="text" aria-label="Add conditions" aria-describedby="conditions-help" aria-invalid="${!!this._error}" aria-errormessage="condition-error" placeholder="Add condition…" autocomplete="off" maxlength="1040" .value="${this._draft}" @input="${i=>{this._draft=i.target.value,this._error=""}}" @keydown="${i=>{i.key===" "&&!i.isComposing&&(i.preventDefault(),this.addConditions())}}" @blur="${()=>this.addConditions()}"></div></form><p id="conditions-help">Package export conditions. <code>import</code> / <code>require</code>${t.map((i,s)=>c`${s<t.length-1?", ":t.length>1?", and ":" and "}<code>${i}</code>`)} are automatic.</p>${this._error?c`<p id="condition-error" class="error" role="alert">${this._error}</p>`:m}</div></section>`}};customElements.define("bundle-conditions",cs);var el=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"><circle cx="8" cy="8" r="3"/><path d="M1 8h4m6 0h4"/></svg>`,Mu=100,Iu=[{kind:"branch",label:"Branch",icon:c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"><circle cx="4" cy="3" r="1.5"/><circle cx="4" cy="13" r="1.5"/><circle cx="12" cy="3" r="1.5"/><path d="M4 4.5v7m0-3h3a5 5 0 0 0 5-4"/></svg>`},{kind:"tag",label:"Tag",icon:c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round" aria-hidden="true"><path d="M2 2h5.5l6.5 6.5-5.5 5.5L2 7.5Z"/><circle cx="5" cy="5" r="1"/></svg>`},{kind:"commit",label:"Commit SHA",icon:el}];async function ds(r,e,t){let i=await $(`/api/admin/repositories/${r}?${new URLSearchParams(e)}`,{credentials:"same-origin",headers:{accept:"application/json"},signal:t});if(!i.ok){let s=await i.json().catch(()=>null);if(s?.error==="github-rate-limited"){let o=Number(i.headers.get("retry-after")),n=Math.ceil(o/60),a=Number.isFinite(o)&&o>0?` Try again in about ${n} ${n===1?"minute":"minutes"}.`:" Try again after the limit resets.";throw new Error(`GitHub\u2019s API rate limit has been reached.${a}`)}throw s?.error==="github-status-403"?new Error("GitHub denied this request. Check repository access and the GitHub App\u2019s read permissions."):s?.error==="github-unauthorized"?new Error("GitHub authentication has expired or was revoked. Sign in again and check the repository App installation."):s?.error==="github-unreachable"?new Error("Could not connect to GitHub. Try again shortly."):i.status===404?new Error("This repository, revision, or directory is unavailable."):i.status===403?new Error("Repository access is required to browse files."):new Error("Could not load repository files from GitHub. Try again.")}return i.json()}var ps=class extends A{static styles=[x(N),x(Wa)];static properties={installTooltips:{attribute:!1},createBundle:{attribute:!1},_building:{state:!0},_opening:{state:!0},_buildError:{state:!0},initialRepoId:{attribute:!1},_repos:{state:!0},_loadingRepos:{state:!0},_reposError:{state:!0},_repoId:{state:!0},_refs:{state:!0},_refKind:{state:!0},_refName:{state:!0},_path:{state:!0},_entries:{state:!0},_selected:{state:!0},_commit:{state:!0},_packageEntryPoints:{state:!0},_solidityEntryPoints:{state:!0},_soliditySuggestionsLimited:{state:!0},_loadingRefs:{state:!0},_loading:{state:!0},_error:{state:!0},_refsError:{state:!0},_limited:{state:!0},_revisionOpen:{state:!0},_revisionQuery:{state:!0},_activeRevision:{state:!0}};constructor(){super(),this._repos=[],this._loadingRepos=!0,this._reposError="",this.initialRepoId=null,this._building=!1,this._opening=!1,this._buildError="",this._repoId=null,this._refs={branches:[],tags:[]},this._refKind="branch",this._refName="",this._path="",this._entries=null,this._selected=new Set,this._dismissedSuggestions=new Set,this._bundleConditions=Qa(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._commit="",this._directories=new Map,this._loadingRefs=!1,this._loading=!1,this._error="",this._refsError="",this._limited=!1,this._revisionOpen=!1,this._revisionQuery="",this._activeRevision=-1,this._onViewport=()=>this.positionRevisionSuggestions()}connectedCallback(){super.connectedCallback(),globalThis.addEventListener("resize",this._onViewport),globalThis.addEventListener("scroll",this._onViewport,!0)}updated(e){e.has("installTooltips")&&this.installTooltips?.(this.renderRoot),this.positionRevisionSuggestions()}firstUpdated(){this.loadRepositories()}async loadRepositories(){this._reposRequest?.abort(),this.selectRepository(null),this._repos=[],this._reposError="",this._loadingRepos=!0;let e=new AbortController;this._reposRequest=e;try{let t=await ds("browsable",{},e.signal);if(e.signal.aborted)return;this._repos=t.repos,this._repos.some(i=>i.repoId===this.initialRepoId)&&this.selectRepository(this.initialRepoId)}catch{e.signal.aborted||(this._reposError="Could not load repositories. Try again.")}finally{e.signal.aborted||(this._loadingRepos=!1)}}disconnectedCallback(){this._buildRequest?.abort(),this._opening=!1,globalThis.removeEventListener("resize",this._onViewport),globalThis.removeEventListener("scroll",this._onViewport,!0),clearTimeout(this._browseTimer),this._reposRequest?.abort(),this._refsRequest?.abort(),this._request?.abort(),this._directories.clear(),this._dismissedSuggestions.clear(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,super.disconnectedCallback()}resetFiles(){this._buildError="",clearTimeout(this._browseTimer),this._request?.abort(),this._directories.clear(),this._loading=!1,this._entries=null,this._path="",this._commit="",this._selected=new Set,this._dismissedSuggestions.clear(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._error="",this._limited=!1}async selectRepository(e){if(this.closeRevisionSuggestions(),this._refsRequest?.abort(),this.resetFiles(),this._repoId=e,this._refs={branches:[],tags:[]},this._refsError="",this._refKind="branch",this._refName="",e==null){this._loadingRefs=!1;return}let t=new AbortController;this._refsRequest=t,this._loadingRefs=!0;try{let{defaultContents:i,...s}=await ds("refs",{repoId:e,withDefault:"true"},t.signal);if(t.signal.aborted)return;this._refs=s,this._refName=s.defaultBranch||s.branches[0]||"",i?this.useDirectory(i,""):this._refName&&this.loadDirectory("")}catch(i){t.signal.aborted||(this._refsError=i.message)}finally{t.signal.aborted||(this._loadingRefs=!1)}}changeRevision(e,t){this._refsRequest?.abort(),this._loadingRefs=!1,this.resetFiles(),this._refKind=e,this._refName=t}selectRevisionType(e){this._refKind!==e&&(this.closeRevisionSuggestions(),this.changeRevision(e,e==="branch"&&this._refs.defaultBranch||""),this._refName&&this.loadDirectory(""))}editRevision(e){this.changeRevision(this._refKind,e);let t=e.trim();if(!t)return;let i=this._refKind==="branch"?this._refs.branches:this._refs.tags;this._refKind!=="commit"&&(i.includes(t)||this._refKind==="branch"&&t===this._refs.defaultBranch)?this.loadDirectory(""):this._browseTimer=setTimeout(()=>{this.loadDirectory("")},350)}revisionSuggestions(){let e=this._refKind==="branch"?this._refs.branches:this._refKind==="tag"?this._refs.tags:[],t=this._refKind==="branch"&&this._refs.defaultBranch?[this._refs.defaultBranch,...e.filter(s=>s!==this._refs.defaultBranch)]:e,i=this._revisionQuery.trim().toLowerCase();return t.filter(s=>s.toLowerCase().includes(i))}showRevisionSuggestions(e=!0){this._refKind==="commit"||this._repoId==null||this._loadingRefs||(this._revisionQuery=e?"":this._refName,this._activeRevision=-1,this.renderRoot.querySelector(".revision-menu").showPopover())}closeRevisionSuggestions(){this.renderRoot?.querySelector(".revision-menu")?.hidePopover(),this._revisionOpen=!1,this._activeRevision=-1}pickRevision(e){this.editRevision(e),this.renderRoot.querySelector(".revision-name").focus({preventScroll:!0}),this.closeRevisionSuggestions()}positionRevisionSuggestions(){if(!this._revisionOpen)return;let e=this.renderRoot.querySelector(".revision-menu"),t=this.renderRoot.querySelector(".revision-name").getBoundingClientRect(),i=8,s=6,n=15*parseFloat(getComputedStyle(this).fontSize),a=Math.max(1,Math.min(3,Math.ceil(this.revisionSuggestions().length/8),Math.floor((window.innerWidth-2*i)/n))),l=Math.min(Math.max(t.width,a*n),window.innerWidth-2*i);e.style.width=`${l}px`,e.style.setProperty("--revision-columns",a),e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-l-i))}px`;let d=window.innerHeight-t.bottom-s-i,u=t.top-s-i,p=d<Math.min(e.scrollHeight,320)&&u>d;e.style.maxHeight=`${Math.max(0,Math.min(320,p?u:d))}px`,e.style.top=`${Math.max(i,p?t.top-e.offsetHeight-s:t.bottom+s)}px`,e.dataset.positioned=""}async revisionKeyDown(e){if(e.key==="Escape"||e.key==="Tab"){e.key==="Escape"&&this._revisionOpen&&(e.preventDefault(),e.stopPropagation()),this.closeRevisionSuggestions();return}if(e.key==="Enter"){let i=this.revisionSuggestions()[this._activeRevision];this._revisionOpen&&i!=null?(e.preventDefault(),this.pickRevision(i)):this.closeRevisionSuggestions();return}if(this._refKind==="commit"||!["ArrowDown","ArrowUp"].includes(e.key))return;e.preventDefault(),this._revisionOpen||this.showRevisionSuggestions();let t=this.revisionSuggestions().length;this._activeRevision=t===0?-1:e.key==="ArrowDown"?Math.min(this._activeRevision+1,t-1):this._activeRevision<=0?t-1:this._activeRevision-1,await this.updateComplete,this.renderRoot.querySelector("[data-active]")?.scrollIntoView({block:"nearest"})}async loadDirectory(e,t=!1){if(clearTimeout(this._browseTimer),this._repoId==null||!this._refName.trim())return;t&&this.resetFiles(),this._request?.abort();let i=new AbortController;this._request=i,this._path=e,this._entries=null,this._error="",this._limited=!1,this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._loading=!1;let s=this._refName.trim();if(this._refKind==="commit"&&!/^[a-f\d]{7,40}$/iu.test(s)){this._error="Enter a commit SHA with 7 to 40 hexadecimal characters.";return}let o=this._commit||(this._refKind==="commit"?s:`${this._refKind==="branch"?"heads":"tags"}/${s}`),n=JSON.stringify([this._repoId,this._commit,e]),a=this._commit&&this._directories.get(n);if(a){this._directories.delete(n),this._directories.set(n,a),this._entries=a.entries,this._limited=a.limited,this._packageEntryPoints=a.packageEntryPoints,this._solidityEntryPoints=a.solidityEntryPoints,this._soliditySuggestionsLimited=a.soliditySuggestionsLimited;return}this._loading=!0;try{let l=await ds("contents",{repoId:this._repoId,ref:o,path:e},i.signal);if(i.signal.aborted)return;this.useDirectory(l,e)}catch(l){i.signal.aborted||(this._directories.clear(),this._error=l.message)}finally{i.signal.aborted||(this._loading=!1)}}useDirectory(e,t){this._path=t,this._commit=e.commit,this._entries=e.entries.toSorted((s,o)=>+(o.type==="dir")-+(s.type==="dir")||s.name.localeCompare(o.name)),this._limited=e.limited,this._packageEntryPoints=e.packageEntryPoints??[],this._solidityEntryPoints=e.solidityEntryPoints??[],this._soliditySuggestionsLimited=e.soliditySuggestionsLimited??!1;let i=[...this._packageEntryPoints,...this._solidityEntryPoints].filter(s=>!this._dismissedSuggestions.has(s));if(this._selected=new Set([...this._selected,...i]),/^[a-f\d]{40}$/iu.test(e.commit)){let s=JSON.stringify([this._repoId,e.commit,t]);this._directories.set(s,{entries:this._entries,limited:this._limited,packageEntryPoints:this._packageEntryPoints,solidityEntryPoints:this._solidityEntryPoints,soliditySuggestionsLimited:this._soliditySuggestionsLimited}),this._directories.size>Mu&&this._directories.delete(this._directories.keys().next().value)}}toggleFile(e){let t=new Set(this._selected);t.has(e)?(t.delete(e),this._dismissedSuggestions.add(e)):(t.add(e),this._dismissedSuggestions.delete(e)),this._selected=t}clearFiles(){for(let e of this._selected)this._dismissedSuggestions.add(e);this._selected=new Set}hasScriptEntryPoints(){return[...this._selected].some(e=>/\.[cm]?[tj]sx?$/iu.test(e))}async buildBundle(){if(this._building||this._opening||!this.createBundle||!this._commit||this._selected.size===0)return;let e=new AbortController;this._buildRequest=e,this._building=!0,this._buildError="";try{let t=await this.createBundle({repoId:this._repoId,commit:this._commit,entries:[...this._selected],conditions:this._bundleConditions},e.signal);e.signal.aborted||(this._opening=!0,this.dispatchEvent(new CustomEvent("bundle-created",{detail:t,bubbles:!0,composed:!0})))}catch(t){e.signal.aborted||(this._buildError=t.message)}finally{this._building=!1}}render(){let e=this._building||this._opening,t=this._repos.find(a=>a.repoId===this._repoId),i=this._path.split("/").filter(Boolean),s=t&&this._commit?`https://github.com/${[...t.fullName.split("/"),"tree",this._commit,...i].map(encodeURIComponent).join("/")}`:null,o=this.revisionSuggestions(),n=this._refKind==="commit"?"Commit SHA":this._refKind==="tag"?"Tag":"Branch";return c`<p class="intro ui-hint">Choose a repository and revision, then select files to use as entry points.</p><div ?inert="${e}"><div class="source-fields"><div class="field"><span>Repository</span><repository-selector label="Repository" ?disabled="${this._loadingRepos}" .options="${this._repos.map(a=>({value:a.repoId,label:a.fullName}))}" .value="${this._repoId}" @repository-change="${a=>this.selectRepository(a.detail.value)}"></repository-selector></div><form class="revision" @focusout="${a=>{a.currentTarget.contains(a.relatedTarget)||this.closeRevisionSuggestions()}}" @submit="${a=>{a.preventDefault(),this.loadDirectory("",!0)}}"><div class="revision-switch" role="group" aria-label="Revision type">${Iu.map(({kind:a,label:l,icon:d})=>c`<button type="button" aria-label="${l}" data-tooltip="${l}" aria-pressed="${this._refKind===a}" ?disabled="${!t||this._loadingRefs}" @click="${()=>{this.selectRevisionType(a),this.renderRoot.querySelector(".revision-name").focus(),this.showRevisionSuggestions()}}">${d}</button>`)}</div><input class="revision-name" type="text" aria-label="${n}" role="${Se(this._refKind==="commit"?void 0:"combobox")}" aria-autocomplete="${Se(this._refKind==="commit"?void 0:"list")}" aria-expanded="${Se(this._refKind==="commit"?void 0:String(this._revisionOpen))}" aria-controls="${Se(this._refKind==="commit"?void 0:"bundle-revisions")}" aria-activedescendant="${Se(this._revisionOpen&&this._activeRevision>=0?`revision-${this._activeRevision}`:void 0)}" autocomplete="off" placeholder="${this._refKind==="commit"?"Commit SHA\u2026":`Choose or enter a ${this._refKind}\u2026`}" .value="${this._refName}" ?disabled="${!t||this._loadingRefs}" @focus="${()=>this.showRevisionSuggestions()}" @click="${()=>this.showRevisionSuggestions()}" @keydown="${this.revisionKeyDown}" @input="${a=>{this.editRevision(a.target.value),this.showRevisionSuggestions(!1)}}"> ${this._refKind==="commit"?m:c`<button type="button" class="revision-expand" aria-label="${`Show ${this._refKind} suggestions`}" aria-expanded="${this._revisionOpen}" ?disabled="${!t||this._loadingRefs}" @mousedown="${a=>a.preventDefault()}" @click="${()=>{this._revisionOpen?this.closeRevisionSuggestions():(this.renderRoot.querySelector(".revision-name").focus(),this.showRevisionSuggestions())}}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m4 6 4 4 4-4"/></svg></button>`}<div class="revision-menu" id="bundle-revisions" popover="auto" role="listbox" aria-label="${`${n} suggestions`}" @beforetoggle="${a=>{this._revisionOpen=a.newState==="open",delete a.target.dataset.positioned,this._revisionOpen||(this._activeRevision=-1)}}"><div class="revision-options">${o.map((a,l)=>c`<button type="button" role="option" id="${`revision-${l}`}" aria-selected="${a===this._refName}" ?data-active="${l===this._activeRevision}" tabindex="-1" @mousedown="${d=>d.preventDefault()}" @click="${()=>this.pickRevision(a)}"><span data-tooltip-truncated data-tooltip="${a}">${a}</span></button>`)}</div>${o.length>0?m:c`<p class="revision-empty">${this._revisionQuery?"No matching suggestions. Enter a revision name to browse.":`No ${this._refKind} suggestions available.`}</p>`}</div></form></div>${this._reposError?c`<p class="message" role="alert">${this._reposError} <button type="button" class="text-action" @click="${()=>this.loadRepositories()}">Retry</button></p>`:m} ${this._refsError?c`<p class="message" role="status">${this._refsError} <button type="button" class="text-action" @click="${()=>this.selectRepository(this._repoId)}">Retry</button></p>`:m}<section class="browser" aria-label="Repository files" aria-busy="${this._loadingRepos||this._loading||this._loadingRefs}"><div class="browser-head"><nav class="breadcrumbs" aria-label="Repository directory"><button type="button" ?disabled="${!this._commit}" aria-current="${Se(this._path?void 0:"location")}" @click="${()=>this.loadDirectory("")}">${t?.fullName??"Repository"}</button>${i.map((a,l)=>c`<span aria-hidden="true">/</span><button type="button" aria-current="${Se(l===i.length-1?"location":void 0)}" @click="${()=>this.loadDirectory(i.slice(0,l+1).join("/"))}">${a}</button>`)}</nav>${s?c`<a class="commit-link" href="${s}" target="_blank" rel="noopener noreferrer" data-tooltip="${this._commit}" aria-label="${`View directory at commit ${this._commit.slice(0,7)} on GitHub`}">${el}<code>${this._commit.slice(0,7)}</code></a>`:m}</div><div class="file-browser">${this._loadingRepos||this._loading||this._loadingRefs?c`<p class="empty" role="status">${this._loadingRepos?"Loading repositories\u2026":this._loadingRefs?"Loading revisions\u2026":"Loading files\u2026"}</p>`:this._error?c`<p class="empty error" role="alert">${this._error} <button type="button" class="text-action" @click="${()=>this.loadDirectory(this._path)}">Retry</button></p>`:this._entries==null?c`<p class="empty">${t?"Choose a revision to browse its files.":this._repos.length>0?"Select a repository to browse its files.":"No accessible repositories available."}</p>`:this._entries.length===0?c`<p class="empty">This directory is empty.</p>`:c`<div class="file-grid">${this._entries.map(a=>a.type==="dir"?c`<button type="button" class="file-tile directory" @click="${()=>this.loadDirectory(a.path)}">${Ga}<span data-tooltip-truncated data-tooltip="${a.path}">${a.name}</span><span class="arrow" aria-hidden="true">›</span></button>`:c`<label class="${`file-tile ${this._selected.has(a.path)?"selected":""} ${a.type==="file"?"":"unsupported"}`}" data-tooltip="${a.type==="file"?m:`${a.path} (${a.type})`}"><input type="checkbox" aria-label="${`Select ${a.path} as an entry point`}" .checked="${this._selected.has(a.path)}" ?disabled="${a.type!=="file"}" @change="${()=>this.toggleFile(a.path)}">${ns(a.name)}<span data-tooltip-truncated data-tooltip="${a.type==="file"?a.path:m}">${a.name}</span></label>`)}</div>`}</div>${this._limited?c`<p class="message">Showing GitHub’s first 1,000 entries in this directory.</p>`:m}</section>${Ka(this._packageEntryPoints,this._selected,a=>{this._selected=new Set([...this._selected,...a])})} ${Za(this._solidityEntryPoints,this._selected,a=>{this._selected=new Set([...this._selected,...a])},this._soliditySuggestionsLimited)}<section class="entry-points" aria-label="Selected entry points"><div class="selection"><div class="selection-head"><h2>Entry points <span aria-live="polite">${this._selected.size}</span></h2>${this._selected.size>0?c`<button type="button" class="btn clear-selection" @click="${this.clearFiles}">Clear all</button>`:m}</div>${this._selected.size>0?c`<ul>${[...this._selected].map(a=>c`<li>${ns(a)}<span data-tooltip-truncated data-tooltip="${a}">${a}</span><button type="button" aria-label="${`Remove ${a}`}" @click="${()=>this.toggleFile(a)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="m4 4 8 8m0-8-8 8"/></svg></button></li>`)}</ul>`:c`<p class="note">Select files above. You can choose entry points from multiple directories.</p>`}</div></section><bundle-conditions .showConditions="${this.hasScriptEntryPoints()}" @conditions-change="${a=>{this._bundleConditions=a.detail}}"><button type="button" slot="actions" class="btn primary" ?disabled="${e||!this.createBundle||!this._commit||this._selected.size===0||this._loading||this._loadingRefs}" @click="${this.buildBundle}">${this._opening?"Opening\u2026":this._building?"Creating\u2026":"Create a bundle"}</button></bundle-conditions></div>${e?c`<p class="message" role="status">${this._opening?"Opening bundle\u2026":"Building the selected entry points with Stasis\u2026"}</p>`:m} ${this._buildError?c`<p class="message error" role="alert">${this._buildError}</p>`:m}`}};customElements.define("managed-create-bundle",ps);var Lu=Object.freeze({javascript:"JavaScript",jsx:"JSX",typescript:"TypeScript",tsx:"TSX",json:"JSON",css:"CSS",markup:"HTML",yaml:"YAML",bash:"Shell",markdown:"Markdown",solidity:"Solidity",php:"PHP",rust:"Rust",ruby:"Ruby",java:"Java",cpp:"C++",c:"C",objectivec:"Objective-C",python:"Python",go:"Go",kotlin:"Kotlin",swift:"Swift",dart:"Dart",sql:"SQL",lua:"Lua",csharp:"C#",scala:"Scala",vue:"Vue",svelte:"Svelte"}),zu=Object.freeze({py:"python",pyw:"python",go:"go",kt:"kotlin",kts:"kotlin",swift:"swift",dart:"dart",sql:"sql",lua:"lua",cs:"csharp",scala:"scala",sc:"scala",vue:"vue",svelte:"svelte"});function Ou(r){let e=typeof r=="string"?r.slice(r.lastIndexOf("/")+1):"",t=e.lastIndexOf("."),i=t>0?e.slice(t+1).trim().toLowerCase():"",s=vr(r)??zu[i];return s?{key:s,label:Lu[s]??s}:i?{key:`extension:${i}`,label:`.${i}`}:{key:"other",label:"Other"}}function tl(r,e){let t=new Map,i=0,s=0;for(let[o,n]of r){let a=Ou(o),l=t.get(a.key)??{...a,files:0,lines:0,bytes:0};l.files++,l.lines+=n,l.bytes+=e.get(o)??0,t.set(a.key,l),s+=n,i+=e.get(o)??0}return{files:r.size,lines:s,bytes:i,languages:[...t.values()].toSorted((o,n)=>n.lines-o.lines||o.label.localeCompare(n.label))}}hs();var Tu=new Set(["module","commonjs","json","module-typescript","commonjs-typescript"]),Nu=new Set(["solidity","php","shell","rust"]),Pu=new Set(["java","kotlin","gradle","objc","objcpp","swift","c","cpp","c-header","cpp-header","ruby","python","cmake","podspec","podfile","podfile-lock","template","xml","env","fastlane","pbxproj"]),Bu=new Set(["resource","resource:base64"]),ol=new Set(["stat:file","stat:directory"]),Du=new Set([...Tu,...Nu,...Pu,...Bu,"patch","directory",...ol]),ms=r=>ol.has(r);var rl=r=>r==="directory"||r==="stat:directory"?"directory":"file";function ju(r,e,t){if(r===e)return r;let i=ms(r);if(i!==ms(e)&&rl(r)===rl(e))return i?e:r;throw new Error(`format conflict for '${t}' ('${e}' vs '${r}')`)}function Ue(r,e){return e===""?r:r==="."?e:`${r}/${e}`}var Uu=/^(?=[A-Za-z0-9-]{1,39}\/)[A-Za-z0-9](?:-?[A-Za-z0-9])*\/(?!\.\.?$)[\w.-]{1,100}$/u,Fu=/^(?!\.\.?(?:\/|$))[\w.~@+-]+(?:\/(?!\.\.?(?:\/|$))[\w.~@+-]+)*$/u,Hu=/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/u,fs={github:r=>typeof r=="string"&&Uu.test(r),directory:r=>typeof r=="string"&&r.length<=1024&&(r===""||Fu.test(r)),commit:r=>typeof r=="string"&&Hu.test(r)},nl=(r,e)=>r?.toLowerCase()===e?.toLowerCase();var _r=(r,e,t)=>{if(r===void 0)return;Fe(r)||_(!1,`${t} must be an object`);for(let s of Object.keys(r))Object.hasOwn(e,s)||_(!1,`unknown ${t} key '${s}'`);let i=Object.entries(e).map(([s,o])=>typeof o=="object"?[s,_r(r[s],o,`${t}.${s}`)]:(r[s]!==void 0&&!o(r[s])&&_(!1,`invalid ${t}.${s}: ${JSON.stringify(r[s])}`),[s,r[s]])).filter(([,s])=>s!==void 0);return i.length===0?void 0:Object.freeze(X(i))},xr=(r,e="bundle repo")=>_r(r,fs,e),qu=(r,e)=>e??(He(r)?"npm":void 0),al=(r,{ecosystem:e,repo:t},i)=>{if(t!==void 0)return qu(r,e)===void 0&&_(!1,`${i}: '${r}' is no dependency's bucket, and carries no repo`),xr(t,`${i} module '${r}' repo`)},wr=({name:r,version:e,ecosystem:t,repo:i,files:s})=>({name:r,version:e,...t===void 0?{}:{ecosystem:t},...i===void 0?{}:{repo:i},files:s});function gs({name:r,version:e,ecosystem:t,repo:i,files:s},o,n){return _(t===void 0||typeof t=="string"),wr({name:r,version:e??void 0,ecosystem:t,repo:al(o,{ecosystem:t,repo:i},n),files:X(Object.entries(s))})}function ll(r,{scope:e="full"}={}){let t=new Set;for(let[i,{files:s}]of r)if(!(e!=="full"&&!He(i)))for(let o of Object.keys(s))t.add(Ue(i,o));return t}function Vu(r,{what:e,files:t,formats:i,scope:s}){if(r.includes("\\"))return"holds a '\\'";if(Lt(r))return"escapes the root";if(s!=="full"&&!He(r))return`is outside node_modules, which a '${s}'-scope ${e} does not record`;if(!t.has(r))return`names no file the ${e} records`;let o=i.get(r);return o==="directory"?"is a directory capture, not a file":ms(o)?`is a payload-free '${o}' record, not a file`:null}function cl(r,{what:e,files:t,formats:i,scope:s}){for(let o of r){let n=Vu(o,{what:e,files:t,formats:i,scope:s});_(n===null,`${e}: executable entry '${o}' ${n}`)}}function dl(r,{what:e,files:t,formats:i,scope:s="full"}){if(r===void 0)return new Set;let o=`${e}: executable`;_(Array.isArray(r),`${o} must be an array of file paths`);let n=new Set;for(let a of r)_(typeof a=="string"&&a!=="",`${o} entry must be a non-empty string`),_(!n.has(a),`${o} entry '${a}' is listed twice`),n.add(a);return cl(n,{what:e,files:t,formats:i,scope:s}),n}function pl(r,{what:e,modules:t,formats:i,scope:s}){if(r.size!==0)return cl(r,{what:e,files:ll(t,{scope:s}),formats:i,scope:s}),$r(r)}function _(r,e){if(!r)throw new Error(e)}function ul(r,e){let[t,i]=[r.split("/"),e.split("/")];for(;t.length>0&&t[0]===i[0];)t.shift(),i.shift();if(t.length===0&&i.length===0)return 0;if(t.length<2)return i.length<2&&t>i?1:-1;if(i.length<2)return 1;if(t[0]==="*")return-1;if(i[0]==="*"||t[0]==="node_modules")return 1;if(i[0]==="node_modules")return-1;let[s,o]=[t,i].map(n=>n.join(String.fromCodePoint(0)));if(s<o)return-1;if(s>o)return 1;throw new Error("Unreachable")}var yr=(r,e)=>ul(r[0],e[0]),Fe=r=>r&&[null,Object.prototype].includes(Object.getPrototypeOf(r)),X=r=>Object.setPrototypeOf(Object.fromEntries(r),null),$r=r=>[...r].toSorted(ul),bs=(r,{sorted:e=!0}={})=>{let t=e?[...r].toSorted(yr):[...r];return X(t.map(([i,s])=>[i,s instanceof Map?bs(s,{sorted:e}):s]))},il=(r,e)=>r.get(e)??r.set(e,new Map).get(e),hl=r=>new Map(Object.entries(r).map(([e,t])=>[e,Fe(t)?hl(t):t]));function Lt(r){if(r.startsWith("/"))return!0;if(!r.includes(".."))return!1;let e=0;for(let t of r.split("/"))if(!(t==="."||t==="")){if(t!=="..")e++;else if(--e<0)return!0}return!1}var ml=r=>r.includes("\\")||Lt(r),le=(r,e)=>_(!ml(r),`${e}: path '${r}' escapes the root or holds a '\\'`),fl=(r,e)=>_(typeof r=="string"&&r!==""&&!ml(r),`${e}: invalid entry ${JSON.stringify(r)}`);function gl(r,e){_(Array.isArray(r),`${e}: entries must be an array of file paths`);let t=new Set;for(let i of r)fl(i,e),_(!t.has(i),`${e}: entry '${i}' is listed twice`),t.add(i);return t}function bl(r,e){for(let t of r)fl(t,e);return $r(r)}function vl(r,e){le(r,"formats"),_(Du.has(e),`unknown format '${e}' for ${r}`)}function yl(r){_(Fe(r));let e=new Map;for(let[t,i]of Object.entries(r)){vl(t,i);let s=t===""?".":t;_(!e.has(s),`duplicate format key '${s}'`),e.set(s,i)}return e}function wl(r){for(let[e,t]of r)vl(e,t);return bs(r)}function _l(r){for(let[,e]of r){_(e instanceof Map);for(let[t,i]of e){le(t,"imports"),_(i instanceof Map);for(let[,s]of i){if(typeof s=="string"){le(s,"imports");continue}_(s instanceof Map&&s.size>0,"import target must be a file or a non-empty {platform: file} map");for(let[o,n]of s)_(typeof o=="string"&&o.length>0&&!o.includes("/"),`invalid platform key '${o}'`),_(typeof n=="string"),le(n,"imports")}}}}function xl(r){_(Fe(r));let e=hl(r);return _l(e),e}function $l(r){return _l(r),bs(r)}function kl(r,{skipEmpty:e=!1,repo:t=!0,what:i}={}){let s={modules:[],sources:[]};for(let[o,n]of r){if(e&&Object.keys(n.files).length===0)continue;let a=He(o);a&&_(n.name&&n.version&&n.files);let l=X(Object.entries(n.files).toSorted(yr));s[a?"modules":"sources"].push([o,wr({...n,repo:t?al(o,n,i):void 0,files:l})])}return{modules:X(s.modules.toSorted(yr)),sources:X(s.sources.toSorted(yr))}}function Gu(r,e){let t=r instanceof Map;if(t!==e instanceof Map)return!1;if(!t)return r===e;if(r.size!==e.size)return!1;for(let[i,s]of r)if(e.get(i)!==s)return!1;return!0}var sl=r=>r instanceof Map?`{${[...r].map(([e,t])=>`${e}: ${t}`).join(", ")}}`:r;function Sl(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=il(i,n);for(let[d,u]of a){let p=il(l,d);for(let[h,f]of u)p.has(h)?_(Gu(p.get(h),f),`${t}: import '${h}' from '${d}' resolves differently ('${sl(p.get(h))}' vs '${sl(f)}')`):p.set(h,f instanceof Map?new Map(f):f)}}};return s(r),s(e),i}function Cl(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=i.get(n);if(l===void 0){i.set(n,a);continue}try{i.set(n,ju(a,l,n))}catch(d){throw new Error(`${t}: ${d.message}`,{cause:d})}}};return s(r),s(e),i}function Rl(r,e,t,i){if(r.size===0)return new Set(e);let s=ll(t,{scope:i}),o=new Set(e);for(let n of r)s.has(n)||o.add(n);return o}var Wu=/(?:^|\/)\.{0,2}(?:\/|$)/u;function kr(r,e,t){let i=Ue(r,e);return(i!=="."||e!=="")&&Wu.test(i)&&_(!1,`${t}: non-canonical file key ${JSON.stringify(i)}`),i.includes("\\")&&_(!1,`${t}: file key '${i}' holds a '\\', which no path may`),i}function Sr(r,e,t){let i=new Map;for(let[s,{files:o}]of r){typeof s!="string"&&_(!1,`${e}: bucket dir ${String(s)} is not a string`),le(s,e);for(let n of Object.keys(o)){let a=kr(s,n,e),l=i.get(a);l!==void 0&&t(a,l,s),i.set(a,s)}}return i}var El=(r,e)=>t=>_(!1,`duplicate file key '${t}' across ${r} buckets -- module bucketing changed between writes (a workspace package without a version now owns its own bucket); regenerate the ${e}`);function Al(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=i.get(n);if(l===void 0){i.set(n,wr({...a,files:Object.assign(Object.create(null),a.files)}));continue}_(l.name===a.name,`${t}: module '${n}' name mismatch ('${l.name}' vs '${a.name}')`),_(l.version===a.version,`${t}: module '${n}' version mismatch ('${l.version}' vs '${a.version}')`+(l.version==null==(a.version==null)?"":" -- an artifact from an older stasis may record a placeholder version for a workspace package without one; regenerate it (bundle=replace / lock=replace)")),_(l.ecosystem===a.ecosystem,`${t}: module '${n}' ecosystem mismatch ('${l.ecosystem??"(none)"}' vs '${a.ecosystem??"(none)"}')`),l.repo===void 0&&a.repo!==void 0&&i.set(n,wr({...l,repo:a.repo}));for(let[d,u]of Object.entries(a.files))Object.hasOwn(l.files,d)?_(l.files[d]===u,`${t}: content mismatch for '${Ue(n,d)}'`):l.files[d]=u}};return s(r),s(e),Sr(i,t,(o,n,a)=>_(!1,`${t}: file '${o}' is bucketed under both '${n}' and '${a}' -- module bucketing changed between the artifacts (a workspace package without a version now owns its own bucket); regenerate the artifact (bundle=replace / lock=replace)`)),i}function He(r){return r.split("/").includes("node_modules")}function Ku(r){let e="node_modules/",t=r.length;for(;(t=r.lastIndexOf(e,t-1))!==-1;)if(t===0||r[t-1]==="/")return t;return-1}function Ml(r){let e="node_modules/",t=Ku(r);if(t===-1)return null;let i=t+e.length,s=r.slice(i).split("/"),o=s[0].startsWith("@")?2:1;if(s.length<=o||s.slice(0,o).some(a=>!a))return null;let n=s.slice(0,o).join("/");return{dir:r.slice(0,i)+n,rel:s.slice(o).join("/"),name:n}}var Ce=1,Il=0,Ll=El("bundle","artifact (bundle=replace)"),zl=r=>Ml(r)??{dir:".",rel:r==="."?"":r,name:null};function Zu(){throw new Error("bundle: file contents are not retained by this contents-free Bundle")}var Ju=(r,{files:e,...t})=>{let i=Object.create(null);for(let[s,o]of Object.entries(e))typeof o!="symbol"&&_(!1,`bundle: file '${Ue(r,s)}' is not a placeholder`),Object.defineProperty(i,s,{get:Zu,enumerable:!0});return{...t,files:Object.freeze(i)}},vs=(r,e)=>{if(r===void 0&&e===void 0)return;let t=new Map;for(let i of[r,e])for(let[s,o]of Object.entries(i??{})){if(!Array.isArray(o))continue;let n=t.get(s);n===void 0&&t.set(s,n=new Set);for(let a of o)n.add(a)}return X([...t.keys()].toSorted().map(i=>[i,$r(t.get(i))]))};var Yu=(r,e)=>{if(r?.github===void 0||!nl(r.github,e?.github))return;let t=Object.keys(fs).filter(i=>r[i]!==void 0&&(i==="github"||r[i]===e[i]));return X(t.map(i=>[i,r[i]]))},Xu=r=>{if(!Fe(r)||r.root!==!0||Object.hasOwn(r,"directory"))return r;let{root:e,...t}=r;return t},Ol=r=>typeof r=="string"&&/^[\w.+@/~'!()*-]+$/u.test(r),ys={name:Ol,version:Ol},Tl={npm:ys,composer:ys,cargo:ys},Qu=(r,e)=>X(Object.keys(Tl).map(t=>{let[i,s]=[r?.[t],e?.[t]];return[t,i?.name!==void 0&&i.name===s?.name?X(Object.entries(i).filter(([o,n])=>n===s[o])):void 0]})),qe=class r{static VERSION=Ce;version=Ce;config;entries;modules;formats;imports;executable;reason;#e;get repo(){return this.#e}set repo(e){this.#e=xr(e)}#t;get package(){return this.#t}set package(e){this.#t=_r(e,Tl,"bundle package")}constructor({config:e={scope:"full"},entries:t,modules:i,formats:s,imports:o,executable:n,reason:a,repo:l,package:d,version:u=Ce}={}){_([Il,Ce].includes(u)),_(["node_modules","full"].includes(e.scope)),this.version=u,this.config=e,this.entries=t??new Set,this.modules=i??new Map,this.formats=s??new Map,this.imports=o??new Map,this.executable=n??new Set,this.reason=a,this.repo=xr(l),this.package=d}get sources(){let e=new Map;for(let[t,{files:i}]of this.modules)for(let[s,o]of Object.entries(i))e.set(Ue(t,s),o);return e}static isResourceFormat(e){return e==="resource"||e==="resource:base64"||e==="directory"}get hasCode(){for(let[e,{files:t}]of this.modules)for(let i of Object.keys(t))if(!r.isResourceFormat(this.formats.get(Ue(e,i))))return!0;return!1}static parse(e){return r.fromJSON(JSON.parse(e))}static fileKeyAt(e){let[t,i,s,o]=e;if(typeof i=="string"){if(e.length===2&&t==="sources"){let n=zl(i);return kr(n.dir,n.rel,"bundle")}if(e.length===4&&(t==="sources"||t==="modules")&&s==="files"&&typeof o=="string")return kr(i,o,"bundle")}}static fromJSON(e,{contents:t=!0}={}){_(e.version===Ce||e.version===Il),_(["node_modules","full"].includes(e.config?.scope));let i=yl(e.formats),s=new Map,o=new Set;if(e.version===Ce){let l=e.config.scope==="full";if(e.modules!==void 0){_(typeof e.modules=="object"&&e.modules!==null);for(let[d,u]of Object.entries(e.modules))_(He(d)),le(d,"bundle"),_(u?.name&&u.version&&u.files),s.set(d,gs(u,d,"bundle"))}if(l){_(e.sources&&typeof e.sources=="object");for(let[d,u]of Object.entries(e.sources))_(!He(d)),le(d,"bundle"),_(u?.name&&u.files),s.set(d,gs(u,d,"bundle"));e.entries!==void 0&&(o=gl(e.entries,"bundle"))}else _(e.entries===void 0),_(e.sources===void 0)}else{_(e.sources);for(let[l,d]of Object.entries(e.sources)){le(l,"bundle");let{dir:u,rel:p,name:h}=zl(l);_(!Lt(u)&&!Lt(p)),s.has(u)||s.set(u,{name:h,version:null,files:Object.create(null)});let{files:f}=s.get(u);_(!Object.hasOwn(f,p),"bundle: duplicate file key '.' (v0 '' and '.')"),f[p]=d}}let n=Sr(s,"bundle",Ll),a=xl(e.imports);if(!t)for(let[l,d]of s)s.set(l,Ju(l,d));return new r({version:e.version,config:e.config,entries:o,modules:s,formats:i,imports:a,executable:e.version===Ce?dl(e.executable,{what:"bundle",files:n,formats:i,scope:e.config.scope}):new Set,reason:Fe(e.reason)?e.reason:void 0,repo:Xu(e.repo),package:e.package})}serialize(){Sr(this.modules,"bundle",Ll);let{modules:e,sources:t}=kl(this.modules,{skipEmpty:!0,what:"bundle"}),i=this.config.scope==="full",s={version:Ce,config:this.config};this.repo!==void 0&&(s.repo=this.repo),this.package!==void 0&&(s.package=this.package),i&&(s.entries=bl(this.entries,"bundle")),s.formats=wl(this.formats),s.imports=$l(this.imports);let o=pl(this.executable,{what:"bundle",modules:this.modules,formats:this.formats,scope:this.config.scope});return o!==void 0&&(s.executable=o),this.reason!==void 0&&(s.reason=vs(this.reason,void 0)),i&&(s.sources=t),s.modules=e,JSON.stringify(s,void 0,2)}withReason(e){let{version:t,config:i,entries:s,modules:o,formats:n,imports:a,executable:l,repo:d,package:u}=this,p=vs(this.reason,{[e]:[...this.sources.keys()]});return new r({version:t,config:i,entries:s,modules:o,formats:n,imports:a,executable:l,reason:p,repo:d,package:u})}merge(e){return _(this.config.scope===e.config.scope,`bundle merge: scope mismatch ('${this.config.scope}' vs '${e.config.scope}')`),new r({config:{scope:this.config.scope},entries:new Set([...this.entries,...e.entries]),modules:Al(this.modules,e.modules,"bundle merge"),formats:Cl(this.formats,e.formats,"bundle merge"),imports:Sl(this.imports,e.imports,"bundle merge"),executable:Rl(this.executable,e.executable,e.modules,this.config.scope),reason:vs(this.reason,e.reason),repo:Yu(this.repo,e.repo),package:Qu(this.package,e.package)})}};var eh=new TextEncoder,H1=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});var th=2;function ws(r){if(typeof r!="string")throw new TypeError(`utf8ByteLength expects a string, got ${typeof r}`);if(/[\u0100-\uFFFF]/.test(r))return eh.encode(r).byteLength;let e=/[\u0080-\u00FF]/gu,t=r.length;for(;e.test(r);){let i=e.lastIndex-1;for(let s=0;i<r.length&&s<th;i++)r.codePointAt(i)>127?(t++,s=0):s++;e.lastIndex=i}return t}var _s=new WeakMap,xs=new WeakMap,$s=new WeakMap;function Cr(r){if(r?.metadataOnly)return new Map;let e=r?.bundle??r?.json;if(e&&_s.has(e))return _s.get(e);let t=new Map;if(!r)return t;if(r.kind==="stasis"){if(!r.bundle)return t;let i=r.bundle.formats;for(let[s,o]of r.bundle.sources)typeof o=="string"&&(qe.isResourceFormat(i?.get(s))||t.set(s,o))}else if(r.kind==="sourcemap"){if(!r.json)return t;let i=r.json.sources??[],s=r.json.sourcesContent??[];for(let o=0;o<i.length;o++)typeof s[o]=="string"&&t.set(i[o],s[o])}return e&&_s.set(e,t),t}function rh(r){let e=r?.bundle??r?.json;if(e&&xs.has(e))return xs.get(e);let t=new Map(Cr(r));if(r?.kind==="stasis"&&r.bundle){let i=r.bundle.formats;for(let[s,o]of r.bundle.sources){if(typeof o!="string")continue;let n=i?.get(s);n==="resource"?t.set(s,o):n==="resource:base64"&&t.set(s,{format:"base64",data:o})}}return e&&xs.set(e,t),t}var ih="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function sh(r){let e=r.endsWith("=");if(e?r.length%4!==0||r.at(-3)==="=":r.length%4===1)return null;let t=e?r.slice(0,r.endsWith("==")?-2:-1):r;if(/[^A-Za-z0-9+/]/u.test(t))return null;let i=t.length%4;return i>1&&ih.indexOf(t.at(-1))&(i===2?15:3)?null:Math.floor(t.length*3/4)}function oh(r){return typeof r=="string"?ws(r):r?.format==="base64"?sh(r.data):null}function zt(r){if(r?.fileSizes)return r.fileSizes;let e=r?.bundle??r?.json;if(e&&$s.has(e))return $s.get(e);let t=new Map,i=rh(r),s=r?.kind==="stasis"?r.bundle?.sources.keys():r?.json?.sources;for(let o of s??[])t.set(o,oh(i.get(o)));return e&&$s.set(e,t),t}function Nl(r){if(r?.kind!=="stasis"||!r.bundle?.modules)return null;let e=new Map;for(let[t,i]of r.bundle.modules)for(let s of Object.keys(i.files))e.set(t==="."?s:`${t}/${s}`,t);return e}var nh=4,Pl=nh;function Bl(r){return typeof r!="string"||r.length===0?0:(r.match(/\r\n|\r|\n/gu)?.length??0)+(/[\r\n]$/u.test(r)?0:1)}function Dl(r,e){if(![1,2,3,Pl].includes(r?.version)||r.integrity!==e||!["stasis","sourcemap"].includes(r.kind)||!Number.isSafeInteger(r.size)||r.size<0||!Array.isArray(r.files))throw new Error("Invalid bundle metadata");let t=r.version!==Pl,i=r.version===1,s=new Map,o=new Map,n=new Map;for(let d of r.files){if(!Array.isArray(d)||d.length!==4&&!(i&&d.length===3))throw new Error("Invalid bundle metadata file");let[u,p,h,f]=d;if(typeof u!="string"||o.has(u)||p!==null&&(!Number.isSafeInteger(p)||p<0)||h!==null&&(typeof h!="string"||!/^sha512-[A-Za-z0-9+/]{86}==$/u.test(h))||p===null&&h!==null||i&&p!==null&&h===null||f!=null&&(!Number.isSafeInteger(f)||f<0))throw new Error("Invalid bundle metadata file");o.set(u,p),h!==null&&s.set(u,h),f!=null&&n.set(u,f)}let a=new Set(r.unsized??[]);if(r.unsized!==void 0&&(i||!Array.isArray(r.unsized)||a.size!==r.unsized.length)||[...a].some(d=>typeof d!="string"||!o.has(d)||o.get(d)!==null))throw new Error("Invalid bundle metadata");let l={integrity:e,kind:r.kind,size:r.size,metadataOnly:!0,fileSizes:o,fileHashes:s,lineCounts:n,unsizedFiles:a,stale:t};if(r.kind==="stasis"){l.bundle=qe.parse(JSON.stringify(r.bundle));let d=l.bundle.sources;if(d.size!==o.size||[...d.keys()].some(p=>!o.has(p)))throw new Error("Invalid bundle metadata inventory");let u=l.bundle.formats;if(!i&&[...o].some(([p,h])=>s.has(p)!==(h!==null&&!qe.isResourceFormat(u.get(p)))))throw new Error("Invalid bundle metadata inventory");if([...a].some(p=>u.get(p)!=="resource:base64"))throw new Error("Invalid bundle metadata inventory")}else{if(!r.json||typeof r.json!="object"||![null,void 0].includes(r.namesCount)&&(!Number.isSafeInteger(r.namesCount)||r.namesCount<0))throw new Error("Invalid sourcemap metadata");if(!Array.isArray(r.json.sources)||r.json.sources.some(d=>!o.has(d))||!Array.isArray(r.sourceSizes)||r.sourceSizes.length!==r.json.sources.length||r.sourceSizes.some(d=>d!==null&&(!Number.isSafeInteger(d)||d<0))||[...o].some(([d,u])=>s.has(d)!==(u!==null))||a.size>0)throw new Error("Invalid sourcemap inventory");l.json=r.json,l.sourceSizes=r.sourceSizes,l.namesCount=r.namesCount}if(r.codeStats===void 0)l.codeStats=tl(n,o);else{let d=r.codeStats,u=p=>Number.isSafeInteger(p)&&p>=0;if(!d||![d.files,d.lines,d.bytes].every(u)||!Array.isArray(d.languages)||d.languages.some(p=>!p||typeof p.key!="string"||typeof p.label!="string"||![p.files,p.lines,p.bytes].every(u)))throw new Error("Invalid bundle code stats");l.codeStats=d}return l}function ks(r,{packageDir:e=null}={}){if(e){if(e!=="."){let t=e.match(/(?:^|\/)node_modules\/(@[^/]+\/[^/]+|[^/]+)$/u);return t&&t[1]!==".pnpm"?t[1]:e}}else{let t=/(?:^|\/)(?:node_modules|dependencies)\/(@[^/]+\/[^/]+|[^/]+)/gu,i;for(;(i=t.exec(r))!==null;)if(i[1]!==".pnpm")return i[1]}return"__own__"}function Ss(r,e){let t=new Map,i=r?.kind==="stasis"?r.bundle?.reason:null;if(!i||typeof i!="object"||Array.isArray(i))return t;let s=new Set(e??[...zt(r)].filter(([,o])=>o!=null).map(([o])=>o));for(let[o,n]of Object.entries(i).toSorted(([a],[l])=>a.localeCompare(l))){if(!o||!Array.isArray(n))continue;let a=new Set(n.filter(l=>typeof l=="string"&&s.has(l)));a.size>0&&t.set(o,a)}return[...t.values()].some(o=>o.size<s.size)||t.clear(),t}function jl(r,e){if(e.error)throw new Error(e.error);let t=Nl(e),i=e.kind==="stasis"?e.bundle?.formats:null,s=e.lineCounts??new Map([...Cr(e)].map(([a,l])=>[a,Bl(l)])),o=[...zt(e)].filter(([,a])=>a!=null).map(([a,l])=>({path:a,format:i?.get(a)??null,bytes:l,lines:s.get(a)??0,size:se(l),module:ks(a,{packageDir:t?.get(a)})})),n=[{id:"all",label:"All",filePaths:null},...[...Ss(e,o.map(a=>a.path))].map(([a,l])=>({id:`reason:${a}`,label:a,filePaths:[...l]}))];return{...r,files:o,reasons:n,size:se(e.size)}}function Ul(r){let e=new Map((r.repos??[]).map(i=>[i.repoId,{id:i.repoId,label:i.fullName}])),t=(r.bundles??[]).map(i=>{let s=i.repoId??"unattached";return e.has(s)||e.set(s,{id:s,label:s==="unattached"?"Unattached":i.repoFullName??String(s)}),{...i,repoId:s,repo:e.get(s).label,size:se(i.byteSize),files:null,reasons:[]}});return{repositories:[...e.values()],bundles:t,scans:[]}}async function Fl(r,e){let t=await Ii(r.id,{signal:e});e?.throwIfAborted();let i=Dl(t,r.integrity);return jl(r,i)}var Hl=new Set(["overview","graph","treemap","compare","advisories","issues","code","search","terminal"]);var ah=/^\d+$/u;function lh(r){for(let e=0;e<r.length;e++){let t=r.codePointAt(e);if(t<32||t===127)return!0}return!1}var ql=512;function ch(r){return typeof r=="string"&&r.length>0&&r.length<=ql&&!lh(r)}function Vl(r){return ch(r)&&!ah.test(r)}var Gl=Object.freeze({manage:"/manage","manage-bundles":"/manage/bundle","manage-scans":"/manage/scans","manage-reports":"/manage/report","manage-repos":"/manage/repositories","admin-users":"/manage/users","manage-teams":"/manage/team","manage-import":"/manage/import","manage-links":"/manage/links","manage-deduplication":"/manage/deduplication","manage-history":"/manage/history"});function dh(r){if(!Vl(r)||r==="."||r==="..")return null;try{return`/finding/${encodeURIComponent(r)}`}catch{return null}}function Wl(r){if(!r)return null;if(r.view==="home")return"/";if(r.view==="workspace-reports"||r.view==="workspace-bundles")return/^[A-Za-z0-9_-]+$/u.test(r.teamSlug??"")?`/team/${r.teamSlug}/${r.view.slice(10)}`:null;if(r.view==="bundles"){if(!/^[A-Za-z0-9_-]+$/u.test(r.bundleSlug??"")||r.teamSlug!=null&&!/^[A-Za-z0-9_-]+$/u.test(r.teamSlug))return null;let i=r.bundleTab??"overview";return Hl.has(i)?`${r.teamSlug?`/team/${r.teamSlug}`:"/manage"}/bundle/${r.bundleSlug}${i==="overview"?"":`/${i}`}`:null}if(Object.hasOwn(Gl,r.view)){let i=Gl[r.view];return r.view==="manage-deduplication"&&r.linkId?`${i}?report=${encodeURIComponent(r.linkId)}`:r.view==="manage-bundles"&&Number.isSafeInteger(r.createRepoId)&&r.createRepoId>0?`${i}?createRepo=${r.createRepoId}`:r.view==="manage-scans"&&r.scanMode==="link"?`${i}?mode=link`:r.view==="manage-scans"&&r.bundleId?`${i}?bundle=${encodeURIComponent(r.bundleId)}`:r.view==="manage-history"&&r.actor?`${i}?actor=${encodeURIComponent(r.actor)}`:i}if(!["findings","files"].includes(r.view)||!r.teamSlug||[r.teamSlug,r.reportSlug].some(i=>i!=null&&!/^[A-Za-z0-9_-]+$/u.test(i)))return null;let e=`/team/${encodeURIComponent(r.teamSlug)}`,t=r.reportSlug?`/report/${encodeURIComponent(r.reportSlug)}`:"";if(r.finding){let i=dh(r.finding.id);return r.view==="findings"&&i?`${e}${t}${i}`:null}return`${e}${t}${r.view==="files"?"/files":""}`}ve();function ph(r){let{data:e}=Nn(r);return e&&Kl(e)>0?e:null}function Kl(r){return(be(r)??[]).filter(e=>(Array.isArray(e)?e:[e]).some(t=>t&&typeof t=="object"&&ni(t,t.source??r.source))).length}function Zl(r,e){let t=(r.reports??[]).filter(n=>n.visible&&n.repoId!=null).flatMap(n=>{let a=ph(n.content??"");return a?[{id:n.id,filename:n.filename,repoIds:[n.repoId],repo:n.repoFullName,directory:n.repoDirectory,analyzer:n.analyzer,appFindings:Kl(a)}]:[]}),i=new Map((r.repos??[]).map(n=>[n.repoId,{id:n.repoId,label:n.fullName}]));for(let n of t)i.has(n.repoIds[0])||i.set(n.repoIds[0],{id:n.repoIds[0],label:n.repo??String(n.repoIds[0])});let s=e.results??[],o=new Set(s.map(n=>n.bundleId));return{merge:{bundles:(e.bundles??[]).filter(n=>o.has(n.id)).map(n=>({...n,size:se(n.byteSize)})),results:s},link:{repositories:[...i.values()].filter(n=>t.some(a=>a.repoIds.includes(n.id))),reports:t}}}S();Cs();B();function Yl(r){return r.map(e=>{let t=e.login||String(e.id),i=e.name?.trim()||`@${t}`,s=i===`@${t}`?"":`@${t}`,o=i.replace(/^@/u,"").split(/\s+/u).filter(Boolean).slice(0,2).map(n=>n[0]).join("").toUpperCase();return{value:e.id,label:s?`${i} ${s}`:i,displayLabel:i,secondary:s,initials:o,disabled:e.disabled,detail:e.detail}})}function Xl(r,e){let t=e.normalize("NFKC").toLocaleLowerCase().trim().split(/\s+/u).filter(Boolean),i=r.filter(o=>!o.reset),s=i.filter(o=>t.every(n=>o.label.normalize("NFKC").toLocaleLowerCase().includes(n))).toSorted((o,n)=>o.label.localeCompare(n.label,void 0,{sensitivity:"base",numeric:!0}));return{pinned:r.filter(o=>o.reset),sections:[{label:null,options:s}],facets:[],showFacets:!1,count:s.length,total:i.length}}var Rs=class extends F{static properties={users:{attribute:!1},resetLabel:{type:String,attribute:"reset-label"}};static styles=[F.styles,z`.avatar{position:relative;overflow:hidden}.avatar img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}`];constructor(){super(),this.users=[],this.resetLabel="",this.label="Choose user",this.placeholder="Choose user"}get searchLabel(){return"Search users"}get optionsLabel(){return"Users"}get noMatchesLabel(){return"No matching users"}get emptyLabel(){return"No users available"}get changeEvent(){return"user-change"}willUpdate(e){(e.has("users")||e.has("resetLabel"))&&(this.options=[...this.resetLabel?[{value:"",label:this.resetLabel,reset:!0}]:[],...Yl(this.users)])}choices(){return Xl(this.options,this._query)}optionIcon(e){return e.initials?c`<span class="avatar" aria-hidden="true">${e.initials}${Ee()?m:Rr(e.value,c`<img alt="" loading="lazy" decoding="async" src="${`/api/avatar/${encodeURIComponent(e.value)}`}" @error="${t=>{t.currentTarget.hidden=!0}}">`)}</span>`:m}};customElements.get("user-selector")||customElements.define("user-selector",Rs);S();B();var Ql=`:host{padding:0;margin-top:2rem;container-type:normal}.heading{display:flex;align-items:center;justify-content:space-between;gap:1rem}h2{margin:0;font-size:1.125rem}.intro{margin:.5rem 0 1rem}.alias-table{overflow-x:auto;padding-bottom:.5rem}table{width:100%;border-collapse:collapse;text-align:left}th,td{padding:.35rem .5rem;border-bottom:1px solid var(--border)}th{color:var(--muted);font-weight:500}td:not(.actions,.empty){overflow-wrap:anywhere}input{width:100%;min-width:7rem;padding:.3rem .45rem;border:1px solid var(--border);border-radius:.375rem;background:var(--bg);color:var(--text);font:inherit}.actions{white-space:nowrap;text-align:right}.actions .btn{min-height:1.75rem;padding:.2rem .55rem}.actions .btn+.btn{margin-left:.25rem}
|
|
266
|
+
`;var ls=["import","require","default"],Eu=[...ls,"node","node-addons","module-sync"],It=[{id:"node",label:"Node.js",conditions:["node"],automatic:Eu,icon:V`<path d="m8 1.5 5.5 3.2v6.6L8 14.5l-5.5-3.2V4.7Z"/><path d="M6 10V6l4 4V6"/>`},{id:"browser",label:"Browser",conditions:["browser","module"],automatic:ls,icon:V`<rect x="1.5" y="2.5" width="13" height="11" rx="1.5"/><path d="M1.5 6h13M4 4.3h.1m2 0h.1"/>`},{id:"metro",label:"Metro",conditions:["react-native"],automatic:ls,icon:V`<rect x="4" y="1.5" width="8" height="13" rx="2"/><path d="M6.5 3.5h3M7 12.5h2"/>`}],Xa=16-Math.max(...It.map(r=>r.conditions.length)),as=[{id:"ios",label:"iOS"},{id:"android",label:"Android"}],Au=new Intl.ListFormat("en",{type:"conjunction"});function Qa(){return{preset:"node",conditions:["node"],platforms:[]}}var cs=class extends A{static styles=[x(N),x(Ya)];static properties={showConditions:{attribute:!1},_preset:{state:!0},_manual:{state:!0},_platforms:{state:!0},_draft:{state:!0},_error:{state:!0},_manualOpen:{state:!0}};constructor(){super(),this.showConditions=!0,this._preset="node",this._manual=[],this._platforms=["ios","android"],this._draft="",this._error="",this._manualOpen=!1}get value(){return{preset:this._preset,conditions:this.conditions,platforms:this._preset==="metro"?[...this._platforms]:[]}}get presetConditions(){return It.find(e=>e.id===this._preset).conditions}get automaticConditions(){return It.find(e=>e.id===this._preset).automatic}get conditions(){return[...new Set([...this.presetConditions,...this._preset==="metro"?[]:this._manual])]}notifyChange(){this.dispatchEvent(new CustomEvent("conditions-change",{detail:this.value,bubbles:!0,composed:!0}))}selectPreset(e){It.find(i=>i.id===e)&&(this._preset=e,this._draft="",this._error="",this.notifyChange())}togglePlatform(e){if(!as.some(i=>i.id===e))return;let t=this._platforms.includes(e);t&&this._platforms.length===1||(this._platforms=as.map(i=>i.id).filter(i=>i===e?!t:this._platforms.includes(i)),this.notifyChange())}addConditions(){if(this._preset==="metro")return;let e=this._draft.trim().split(/[\s,]+/u).filter(Boolean);if(e.length===0)return;if(e.some(i=>this.automaticConditions.includes(i)&&!this.presetConditions.includes(i))){this._error=`${Au.format(this.automaticConditions)} are handled automatically.`;return}if(e.some(i=>i.length>64||i.startsWith(".")||/^\d+$/u.test(i))){this._error="Use condition names of up to 64 characters, without a leading dot or an all-numeric name.";return}let t=[...new Set([...this._manual,...e.filter(i=>!this.presetConditions.includes(i))])];if(t.length>Xa){this._error=`Use up to ${Xa} manual conditions.`;return}this._manual=t,this._draft="",this._error="",this.notifyChange()}removeCondition(e){this.presetConditions.includes(e)||(this._manual=this._manual.filter(t=>t!==e),this._error="",this.notifyChange())}render(){let e=this._preset!=="metro",t=this.automaticConditions.filter(i=>i!=="import"&&i!=="require");return c`<section aria-label="${this.showConditions?"Conditions":"Bundle actions"}"><div class="conditions-head" ?data-conditions-hidden="${!this.showConditions}"><h2 id="conditions-heading">Conditions</h2><div class="presets" role="group" aria-label="Condition preset">${It.map(i=>c`<button type="button" aria-pressed="${this._preset===i.id}" @click="${()=>this.selectPreset(i.id)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${i.icon}</svg>${i.label}</button>`)}</div>${this._preset==="metro"?c`<div class="platforms" role="group" aria-label="Metro platforms"><span>Platforms</span>${as.map(({id:i,label:s})=>c`<label><input type="checkbox" .checked="${this._platforms.includes(i)}" ?disabled="${this._platforms.includes(i)&&this._platforms.length===1}" @change="${()=>this.togglePlatform(i)}">${s}</label>`)}</div>`:m} <button type="button" class="manual-toggle" ?hidden="${!e}" aria-expanded="${this._manualOpen}" aria-controls="manual-conditions" @click="${()=>{this._manualOpen=!this._manualOpen}}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 4 4 4-4 4"/></svg>Manual conditions</button><slot name="actions"></slot></div><div id="manual-conditions" ?hidden="${!this.showConditions||!e||!this._manualOpen}"><form class="condition-editor" @submit="${i=>{i.preventDefault(),this.addConditions()}}"><ul aria-label="Export conditions">${this.conditions.map(i=>this.presetConditions.includes(i)?c`<li class="preset"><code>${i}</code></li>`:c`<li><code>${i}</code><button type="button" aria-label="${`Remove condition ${i}`}" @click="${()=>this.removeCondition(i)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="m4 4 8 8m0-8-8 8"/></svg></button></li>`)}</ul><div class="condition-input"><input type="text" aria-label="Add conditions" aria-describedby="conditions-help" aria-invalid="${!!this._error}" aria-errormessage="condition-error" placeholder="Add condition…" autocomplete="off" maxlength="1040" .value="${this._draft}" @input="${i=>{this._draft=i.target.value,this._error=""}}" @keydown="${i=>{i.key===" "&&!i.isComposing&&(i.preventDefault(),this.addConditions())}}" @blur="${()=>this.addConditions()}"></div></form><p id="conditions-help">Package export conditions. <code>import</code> / <code>require</code>${t.map((i,s)=>c`${s<t.length-1?", ":t.length>1?", and ":" and "}<code>${i}</code>`)} are automatic.</p>${this._error?c`<p id="condition-error" class="error" role="alert">${this._error}</p>`:m}</div></section>`}};customElements.define("bundle-conditions",cs);var el=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"><circle cx="8" cy="8" r="3"/><path d="M1 8h4m6 0h4"/></svg>`,Mu=100,Iu=[{kind:"branch",label:"Branch",icon:c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"><circle cx="4" cy="3" r="1.5"/><circle cx="4" cy="13" r="1.5"/><circle cx="12" cy="3" r="1.5"/><path d="M4 4.5v7m0-3h3a5 5 0 0 0 5-4"/></svg>`},{kind:"tag",label:"Tag",icon:c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round" aria-hidden="true"><path d="M2 2h5.5l6.5 6.5-5.5 5.5L2 7.5Z"/><circle cx="5" cy="5" r="1"/></svg>`},{kind:"commit",label:"Commit SHA",icon:el}];async function ds(r,e,t){let i=await $(`/api/admin/repositories/${r}?${new URLSearchParams(e)}`,{credentials:"same-origin",headers:{accept:"application/json"},signal:t});if(!i.ok){let s=await i.json().catch(()=>null);if(s?.error==="github-rate-limited"){let o=Number(i.headers.get("retry-after")),n=Math.ceil(o/60),a=Number.isFinite(o)&&o>0?` Try again in about ${n} ${n===1?"minute":"minutes"}.`:" Try again after the limit resets.";throw new Error(`GitHub\u2019s API rate limit has been reached.${a}`)}throw s?.error==="github-status-403"?new Error("GitHub denied this request. Check repository access and the GitHub App\u2019s read permissions."):s?.error==="github-unauthorized"?new Error("GitHub authentication has expired or was revoked. Sign in again and check the repository App installation."):s?.error==="github-unreachable"?new Error("Could not connect to GitHub. Try again shortly."):i.status===404?new Error("This repository, revision, or directory is unavailable."):i.status===403?new Error("Repository access is required to browse files."):new Error("Could not load repository files from GitHub. Try again.")}return i.json()}var ps=class extends A{static styles=[x(N),x(Wa)];static properties={installTooltips:{attribute:!1},createBundle:{attribute:!1},_building:{state:!0},_opening:{state:!0},_buildError:{state:!0},initialRepoId:{attribute:!1},_repos:{state:!0},_loadingRepos:{state:!0},_reposError:{state:!0},_repoId:{state:!0},_refs:{state:!0},_refKind:{state:!0},_refName:{state:!0},_path:{state:!0},_entries:{state:!0},_selected:{state:!0},_commit:{state:!0},_packageEntryPoints:{state:!0},_solidityEntryPoints:{state:!0},_soliditySuggestionsLimited:{state:!0},_loadingRefs:{state:!0},_loading:{state:!0},_error:{state:!0},_refsError:{state:!0},_limited:{state:!0},_revisionOpen:{state:!0},_revisionQuery:{state:!0},_activeRevision:{state:!0}};constructor(){super(),this._repos=[],this._loadingRepos=!0,this._reposError="",this.initialRepoId=null,this._building=!1,this._opening=!1,this._buildError="",this._repoId=null,this._refs={branches:[],tags:[]},this._refKind="branch",this._refName="",this._path="",this._entries=null,this._selected=new Set,this._dismissedSuggestions=new Set,this._bundleConditions=Qa(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._commit="",this._directories=new Map,this._loadingRefs=!1,this._loading=!1,this._error="",this._refsError="",this._limited=!1,this._revisionOpen=!1,this._revisionQuery="",this._activeRevision=-1,this._onViewport=()=>this.positionRevisionSuggestions()}connectedCallback(){super.connectedCallback(),globalThis.addEventListener("resize",this._onViewport),globalThis.addEventListener("scroll",this._onViewport,!0)}updated(e){e.has("installTooltips")&&this.installTooltips?.(this.renderRoot),this.positionRevisionSuggestions()}firstUpdated(){this.loadRepositories()}async loadRepositories(){this._reposRequest?.abort(),this.selectRepository(null),this._repos=[],this._reposError="",this._loadingRepos=!0;let e=new AbortController;this._reposRequest=e;try{let t=await ds("browsable",{},e.signal);if(e.signal.aborted)return;this._repos=t.repos,this._repos.some(i=>i.repoId===this.initialRepoId)&&this.selectRepository(this.initialRepoId)}catch{e.signal.aborted||(this._reposError="Could not load repositories. Try again.")}finally{e.signal.aborted||(this._loadingRepos=!1)}}disconnectedCallback(){this._buildRequest?.abort(),this._opening=!1,globalThis.removeEventListener("resize",this._onViewport),globalThis.removeEventListener("scroll",this._onViewport,!0),clearTimeout(this._browseTimer),this._reposRequest?.abort(),this._refsRequest?.abort(),this._request?.abort(),this._directories.clear(),this._dismissedSuggestions.clear(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,super.disconnectedCallback()}resetFiles(){this._buildError="",clearTimeout(this._browseTimer),this._request?.abort(),this._directories.clear(),this._loading=!1,this._entries=null,this._path="",this._commit="",this._selected=new Set,this._dismissedSuggestions.clear(),this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._error="",this._limited=!1}async selectRepository(e){if(this.closeRevisionSuggestions(),this._refsRequest?.abort(),this.resetFiles(),this._repoId=e,this._refs={branches:[],tags:[]},this._refsError="",this._refKind="branch",this._refName="",e==null){this._loadingRefs=!1;return}let t=new AbortController;this._refsRequest=t,this._loadingRefs=!0;try{let{defaultContents:i,...s}=await ds("refs",{repoId:e,withDefault:"true"},t.signal);if(t.signal.aborted)return;this._refs=s,this._refName=s.defaultBranch||s.branches[0]||"",i?this.useDirectory(i,""):this._refName&&this.loadDirectory("")}catch(i){t.signal.aborted||(this._refsError=i.message)}finally{t.signal.aborted||(this._loadingRefs=!1)}}changeRevision(e,t){this._refsRequest?.abort(),this._loadingRefs=!1,this.resetFiles(),this._refKind=e,this._refName=t}selectRevisionType(e){this._refKind!==e&&(this.closeRevisionSuggestions(),this.changeRevision(e,e==="branch"&&this._refs.defaultBranch||""),this._refName&&this.loadDirectory(""))}editRevision(e){this.changeRevision(this._refKind,e);let t=e.trim();if(!t)return;let i=this._refKind==="branch"?this._refs.branches:this._refs.tags;this._refKind!=="commit"&&(i.includes(t)||this._refKind==="branch"&&t===this._refs.defaultBranch)?this.loadDirectory(""):this._browseTimer=setTimeout(()=>{this.loadDirectory("")},350)}revisionSuggestions(){let e=this._refKind==="branch"?this._refs.branches:this._refKind==="tag"?this._refs.tags:[],t=this._refKind==="branch"&&this._refs.defaultBranch?[this._refs.defaultBranch,...e.filter(s=>s!==this._refs.defaultBranch)]:e,i=this._revisionQuery.trim().toLowerCase();return t.filter(s=>s.toLowerCase().includes(i))}showRevisionSuggestions(e=!0){this._refKind==="commit"||this._repoId==null||this._loadingRefs||(this._revisionQuery=e?"":this._refName,this._activeRevision=-1,this.renderRoot.querySelector(".revision-menu").showPopover())}closeRevisionSuggestions(){this.renderRoot?.querySelector(".revision-menu")?.hidePopover(),this._revisionOpen=!1,this._activeRevision=-1}pickRevision(e){this.editRevision(e),this.renderRoot.querySelector(".revision-name").focus({preventScroll:!0}),this.closeRevisionSuggestions()}positionRevisionSuggestions(){if(!this._revisionOpen)return;let e=this.renderRoot.querySelector(".revision-menu"),t=this.renderRoot.querySelector(".revision-name").getBoundingClientRect(),i=8,s=6,n=15*parseFloat(getComputedStyle(this).fontSize),a=Math.max(1,Math.min(3,Math.ceil(this.revisionSuggestions().length/8),Math.floor((window.innerWidth-2*i)/n))),l=Math.min(Math.max(t.width,a*n),window.innerWidth-2*i);e.style.width=`${l}px`,e.style.setProperty("--revision-columns",a),e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-l-i))}px`;let d=window.innerHeight-t.bottom-s-i,u=t.top-s-i,p=d<Math.min(e.scrollHeight,320)&&u>d;e.style.maxHeight=`${Math.max(0,Math.min(320,p?u:d))}px`,e.style.top=`${Math.max(i,p?t.top-e.offsetHeight-s:t.bottom+s)}px`,e.dataset.positioned=""}async revisionKeyDown(e){if(e.key==="Escape"||e.key==="Tab"){e.key==="Escape"&&this._revisionOpen&&(e.preventDefault(),e.stopPropagation()),this.closeRevisionSuggestions();return}if(e.key==="Enter"){let i=this.revisionSuggestions()[this._activeRevision];this._revisionOpen&&i!=null?(e.preventDefault(),this.pickRevision(i)):this.closeRevisionSuggestions();return}if(this._refKind==="commit"||!["ArrowDown","ArrowUp"].includes(e.key))return;e.preventDefault(),this._revisionOpen||this.showRevisionSuggestions();let t=this.revisionSuggestions().length;this._activeRevision=t===0?-1:e.key==="ArrowDown"?Math.min(this._activeRevision+1,t-1):this._activeRevision<=0?t-1:this._activeRevision-1,await this.updateComplete,this.renderRoot.querySelector("[data-active]")?.scrollIntoView({block:"nearest"})}async loadDirectory(e,t=!1){if(clearTimeout(this._browseTimer),this._repoId==null||!this._refName.trim())return;t&&this.resetFiles(),this._request?.abort();let i=new AbortController;this._request=i,this._path=e,this._entries=null,this._error="",this._limited=!1,this._packageEntryPoints=[],this._solidityEntryPoints=[],this._soliditySuggestionsLimited=!1,this._loading=!1;let s=this._refName.trim();if(this._refKind==="commit"&&!/^[a-f\d]{7,40}$/iu.test(s)){this._error="Enter a commit SHA with 7 to 40 hexadecimal characters.";return}let o=this._commit||(this._refKind==="commit"?s:`${this._refKind==="branch"?"heads":"tags"}/${s}`),n=JSON.stringify([this._repoId,this._commit,e]),a=this._commit&&this._directories.get(n);if(a){this._directories.delete(n),this._directories.set(n,a),this._entries=a.entries,this._limited=a.limited,this._packageEntryPoints=a.packageEntryPoints,this._solidityEntryPoints=a.solidityEntryPoints,this._soliditySuggestionsLimited=a.soliditySuggestionsLimited;return}this._loading=!0;try{let l=await ds("contents",{repoId:this._repoId,ref:o,path:e},i.signal);if(i.signal.aborted)return;this.useDirectory(l,e)}catch(l){i.signal.aborted||(this._directories.clear(),this._error=l.message)}finally{i.signal.aborted||(this._loading=!1)}}useDirectory(e,t){this._path=t,this._commit=e.commit,this._entries=e.entries.toSorted((s,o)=>+(o.type==="dir")-+(s.type==="dir")||s.name.localeCompare(o.name)),this._limited=e.limited,this._packageEntryPoints=e.packageEntryPoints??[],this._solidityEntryPoints=e.solidityEntryPoints??[],this._soliditySuggestionsLimited=e.soliditySuggestionsLimited??!1;let i=[...this._packageEntryPoints,...this._solidityEntryPoints].filter(s=>!this._dismissedSuggestions.has(s));if(this._selected=new Set([...this._selected,...i]),/^[a-f\d]{40}$/iu.test(e.commit)){let s=JSON.stringify([this._repoId,e.commit,t]);this._directories.set(s,{entries:this._entries,limited:this._limited,packageEntryPoints:this._packageEntryPoints,solidityEntryPoints:this._solidityEntryPoints,soliditySuggestionsLimited:this._soliditySuggestionsLimited}),this._directories.size>Mu&&this._directories.delete(this._directories.keys().next().value)}}toggleFile(e){let t=new Set(this._selected);t.has(e)?(t.delete(e),this._dismissedSuggestions.add(e)):(t.add(e),this._dismissedSuggestions.delete(e)),this._selected=t}clearFiles(){for(let e of this._selected)this._dismissedSuggestions.add(e);this._selected=new Set}hasScriptEntryPoints(){return[...this._selected].some(e=>/\.[cm]?[tj]sx?$/iu.test(e))}async buildBundle(){if(this._building||this._opening||!this.createBundle||!this._commit||this._selected.size===0)return;let e=new AbortController;this._buildRequest=e,this._building=!0,this._buildError="";try{let t=await this.createBundle({repoId:this._repoId,commit:this._commit,entries:[...this._selected],conditions:this._bundleConditions},e.signal);e.signal.aborted||(this._opening=!0,this.dispatchEvent(new CustomEvent("bundle-created",{detail:t,bubbles:!0,composed:!0})))}catch(t){e.signal.aborted||(this._buildError=t.message)}finally{this._building=!1}}render(){let e=this._building||this._opening,t=this._repos.find(a=>a.repoId===this._repoId),i=this._path.split("/").filter(Boolean),s=t&&this._commit?`https://github.com/${[...t.fullName.split("/"),"tree",this._commit,...i].map(encodeURIComponent).join("/")}`:null,o=this.revisionSuggestions(),n=this._refKind==="commit"?"Commit SHA":this._refKind==="tag"?"Tag":"Branch";return c`<p class="intro ui-hint">Choose a repository and revision, then select files to use as entry points.</p><div ?inert="${e}"><div class="source-fields"><div class="field"><span>Repository</span><repository-selector label="Repository" ?disabled="${this._loadingRepos}" .options="${this._repos.map(a=>({value:a.repoId,label:a.fullName}))}" .value="${this._repoId}" @repository-change="${a=>this.selectRepository(a.detail.value)}"></repository-selector></div><form class="revision" @focusout="${a=>{a.currentTarget.contains(a.relatedTarget)||this.closeRevisionSuggestions()}}" @submit="${a=>{a.preventDefault(),this.loadDirectory("",!0)}}"><div class="revision-switch" role="group" aria-label="Revision type">${Iu.map(({kind:a,label:l,icon:d})=>c`<button type="button" aria-label="${l}" data-tooltip="${l}" aria-pressed="${this._refKind===a}" ?disabled="${!t||this._loadingRefs}" @click="${()=>{this.selectRevisionType(a),this.renderRoot.querySelector(".revision-name").focus(),this.showRevisionSuggestions()}}">${d}</button>`)}</div><input class="revision-name" type="text" aria-label="${n}" role="${Se(this._refKind==="commit"?void 0:"combobox")}" aria-autocomplete="${Se(this._refKind==="commit"?void 0:"list")}" aria-expanded="${Se(this._refKind==="commit"?void 0:String(this._revisionOpen))}" aria-controls="${Se(this._refKind==="commit"?void 0:"bundle-revisions")}" aria-activedescendant="${Se(this._revisionOpen&&this._activeRevision>=0?`revision-${this._activeRevision}`:void 0)}" autocomplete="off" placeholder="${this._refKind==="commit"?"Commit SHA\u2026":`Choose or enter a ${this._refKind}\u2026`}" .value="${this._refName}" ?disabled="${!t||this._loadingRefs}" @focus="${()=>this.showRevisionSuggestions()}" @click="${()=>this.showRevisionSuggestions()}" @keydown="${this.revisionKeyDown}" @input="${a=>{this.editRevision(a.target.value),this.showRevisionSuggestions(!1)}}"> ${this._refKind==="commit"?m:c`<button type="button" class="revision-expand" aria-label="${`Show ${this._refKind} suggestions`}" aria-expanded="${this._revisionOpen}" ?disabled="${!t||this._loadingRefs}" @mousedown="${a=>a.preventDefault()}" @click="${()=>{this._revisionOpen?this.closeRevisionSuggestions():(this.renderRoot.querySelector(".revision-name").focus(),this.showRevisionSuggestions())}}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m4 6 4 4 4-4"/></svg></button>`}<div class="revision-menu" id="bundle-revisions" popover="auto" role="listbox" aria-label="${`${n} suggestions`}" @beforetoggle="${a=>{this._revisionOpen=a.newState==="open",delete a.target.dataset.positioned,this._revisionOpen||(this._activeRevision=-1)}}"><div class="revision-options">${o.map((a,l)=>c`<button type="button" role="option" id="${`revision-${l}`}" aria-selected="${a===this._refName}" ?data-active="${l===this._activeRevision}" tabindex="-1" @mousedown="${d=>d.preventDefault()}" @click="${()=>this.pickRevision(a)}"><span data-tooltip-truncated data-tooltip="${a}">${a}</span></button>`)}</div>${o.length>0?m:c`<p class="revision-empty">${this._revisionQuery?"No matching suggestions. Enter a revision name to browse.":`No ${this._refKind} suggestions available.`}</p>`}</div></form></div>${this._reposError?c`<p class="message" role="alert">${this._reposError} <button type="button" class="text-action" @click="${()=>this.loadRepositories()}">Retry</button></p>`:m} ${this._refsError?c`<p class="message" role="status">${this._refsError} <button type="button" class="text-action" @click="${()=>this.selectRepository(this._repoId)}">Retry</button></p>`:m}<section class="browser" aria-label="Repository files" aria-busy="${this._loadingRepos||this._loading||this._loadingRefs}"><div class="browser-head"><nav class="breadcrumbs" aria-label="Repository directory"><button type="button" ?disabled="${!this._commit}" aria-current="${Se(this._path?void 0:"location")}" @click="${()=>this.loadDirectory("")}">${t?.fullName??"Repository"}</button>${i.map((a,l)=>c`<span aria-hidden="true">/</span><button type="button" aria-current="${Se(l===i.length-1?"location":void 0)}" @click="${()=>this.loadDirectory(i.slice(0,l+1).join("/"))}">${a}</button>`)}</nav>${s?c`<a class="commit-link" href="${s}" target="_blank" rel="noopener noreferrer" data-tooltip="${this._commit}" aria-label="${`View directory at commit ${this._commit.slice(0,7)} on GitHub`}">${el}<code>${this._commit.slice(0,7)}</code></a>`:m}</div><div class="file-browser">${this._loadingRepos||this._loading||this._loadingRefs?c`<p class="empty" role="status">${this._loadingRepos?"Loading repositories\u2026":this._loadingRefs?"Loading revisions\u2026":"Loading files\u2026"}</p>`:this._error?c`<p class="empty error" role="alert">${this._error} <button type="button" class="text-action" @click="${()=>this.loadDirectory(this._path)}">Retry</button></p>`:this._entries==null?c`<p class="empty">${t?"Choose a revision to browse its files.":this._repos.length>0?"Select a repository to browse its files.":"No accessible repositories available."}</p>`:this._entries.length===0?c`<p class="empty">This directory is empty.</p>`:c`<div class="file-grid">${this._entries.map(a=>a.type==="dir"?c`<button type="button" class="file-tile directory" @click="${()=>this.loadDirectory(a.path)}">${Ga}<span data-tooltip-truncated data-tooltip="${a.path}">${a.name}</span><span class="arrow" aria-hidden="true">›</span></button>`:c`<label class="${`file-tile ${this._selected.has(a.path)?"selected":""} ${a.type==="file"?"":"unsupported"}`}" data-tooltip="${a.type==="file"?m:`${a.path} (${a.type})`}"><input type="checkbox" aria-label="${`Select ${a.path} as an entry point`}" .checked="${this._selected.has(a.path)}" ?disabled="${a.type!=="file"}" @change="${()=>this.toggleFile(a.path)}">${ns(a.name)}<span data-tooltip-truncated data-tooltip="${a.type==="file"?a.path:m}">${a.name}</span></label>`)}</div>`}</div>${this._limited?c`<p class="message">Showing GitHub’s first 1,000 entries in this directory.</p>`:m}</section>${Ka(this._packageEntryPoints,this._selected,a=>{this._selected=new Set([...this._selected,...a])})} ${Za(this._solidityEntryPoints,this._selected,a=>{this._selected=new Set([...this._selected,...a])},this._soliditySuggestionsLimited)}<section class="entry-points" aria-label="Selected entry points"><div class="selection"><div class="selection-head"><h2>Entry points <span aria-live="polite">${this._selected.size}</span></h2>${this._selected.size>0?c`<button type="button" class="btn clear-selection" @click="${this.clearFiles}">Clear all</button>`:m}</div>${this._selected.size>0?c`<ul>${[...this._selected].map(a=>c`<li>${ns(a)}<span data-tooltip-truncated data-tooltip="${a}">${a}</span><button type="button" aria-label="${`Remove ${a}`}" @click="${()=>this.toggleFile(a)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="m4 4 8 8m0-8-8 8"/></svg></button></li>`)}</ul>`:c`<p class="note">Select files above. You can choose entry points from multiple directories.</p>`}</div></section><bundle-conditions .showConditions="${this.hasScriptEntryPoints()}" @conditions-change="${a=>{this._bundleConditions=a.detail}}"><button type="button" slot="actions" class="btn primary" ?disabled="${e||!this.createBundle||!this._commit||this._selected.size===0||this._loading||this._loadingRefs}" @click="${this.buildBundle}">${this._opening?"Opening\u2026":this._building?"Creating\u2026":"Create a bundle"}</button></bundle-conditions></div>${e?c`<p class="message" role="status">${this._opening?"Opening bundle\u2026":"Building the selected entry points with Stasis\u2026"}</p>`:m} ${this._buildError?c`<p class="message error" role="alert">${this._buildError}</p>`:m}`}};customElements.define("managed-create-bundle",ps);var Lu=Object.freeze({javascript:"JavaScript",jsx:"JSX",typescript:"TypeScript",tsx:"TSX",json:"JSON",css:"CSS",markup:"HTML",yaml:"YAML",bash:"Shell",markdown:"Markdown",solidity:"Solidity",php:"PHP",rust:"Rust",ruby:"Ruby",java:"Java",cpp:"C++",c:"C",objectivec:"Objective-C",python:"Python",go:"Go",kotlin:"Kotlin",swift:"Swift",dart:"Dart",sql:"SQL",lua:"Lua",csharp:"C#",scala:"Scala",vue:"Vue",svelte:"Svelte"}),zu=Object.freeze({py:"python",pyw:"python",go:"go",kt:"kotlin",kts:"kotlin",swift:"swift",dart:"dart",sql:"sql",lua:"lua",cs:"csharp",scala:"scala",sc:"scala",vue:"vue",svelte:"svelte"});function Ou(r){let e=typeof r=="string"?r.slice(r.lastIndexOf("/")+1):"",t=e.lastIndexOf("."),i=t>0?e.slice(t+1).trim().toLowerCase():"",s=vr(r)??zu[i];return s?{key:s,label:Lu[s]??s}:i?{key:`extension:${i}`,label:`.${i}`}:{key:"other",label:"Other"}}function tl(r,e){let t=new Map,i=0,s=0;for(let[o,n]of r){let a=Ou(o),l=t.get(a.key)??{...a,files:0,lines:0,bytes:0};l.files++,l.lines+=n,l.bytes+=e.get(o)??0,t.set(a.key,l),s+=n,i+=e.get(o)??0}return{files:r.size,lines:s,bytes:i,languages:[...t.values()].toSorted((o,n)=>n.lines-o.lines||o.label.localeCompare(n.label))}}hs();var Tu=new Set(["module","commonjs","json","module-typescript","commonjs-typescript"]),Nu=new Set(["solidity","php","shell","rust"]),Pu=new Set(["java","kotlin","gradle","objc","objcpp","swift","c","cpp","c-header","cpp-header","ruby","python","cmake","podspec","podfile","podfile-lock","template","xml","env","fastlane","pbxproj"]),Bu=new Set(["resource","resource:base64"]),ol=new Set(["stat:file","stat:directory"]),Du=new Set([...Tu,...Nu,...Pu,...Bu,"patch","directory",...ol]),ms=r=>ol.has(r);var rl=r=>r==="directory"||r==="stat:directory"?"directory":"file";function ju(r,e,t){if(r===e)return r;let i=ms(r);if(i!==ms(e)&&rl(r)===rl(e))return i?e:r;throw new Error(`format conflict for '${t}' ('${e}' vs '${r}')`)}function Ue(r,e){return e===""?r:r==="."?e:`${r}/${e}`}var Uu=/^(?=[A-Za-z0-9-]{1,39}\/)[A-Za-z0-9](?:-?[A-Za-z0-9])*\/(?!\.\.?$)[\w.-]{1,100}$/u,Fu=/^(?!\.\.?(?:\/|$))[\w.~@+-]+(?:\/(?!\.\.?(?:\/|$))[\w.~@+-]+)*$/u,Hu=/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/u,fs={github:r=>typeof r=="string"&&Uu.test(r),directory:r=>typeof r=="string"&&r.length<=1024&&(r===""||Fu.test(r)),commit:r=>typeof r=="string"&&Hu.test(r)},nl=(r,e)=>r?.toLowerCase()===e?.toLowerCase();var _r=(r,e,t)=>{if(r===void 0)return;Fe(r)||_(!1,`${t} must be an object`);for(let s of Object.keys(r))Object.hasOwn(e,s)||_(!1,`unknown ${t} key '${s}'`);let i=Object.entries(e).map(([s,o])=>typeof o=="object"?[s,_r(r[s],o,`${t}.${s}`)]:(r[s]!==void 0&&!o(r[s])&&_(!1,`invalid ${t}.${s}: ${JSON.stringify(r[s])}`),[s,r[s]])).filter(([,s])=>s!==void 0);return i.length===0?void 0:Object.freeze(X(i))},xr=(r,e="bundle repo")=>_r(r,fs,e),qu=(r,e)=>e??(He(r)?"npm":void 0),al=(r,{ecosystem:e,repo:t},i)=>{if(t===void 0)return;qu(r,e)===void 0&&_(!1,`${i}: '${r}' is no dependency's bucket, and carries no repo`);let s=xr(t,`${i} module '${r}' repo`);return s?.github===void 0&&_(!1,`${i} module '${r}' repo has no github`),s},wr=({name:r,version:e,ecosystem:t,repo:i,files:s})=>({name:r,version:e,...t===void 0?{}:{ecosystem:t},...i===void 0?{}:{repo:i},files:s});function gs({name:r,version:e,ecosystem:t,repo:i,files:s},o,n){return _(t===void 0||typeof t=="string"),wr({name:r,version:e??void 0,ecosystem:t,repo:al(o,{ecosystem:t,repo:i},n),files:X(Object.entries(s))})}function ll(r,{scope:e="full"}={}){let t=new Set;for(let[i,{files:s}]of r)if(!(e!=="full"&&!He(i)))for(let o of Object.keys(s))t.add(Ue(i,o));return t}function Vu(r,{what:e,files:t,formats:i,scope:s}){if(r.includes("\\"))return"holds a '\\'";if(Lt(r))return"escapes the root";if(s!=="full"&&!He(r))return`is outside node_modules, which a '${s}'-scope ${e} does not record`;if(!t.has(r))return`names no file the ${e} records`;let o=i.get(r);return o==="directory"?"is a directory capture, not a file":ms(o)?`is a payload-free '${o}' record, not a file`:null}function cl(r,{what:e,files:t,formats:i,scope:s}){for(let o of r){let n=Vu(o,{what:e,files:t,formats:i,scope:s});_(n===null,`${e}: executable entry '${o}' ${n}`)}}function dl(r,{what:e,files:t,formats:i,scope:s="full"}){if(r===void 0)return new Set;let o=`${e}: executable`;_(Array.isArray(r),`${o} must be an array of file paths`);let n=new Set;for(let a of r)_(typeof a=="string"&&a!=="",`${o} entry must be a non-empty string`),_(!n.has(a),`${o} entry '${a}' is listed twice`),n.add(a);return cl(n,{what:e,files:t,formats:i,scope:s}),n}function pl(r,{what:e,modules:t,formats:i,scope:s}){if(r.size!==0)return cl(r,{what:e,files:ll(t,{scope:s}),formats:i,scope:s}),$r(r)}function _(r,e){if(!r)throw new Error(e)}function ul(r,e){let[t,i]=[r.split("/"),e.split("/")];for(;t.length>0&&t[0]===i[0];)t.shift(),i.shift();if(t.length===0&&i.length===0)return 0;if(t.length<2)return i.length<2&&t>i?1:-1;if(i.length<2)return 1;if(t[0]==="*")return-1;if(i[0]==="*"||t[0]==="node_modules")return 1;if(i[0]==="node_modules")return-1;let[s,o]=[t,i].map(n=>n.join(String.fromCodePoint(0)));if(s<o)return-1;if(s>o)return 1;throw new Error("Unreachable")}var yr=(r,e)=>ul(r[0],e[0]),Fe=r=>r&&[null,Object.prototype].includes(Object.getPrototypeOf(r)),X=r=>Object.setPrototypeOf(Object.fromEntries(r),null),$r=r=>[...r].toSorted(ul),bs=(r,{sorted:e=!0}={})=>{let t=e?[...r].toSorted(yr):[...r];return X(t.map(([i,s])=>[i,s instanceof Map?bs(s,{sorted:e}):s]))},il=(r,e)=>r.get(e)??r.set(e,new Map).get(e),hl=r=>new Map(Object.entries(r).map(([e,t])=>[e,Fe(t)?hl(t):t]));function Lt(r){if(r.startsWith("/"))return!0;if(!r.includes(".."))return!1;let e=0;for(let t of r.split("/"))if(!(t==="."||t==="")){if(t!=="..")e++;else if(--e<0)return!0}return!1}var ml=r=>r.includes("\\")||Lt(r),le=(r,e)=>_(!ml(r),`${e}: path '${r}' escapes the root or holds a '\\'`),fl=(r,e)=>_(typeof r=="string"&&r!==""&&!ml(r),`${e}: invalid entry ${JSON.stringify(r)}`);function gl(r,e){_(Array.isArray(r),`${e}: entries must be an array of file paths`);let t=new Set;for(let i of r)fl(i,e),_(!t.has(i),`${e}: entry '${i}' is listed twice`),t.add(i);return t}function bl(r,e){for(let t of r)fl(t,e);return $r(r)}function vl(r,e){le(r,"formats"),_(Du.has(e),`unknown format '${e}' for ${r}`)}function yl(r){_(Fe(r));let e=new Map;for(let[t,i]of Object.entries(r)){vl(t,i);let s=t===""?".":t;_(!e.has(s),`duplicate format key '${s}'`),e.set(s,i)}return e}function wl(r){for(let[e,t]of r)vl(e,t);return bs(r)}function _l(r){for(let[,e]of r){_(e instanceof Map);for(let[t,i]of e){le(t,"imports"),_(i instanceof Map);for(let[,s]of i){if(typeof s=="string"){le(s,"imports");continue}_(s instanceof Map&&s.size>0,"import target must be a file or a non-empty {platform: file} map");for(let[o,n]of s)_(typeof o=="string"&&o.length>0&&!o.includes("/"),`invalid platform key '${o}'`),_(typeof n=="string"),le(n,"imports")}}}}function xl(r){_(Fe(r));let e=hl(r);return _l(e),e}function $l(r){return _l(r),bs(r)}function kl(r,{skipEmpty:e=!1,repo:t=!0,what:i}={}){let s={modules:[],sources:[]};for(let[o,n]of r){if(e&&Object.keys(n.files).length===0)continue;let a=He(o);a&&_(n.name&&n.version&&n.files);let l=X(Object.entries(n.files).toSorted(yr));s[a?"modules":"sources"].push([o,wr({...n,repo:t?al(o,n,i):void 0,files:l})])}return{modules:X(s.modules.toSorted(yr)),sources:X(s.sources.toSorted(yr))}}function Gu(r,e){let t=r instanceof Map;if(t!==e instanceof Map)return!1;if(!t)return r===e;if(r.size!==e.size)return!1;for(let[i,s]of r)if(e.get(i)!==s)return!1;return!0}var sl=r=>r instanceof Map?`{${[...r].map(([e,t])=>`${e}: ${t}`).join(", ")}}`:r;function Sl(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=il(i,n);for(let[d,u]of a){let p=il(l,d);for(let[h,f]of u)p.has(h)?_(Gu(p.get(h),f),`${t}: import '${h}' from '${d}' resolves differently ('${sl(p.get(h))}' vs '${sl(f)}')`):p.set(h,f instanceof Map?new Map(f):f)}}};return s(r),s(e),i}function Cl(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=i.get(n);if(l===void 0){i.set(n,a);continue}try{i.set(n,ju(a,l,n))}catch(d){throw new Error(`${t}: ${d.message}`,{cause:d})}}};return s(r),s(e),i}function Rl(r,e,t,i){if(r.size===0)return new Set(e);let s=ll(t,{scope:i}),o=new Set(e);for(let n of r)s.has(n)||o.add(n);return o}var Wu=/(?:^|\/)\.{0,2}(?:\/|$)/u;function kr(r,e,t){let i=Ue(r,e);return(i!=="."||e!=="")&&Wu.test(i)&&_(!1,`${t}: non-canonical file key ${JSON.stringify(i)}`),i.includes("\\")&&_(!1,`${t}: file key '${i}' holds a '\\', which no path may`),i}function Sr(r,e,t){let i=new Map;for(let[s,{files:o}]of r){typeof s!="string"&&_(!1,`${e}: bucket dir ${String(s)} is not a string`),le(s,e);for(let n of Object.keys(o)){let a=kr(s,n,e),l=i.get(a);l!==void 0&&t(a,l,s),i.set(a,s)}}return i}var El=(r,e)=>t=>_(!1,`duplicate file key '${t}' across ${r} buckets -- module bucketing changed between writes (a workspace package without a version now owns its own bucket); regenerate the ${e}`);function Al(r,e,t){let i=new Map,s=o=>{for(let[n,a]of o){let l=i.get(n);if(l===void 0){i.set(n,wr({...a,files:Object.assign(Object.create(null),a.files)}));continue}_(l.name===a.name,`${t}: module '${n}' name mismatch ('${l.name}' vs '${a.name}')`),_(l.version===a.version,`${t}: module '${n}' version mismatch ('${l.version}' vs '${a.version}')`+(l.version==null==(a.version==null)?"":" -- an artifact from an older stasis may record a placeholder version for a workspace package without one; regenerate it (bundle=replace / lock=replace)")),_(l.ecosystem===a.ecosystem,`${t}: module '${n}' ecosystem mismatch ('${l.ecosystem??"(none)"}' vs '${a.ecosystem??"(none)"}')`),l.repo===void 0&&a.repo!==void 0&&i.set(n,wr({...l,repo:a.repo}));for(let[d,u]of Object.entries(a.files))Object.hasOwn(l.files,d)?_(l.files[d]===u,`${t}: content mismatch for '${Ue(n,d)}'`):l.files[d]=u}};return s(r),s(e),Sr(i,t,(o,n,a)=>_(!1,`${t}: file '${o}' is bucketed under both '${n}' and '${a}' -- module bucketing changed between the artifacts (a workspace package without a version now owns its own bucket); regenerate the artifact (bundle=replace / lock=replace)`)),i}function He(r){return r.split("/").includes("node_modules")}function Ku(r){let e="node_modules/",t=r.length;for(;(t=r.lastIndexOf(e,t-1))!==-1;)if(t===0||r[t-1]==="/")return t;return-1}function Ml(r){let e="node_modules/",t=Ku(r);if(t===-1)return null;let i=t+e.length,s=r.slice(i).split("/"),o=s[0].startsWith("@")?2:1;if(s.length<=o||s.slice(0,o).some(a=>!a))return null;let n=s.slice(0,o).join("/");return{dir:r.slice(0,i)+n,rel:s.slice(o).join("/"),name:n}}var Ce=1,Il=0,Ll=El("bundle","artifact (bundle=replace)"),zl=r=>Ml(r)??{dir:".",rel:r==="."?"":r,name:null};function Zu(){throw new Error("bundle: file contents are not retained by this contents-free Bundle")}var Ju=(r,{files:e,...t})=>{let i=Object.create(null);for(let[s,o]of Object.entries(e))typeof o!="symbol"&&_(!1,`bundle: file '${Ue(r,s)}' is not a placeholder`),Object.defineProperty(i,s,{get:Zu,enumerable:!0});return{...t,files:Object.freeze(i)}},vs=(r,e)=>{if(r===void 0&&e===void 0)return;let t=new Map;for(let i of[r,e])for(let[s,o]of Object.entries(i??{})){if(!Array.isArray(o))continue;let n=t.get(s);n===void 0&&t.set(s,n=new Set);for(let a of o)n.add(a)}return X([...t.keys()].toSorted().map(i=>[i,$r(t.get(i))]))};var Yu=(r,e)=>{if(r?.github===void 0||!nl(r.github,e?.github))return;let t=Object.keys(fs).filter(i=>r[i]!==void 0&&(i==="github"||r[i]===e[i]));return X(t.map(i=>[i,r[i]]))},Xu=r=>{if(!Fe(r)||r.root!==!0||Object.hasOwn(r,"directory"))return r;let{root:e,...t}=r;return t},Ol=r=>typeof r=="string"&&/^[\w.+@/~'!()*-]+$/u.test(r),ys={name:Ol,version:Ol},Tl={npm:ys,composer:ys,cargo:ys},Qu=(r,e)=>X(Object.keys(Tl).map(t=>{let[i,s]=[r?.[t],e?.[t]];return[t,i?.name!==void 0&&i.name===s?.name?X(Object.entries(i).filter(([o,n])=>n===s[o])):void 0]})),qe=class r{static VERSION=Ce;version=Ce;config;entries;modules;formats;imports;executable;reason;#e;get repo(){return this.#e}set repo(e){this.#e=xr(e)}#t;get package(){return this.#t}set package(e){this.#t=_r(e,Tl,"bundle package")}constructor({config:e={scope:"full"},entries:t,modules:i,formats:s,imports:o,executable:n,reason:a,repo:l,package:d,version:u=Ce}={}){_([Il,Ce].includes(u)),_(["node_modules","full"].includes(e.scope)),this.version=u,this.config=e,this.entries=t??new Set,this.modules=i??new Map,this.formats=s??new Map,this.imports=o??new Map,this.executable=n??new Set,this.reason=a,this.repo=xr(l),this.package=d}get sources(){let e=new Map;for(let[t,{files:i}]of this.modules)for(let[s,o]of Object.entries(i))e.set(Ue(t,s),o);return e}static isResourceFormat(e){return e==="resource"||e==="resource:base64"||e==="directory"}get hasCode(){for(let[e,{files:t}]of this.modules)for(let i of Object.keys(t))if(!r.isResourceFormat(this.formats.get(Ue(e,i))))return!0;return!1}static parse(e){return r.fromJSON(JSON.parse(e))}static fileKeyAt(e){let[t,i,s,o]=e;if(typeof i=="string"){if(e.length===2&&t==="sources"){let n=zl(i);return kr(n.dir,n.rel,"bundle")}if(e.length===4&&(t==="sources"||t==="modules")&&s==="files"&&typeof o=="string")return kr(i,o,"bundle")}}static fromJSON(e,{contents:t=!0}={}){_(e.version===Ce||e.version===Il),_(["node_modules","full"].includes(e.config?.scope));let i=yl(e.formats),s=new Map,o=new Set;if(e.version===Ce){let l=e.config.scope==="full";if(e.modules!==void 0){_(typeof e.modules=="object"&&e.modules!==null);for(let[d,u]of Object.entries(e.modules))_(He(d)),le(d,"bundle"),_(u?.name&&u.version&&u.files),s.set(d,gs(u,d,"bundle"))}if(l){_(e.sources&&typeof e.sources=="object");for(let[d,u]of Object.entries(e.sources))_(!He(d)),le(d,"bundle"),_(u?.name&&u.files),s.set(d,gs(u,d,"bundle"));e.entries!==void 0&&(o=gl(e.entries,"bundle"))}else _(e.entries===void 0),_(e.sources===void 0)}else{_(e.sources);for(let[l,d]of Object.entries(e.sources)){le(l,"bundle");let{dir:u,rel:p,name:h}=zl(l);_(!Lt(u)&&!Lt(p)),s.has(u)||s.set(u,{name:h,version:null,files:Object.create(null)});let{files:f}=s.get(u);_(!Object.hasOwn(f,p),"bundle: duplicate file key '.' (v0 '' and '.')"),f[p]=d}}let n=Sr(s,"bundle",Ll),a=xl(e.imports);if(!t)for(let[l,d]of s)s.set(l,Ju(l,d));return new r({version:e.version,config:e.config,entries:o,modules:s,formats:i,imports:a,executable:e.version===Ce?dl(e.executable,{what:"bundle",files:n,formats:i,scope:e.config.scope}):new Set,reason:Fe(e.reason)?e.reason:void 0,repo:Xu(e.repo),package:e.package})}serialize(){Sr(this.modules,"bundle",Ll);let{modules:e,sources:t}=kl(this.modules,{skipEmpty:!0,what:"bundle"}),i=this.config.scope==="full",s={version:Ce,config:this.config};this.repo!==void 0&&(s.repo=this.repo),this.package!==void 0&&(s.package=this.package),i&&(s.entries=bl(this.entries,"bundle")),s.formats=wl(this.formats),s.imports=$l(this.imports);let o=pl(this.executable,{what:"bundle",modules:this.modules,formats:this.formats,scope:this.config.scope});return o!==void 0&&(s.executable=o),this.reason!==void 0&&(s.reason=vs(this.reason,void 0)),i&&(s.sources=t),s.modules=e,JSON.stringify(s,void 0,2)}withReason(e){let{version:t,config:i,entries:s,modules:o,formats:n,imports:a,executable:l,repo:d,package:u}=this,p=vs(this.reason,{[e]:[...this.sources.keys()]});return new r({version:t,config:i,entries:s,modules:o,formats:n,imports:a,executable:l,reason:p,repo:d,package:u})}merge(e){return _(this.config.scope===e.config.scope,`bundle merge: scope mismatch ('${this.config.scope}' vs '${e.config.scope}')`),new r({config:{scope:this.config.scope},entries:new Set([...this.entries,...e.entries]),modules:Al(this.modules,e.modules,"bundle merge"),formats:Cl(this.formats,e.formats,"bundle merge"),imports:Sl(this.imports,e.imports,"bundle merge"),executable:Rl(this.executable,e.executable,e.modules,this.config.scope),reason:vs(this.reason,e.reason),repo:Yu(this.repo,e.repo),package:Qu(this.package,e.package)})}};var eh=new TextEncoder,H1=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});var th=2;function ws(r){if(typeof r!="string")throw new TypeError(`utf8ByteLength expects a string, got ${typeof r}`);if(/[\u0100-\uFFFF]/.test(r))return eh.encode(r).byteLength;let e=/[\u0080-\u00FF]/gu,t=r.length;for(;e.test(r);){let i=e.lastIndex-1;for(let s=0;i<r.length&&s<th;i++)r.codePointAt(i)>127?(t++,s=0):s++;e.lastIndex=i}return t}var _s=new WeakMap,xs=new WeakMap,$s=new WeakMap;function Cr(r){if(r?.metadataOnly)return new Map;let e=r?.bundle??r?.json;if(e&&_s.has(e))return _s.get(e);let t=new Map;if(!r)return t;if(r.kind==="stasis"){if(!r.bundle)return t;let i=r.bundle.formats;for(let[s,o]of r.bundle.sources)typeof o=="string"&&(qe.isResourceFormat(i?.get(s))||t.set(s,o))}else if(r.kind==="sourcemap"){if(!r.json)return t;let i=r.json.sources??[],s=r.json.sourcesContent??[];for(let o=0;o<i.length;o++)typeof s[o]=="string"&&t.set(i[o],s[o])}return e&&_s.set(e,t),t}function rh(r){let e=r?.bundle??r?.json;if(e&&xs.has(e))return xs.get(e);let t=new Map(Cr(r));if(r?.kind==="stasis"&&r.bundle){let i=r.bundle.formats;for(let[s,o]of r.bundle.sources){if(typeof o!="string")continue;let n=i?.get(s);n==="resource"?t.set(s,o):n==="resource:base64"&&t.set(s,{format:"base64",data:o})}}return e&&xs.set(e,t),t}var ih="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function sh(r){let e=r.endsWith("=");if(e?r.length%4!==0||r.at(-3)==="=":r.length%4===1)return null;let t=e?r.slice(0,r.endsWith("==")?-2:-1):r;if(/[^A-Za-z0-9+/]/u.test(t))return null;let i=t.length%4;return i>1&&ih.indexOf(t.at(-1))&(i===2?15:3)?null:Math.floor(t.length*3/4)}function oh(r){return typeof r=="string"?ws(r):r?.format==="base64"?sh(r.data):null}function zt(r){if(r?.fileSizes)return r.fileSizes;let e=r?.bundle??r?.json;if(e&&$s.has(e))return $s.get(e);let t=new Map,i=rh(r),s=r?.kind==="stasis"?r.bundle?.sources.keys():r?.json?.sources;for(let o of s??[])t.set(o,oh(i.get(o)));return e&&$s.set(e,t),t}function Nl(r){if(r?.kind!=="stasis"||!r.bundle?.modules)return null;let e=new Map;for(let[t,i]of r.bundle.modules)for(let s of Object.keys(i.files))e.set(t==="."?s:`${t}/${s}`,t);return e}var nh=4,Pl=nh;function Bl(r){return typeof r!="string"||r.length===0?0:(r.match(/\r\n|\r|\n/gu)?.length??0)+(/[\r\n]$/u.test(r)?0:1)}function Dl(r,e){if(![1,2,3,Pl].includes(r?.version)||r.integrity!==e||!["stasis","sourcemap"].includes(r.kind)||!Number.isSafeInteger(r.size)||r.size<0||!Array.isArray(r.files))throw new Error("Invalid bundle metadata");let t=r.version!==Pl,i=r.version===1,s=new Map,o=new Map,n=new Map;for(let d of r.files){if(!Array.isArray(d)||d.length!==4&&!(i&&d.length===3))throw new Error("Invalid bundle metadata file");let[u,p,h,f]=d;if(typeof u!="string"||o.has(u)||p!==null&&(!Number.isSafeInteger(p)||p<0)||h!==null&&(typeof h!="string"||!/^sha512-[A-Za-z0-9+/]{86}==$/u.test(h))||p===null&&h!==null||i&&p!==null&&h===null||f!=null&&(!Number.isSafeInteger(f)||f<0))throw new Error("Invalid bundle metadata file");o.set(u,p),h!==null&&s.set(u,h),f!=null&&n.set(u,f)}let a=new Set(r.unsized??[]);if(r.unsized!==void 0&&(i||!Array.isArray(r.unsized)||a.size!==r.unsized.length)||[...a].some(d=>typeof d!="string"||!o.has(d)||o.get(d)!==null))throw new Error("Invalid bundle metadata");let l={integrity:e,kind:r.kind,size:r.size,metadataOnly:!0,fileSizes:o,fileHashes:s,lineCounts:n,unsizedFiles:a,stale:t};if(r.kind==="stasis"){l.bundle=qe.parse(JSON.stringify(r.bundle));let d=l.bundle.sources;if(d.size!==o.size||[...d.keys()].some(p=>!o.has(p)))throw new Error("Invalid bundle metadata inventory");let u=l.bundle.formats;if(!i&&[...o].some(([p,h])=>s.has(p)!==(h!==null&&!qe.isResourceFormat(u.get(p)))))throw new Error("Invalid bundle metadata inventory");if([...a].some(p=>u.get(p)!=="resource:base64"))throw new Error("Invalid bundle metadata inventory")}else{if(!r.json||typeof r.json!="object"||![null,void 0].includes(r.namesCount)&&(!Number.isSafeInteger(r.namesCount)||r.namesCount<0))throw new Error("Invalid sourcemap metadata");if(!Array.isArray(r.json.sources)||r.json.sources.some(d=>!o.has(d))||!Array.isArray(r.sourceSizes)||r.sourceSizes.length!==r.json.sources.length||r.sourceSizes.some(d=>d!==null&&(!Number.isSafeInteger(d)||d<0))||[...o].some(([d,u])=>s.has(d)!==(u!==null))||a.size>0)throw new Error("Invalid sourcemap inventory");l.json=r.json,l.sourceSizes=r.sourceSizes,l.namesCount=r.namesCount}if(r.codeStats===void 0)l.codeStats=tl(n,o);else{let d=r.codeStats,u=p=>Number.isSafeInteger(p)&&p>=0;if(!d||![d.files,d.lines,d.bytes].every(u)||!Array.isArray(d.languages)||d.languages.some(p=>!p||typeof p.key!="string"||typeof p.label!="string"||![p.files,p.lines,p.bytes].every(u)))throw new Error("Invalid bundle code stats");l.codeStats=d}return l}function ks(r,{packageDir:e=null}={}){if(e){if(e!=="."){let t=e.match(/(?:^|\/)node_modules\/(@[^/]+\/[^/]+|[^/]+)$/u);return t&&t[1]!==".pnpm"?t[1]:e}}else{let t=/(?:^|\/)(?:node_modules|dependencies)\/(@[^/]+\/[^/]+|[^/]+)/gu,i;for(;(i=t.exec(r))!==null;)if(i[1]!==".pnpm")return i[1]}return"__own__"}function Ss(r,e){let t=new Map,i=r?.kind==="stasis"?r.bundle?.reason:null;if(!i||typeof i!="object"||Array.isArray(i))return t;let s=new Set(e??[...zt(r)].filter(([,o])=>o!=null).map(([o])=>o));for(let[o,n]of Object.entries(i).toSorted(([a],[l])=>a.localeCompare(l))){if(!o||!Array.isArray(n))continue;let a=new Set(n.filter(l=>typeof l=="string"&&s.has(l)));a.size>0&&t.set(o,a)}return[...t.values()].some(o=>o.size<s.size)||t.clear(),t}function jl(r,e){if(e.error)throw new Error(e.error);let t=Nl(e),i=e.kind==="stasis"?e.bundle?.formats:null,s=e.lineCounts??new Map([...Cr(e)].map(([a,l])=>[a,Bl(l)])),o=[...zt(e)].filter(([,a])=>a!=null).map(([a,l])=>({path:a,format:i?.get(a)??null,bytes:l,lines:s.get(a)??0,size:se(l),module:ks(a,{packageDir:t?.get(a)})})),n=[{id:"all",label:"All",filePaths:null},...[...Ss(e,o.map(a=>a.path))].map(([a,l])=>({id:`reason:${a}`,label:a,filePaths:[...l]}))];return{...r,files:o,reasons:n,size:se(e.size)}}function Ul(r){let e=new Map((r.repos??[]).map(i=>[i.repoId,{id:i.repoId,label:i.fullName}])),t=(r.bundles??[]).map(i=>{let s=i.repoId??"unattached";return e.has(s)||e.set(s,{id:s,label:s==="unattached"?"Unattached":i.repoFullName??String(s)}),{...i,repoId:s,repo:e.get(s).label,size:se(i.byteSize),files:null,reasons:[]}});return{repositories:[...e.values()],bundles:t,scans:[]}}async function Fl(r,e){let t=await Ii(r.id,{signal:e});e?.throwIfAborted();let i=Dl(t,r.integrity);return jl(r,i)}var Hl=new Set(["overview","graph","treemap","compare","advisories","issues","code","search","terminal"]);var ah=/^\d+$/u;function lh(r){for(let e=0;e<r.length;e++){let t=r.codePointAt(e);if(t<32||t===127)return!0}return!1}var ql=512;function ch(r){return typeof r=="string"&&r.length>0&&r.length<=ql&&!lh(r)}function Vl(r){return ch(r)&&!ah.test(r)}var Gl=Object.freeze({manage:"/manage","manage-bundles":"/manage/bundle","manage-scans":"/manage/scans","manage-reports":"/manage/report","manage-repos":"/manage/repositories","admin-users":"/manage/users","manage-teams":"/manage/team","manage-import":"/manage/import","manage-links":"/manage/links","manage-deduplication":"/manage/deduplication","manage-history":"/manage/history"});function dh(r){if(!Vl(r)||r==="."||r==="..")return null;try{return`/finding/${encodeURIComponent(r)}`}catch{return null}}function Wl(r){if(!r)return null;if(r.view==="home")return"/";if(r.view==="workspace-reports"||r.view==="workspace-bundles")return/^[A-Za-z0-9_-]+$/u.test(r.teamSlug??"")?`/team/${r.teamSlug}/${r.view.slice(10)}`:null;if(r.view==="bundles"){if(!/^[A-Za-z0-9_-]+$/u.test(r.bundleSlug??"")||r.teamSlug!=null&&!/^[A-Za-z0-9_-]+$/u.test(r.teamSlug))return null;let i=r.bundleTab??"overview";return Hl.has(i)?`${r.teamSlug?`/team/${r.teamSlug}`:"/manage"}/bundle/${r.bundleSlug}${i==="overview"?"":`/${i}`}`:null}if(Object.hasOwn(Gl,r.view)){let i=Gl[r.view];return r.view==="manage-deduplication"&&r.linkId?`${i}?report=${encodeURIComponent(r.linkId)}`:r.view==="manage-bundles"&&Number.isSafeInteger(r.createRepoId)&&r.createRepoId>0?`${i}?createRepo=${r.createRepoId}`:r.view==="manage-scans"&&r.scanMode==="link"?`${i}?mode=link`:r.view==="manage-scans"&&r.bundleId?`${i}?bundle=${encodeURIComponent(r.bundleId)}`:r.view==="manage-history"&&r.actor?`${i}?actor=${encodeURIComponent(r.actor)}`:i}if(!["findings","files"].includes(r.view)||!r.teamSlug||[r.teamSlug,r.reportSlug].some(i=>i!=null&&!/^[A-Za-z0-9_-]+$/u.test(i)))return null;let e=`/team/${encodeURIComponent(r.teamSlug)}`,t=r.reportSlug?`/report/${encodeURIComponent(r.reportSlug)}`:"";if(r.finding){let i=dh(r.finding.id);return r.view==="findings"&&i?`${e}${t}${i}`:null}return`${e}${t}${r.view==="files"?"/files":""}`}ve();function ph(r){let{data:e}=Nn(r);return e&&Kl(e)>0?e:null}function Kl(r){return(be(r)??[]).filter(e=>(Array.isArray(e)?e:[e]).some(t=>t&&typeof t=="object"&&ni(t,t.source??r.source))).length}function Zl(r,e){let t=(r.reports??[]).filter(n=>n.visible&&n.repoId!=null).flatMap(n=>{let a=ph(n.content??"");return a?[{id:n.id,filename:n.filename,repoIds:[n.repoId],repo:n.repoFullName,directory:n.repoDirectory,analyzer:n.analyzer,appFindings:Kl(a)}]:[]}),i=new Map((r.repos??[]).map(n=>[n.repoId,{id:n.repoId,label:n.fullName}]));for(let n of t)i.has(n.repoIds[0])||i.set(n.repoIds[0],{id:n.repoIds[0],label:n.repo??String(n.repoIds[0])});let s=e.results??[],o=new Set(s.map(n=>n.bundleId));return{merge:{bundles:(e.bundles??[]).filter(n=>o.has(n.id)).map(n=>({...n,size:se(n.byteSize)})),results:s},link:{repositories:[...i.values()].filter(n=>t.some(a=>a.repoIds.includes(n.id))),reports:t}}}S();Cs();B();function Yl(r){return r.map(e=>{let t=e.login||String(e.id),i=e.name?.trim()||`@${t}`,s=i===`@${t}`?"":`@${t}`,o=i.replace(/^@/u,"").split(/\s+/u).filter(Boolean).slice(0,2).map(n=>n[0]).join("").toUpperCase();return{value:e.id,label:s?`${i} ${s}`:i,displayLabel:i,secondary:s,initials:o,disabled:e.disabled,detail:e.detail}})}function Xl(r,e){let t=e.normalize("NFKC").toLocaleLowerCase().trim().split(/\s+/u).filter(Boolean),i=r.filter(o=>!o.reset),s=i.filter(o=>t.every(n=>o.label.normalize("NFKC").toLocaleLowerCase().includes(n))).toSorted((o,n)=>o.label.localeCompare(n.label,void 0,{sensitivity:"base",numeric:!0}));return{pinned:r.filter(o=>o.reset),sections:[{label:null,options:s}],facets:[],showFacets:!1,count:s.length,total:i.length}}var Rs=class extends F{static properties={users:{attribute:!1},resetLabel:{type:String,attribute:"reset-label"}};static styles=[F.styles,z`.avatar{position:relative;overflow:hidden}.avatar img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}`];constructor(){super(),this.users=[],this.resetLabel="",this.label="Choose user",this.placeholder="Choose user"}get searchLabel(){return"Search users"}get optionsLabel(){return"Users"}get noMatchesLabel(){return"No matching users"}get emptyLabel(){return"No users available"}get changeEvent(){return"user-change"}willUpdate(e){(e.has("users")||e.has("resetLabel"))&&(this.options=[...this.resetLabel?[{value:"",label:this.resetLabel,reset:!0}]:[],...Yl(this.users)])}choices(){return Xl(this.options,this._query)}optionIcon(e){return e.initials?c`<span class="avatar" aria-hidden="true">${e.initials}${Ee()?m:Rr(e.value,c`<img alt="" loading="lazy" decoding="async" src="${`/api/avatar/${encodeURIComponent(e.value)}`}" @error="${t=>{t.currentTarget.hidden=!0}}">`)}</span>`:m}};customElements.get("user-selector")||customElements.define("user-selector",Rs);S();B();var Ql=`:host{padding:0;margin-top:2rem;container-type:normal}.heading{display:flex;align-items:center;justify-content:space-between;gap:1rem}h2{margin:0;font-size:1.125rem}.intro{margin:.5rem 0 1rem}.alias-table{overflow-x:auto;padding-bottom:.5rem}table{width:100%;border-collapse:collapse;text-align:left}th,td{padding:.35rem .5rem;border-bottom:1px solid var(--border)}th{color:var(--muted);font-weight:500}td:not(.actions,.empty){overflow-wrap:anywhere}input{width:100%;min-width:7rem;padding:.3rem .45rem;border:1px solid var(--border);border-radius:.375rem;background:var(--bg);color:var(--text);font:inherit}.actions{white-space:nowrap;text-align:right}.actions .btn{min-height:1.75rem;padding:.2rem .55rem}.actions .btn+.btn{margin-left:.25rem}
|
|
267
267
|
`;var hh="/api/admin/repositories/aliases";async function ec(r="",e={}){let t=await $(`${hh}${r}`,{credentials:"same-origin",...e}),i=await t.json();if(!t.ok){let s={"alias-exists":"An alias already exists for this old repository and path. Edit that row instead.","bad-old-repo":"Enter the old repository as owner/name or a GitHub URL.","bad-directory":"Enter repository directories without parent segments, backslashes, or surrounding whitespace.","bad-repo":"Choose a connected repository.","no-alias":"This alias was removed. Refresh the list and try again."};throw new Error(s[i?.error]??`HTTP ${t.status}`)}return i}var Es=class extends T{static properties={repositories:{attribute:!1},_data:{state:!0},_edit:{state:!0},_error:{state:!0},_busy:{state:!0}};static styles=[x(N),x(Ql)];constructor(){super(),this._data=null,this._edit=null,this._error=null,this._busy=!1}connectedCallback(){super.connectedCallback(),this._load()}updated(e){e.has("repositories")&&e.get("repositories")!==void 0&&(this.appState.invalidate(["repository-aliases"]),this._load())}async _load(){this._error=null,await this._loadCollection("repository-aliases","repository aliases",e=>ec("",{signal:e}),e=>{this._data=e})}_start(e=null){this._error=null,this._edit=e?{...e}:{id:null,oldRepo:"",oldPath:"",repoId:null,newPath:""}}async _mutate(e,t,i){if(!(this._busy||!this._csrf||this._role!=="admin")){this._busy=!0,this._error=null;try{await this.appState.mutate(()=>ec(t?`/${encodeURIComponent(t)}`:"",{method:e,headers:{"content-type":"application/json","x-csrf-token":this._csrf},...i?{body:JSON.stringify(i)}:{}}),["repository-aliases","workspace-import"]),this._edit=null,await this._load()}catch(s){this._error=String(s?.message??s)}finally{this._busy=!1}}}_save(){let{id:e,...t}=this._edit;return this._mutate(e?"PATCH":"POST",e,t)}_field(e,t,i){return c`<td><input type="text" aria-label="${t}" placeholder="${i}" .value="${this._edit[e]}" ?disabled="${this._busy}" @input="${s=>{this._edit={...this._edit,[e]:s.target.value}}}"></td>`}_editor(){let e=(this._data?.repos??[]).filter(t=>t.active!==!1).map(t=>({value:t.repoId,label:t.fullName}));return c`<tr>${this._field("oldRepo","Old repository","owner/repository")}${this._field("oldPath","Old path","Repository root")}<td><repository-selector label="New repository" placeholder="Choose repository…" .options="${e}" .value="${this._edit.repoId}" ?disabled="${this._busy}" @repository-change="${t=>{this._edit={...this._edit,repoId:t.detail.value}}}"></repository-selector></td>${this._field("newPath","New path","Repository root")}<td class="actions"><button type="button" class="btn" ?disabled="${this._busy||!this._edit.oldRepo.trim()||this._edit.repoId==null}" @click="${()=>{this._save()}}">${this._busy?"Saving\u2026":"Save"}</button> <button type="button" class="btn" ?disabled="${this._busy}" @click="${()=>{this._edit=null,this._error=null}}">Cancel</button></td></tr>`}render(){let e=this._data?.aliases??[],t=this._data?.repos??[];return c`<section aria-labelledby="aliases-heading"><div class="heading"><h2 id="aliases-heading">Aliases</h2><button type="button" class="btn" ?disabled="${this._busy||this._edit!=null||!this._data}" @click="${()=>this._start()}">Add alias</button></div><p class="intro">Map repository locations when importing new reports and bundles.</p>${this._error?c`<p class="msg error" role="alert">${this._error}</p>`:m}<div aria-busy="${this._loading}">${this._data===null?this._error?c`<button type="button" class="btn" @click="${()=>{this._load()}}">Try again</button>`:q("Loading repository aliases\u2026"):c`<div class="alias-table"><table><thead><tr><th>Old repository</th><th>Old path</th><th>New repository</th><th>New path</th><th><span class="sr-only">Actions</span></th></tr></thead><tbody>${e.map(i=>this._edit?.id===i.id?this._editor():c`<tr><td>${i.oldRepo}</td><td class="mono">${i.oldPath||"/"}</td><td>${t.find(s=>s.repoId===i.repoId)?.fullName??"Removed repository"}${t.find(s=>s.repoId===i.repoId)?.active===!1?" (inactive)":""}</td><td class="mono">${i.newPath||"/"}</td><td class="actions"><button type="button" class="btn" ?disabled="${this._busy||this._edit!=null}" @click="${()=>this._start(i)}">Edit</button> <button type="button" class="btn" ?disabled="${this._busy||this._edit!=null}" @click="${()=>{this._mutate("DELETE",i.id)}}">Delete</button></td></tr>`)} ${this._edit?.id===null?this._editor():m} ${e.length===0&&!this._edit?c`<tr><td colspan="5" class="empty">No repository aliases yet.</td></tr>`:m}</tbody></table></div>`}</div></section>`}};customElements.define("managed-repository-aliases",Es);function tc(r){document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:r},bubbles:!0,composed:!0}))}function oc(r,e){return c`<span class="avatar" aria-hidden="true"><span>${(e?.[0]??"?").toUpperCase()}</span> ${Ee()?m:c`<img alt="" src="${`/api/avatar/${encodeURIComponent(r)}`}" @error="${t=>t.currentTarget.classList.add("broken")}">`}</span>`}var mh=P(Hn),js=P(qn),rc=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="m4 4 8 8m0-8-8 8"/></svg>`,As=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>`,fh={admin:"Admin",manage:"Manager",triage:"Triage",view:"Viewer",none:"No access"},gh={admin:"Manage workspace access and teams",manage:"Manage content and triage within team access",triage:"Review and triage findings",view:"Read-only access",none:"No workspace access"},Ms=class extends T{static styles=[x(ba),x(N)];render(){let e=[["manage-bundles","Bundles","Keep source archives ready for review.","bundle"],["manage-scans","Scans","Run and monitor scans from stored bundles.","scan"],["manage-reports","Reports","Review, publish, and organize findings.","report"]],t=[["manage-repos","Repositories","Connect sources and manage repository settings.","repo"],["admin-users","Users","Manage accounts, roles, and workspace access.","users"],["manage-teams","Teams","Bring people and repositories together.","team"]];return c`<div class="wrap">${U("manage",this._role,this.allowShare)}<h1 class="sr-only">Manage</h1>${this._role==null?c`<p class="msg" role="status">Loading management pages…</p>`:c`<section class="home-section" aria-labelledby="content-heading"><div class="section-heading"><h2 id="content-heading">Content & activity</h2><span>From source to findings</span></div><div class="pages">${e.filter(([i])=>i!=="manage-scans"||["admin","manage"].includes(this._role)).map(i=>this._page(i))}</div></section>${this._role==="admin"?c`<section class="home-section" aria-labelledby="workspace-heading"><div class="section-heading"><h2 id="workspace-heading">Workspace & access</h2><span>Sources, people, and permissions</span></div><div class="pages workspace-pages">${t.map(i=>this._page(i))}</div></section>`:m} <button type="button" class="history-link" @click="${()=>tc("manage-history")}"><span class="page-icon" aria-hidden="true">${D("history")}</span> <span class="page-copy"><strong>Workspace history</strong><span>Follow activity and triage changes across your workspace.</span></span> <span class="history-cta">View history ${D("arrow")}</span></button>`}</div>`}_page([e,t,i,s]){return c`<button type="button" class="${`page page-${s}`}" @click="${()=>tc(e)}"><span class="page-top"><span class="page-icon" aria-hidden="true">${D(s)}</span><strong class="page-title">${t}</strong><span class="arrow" aria-hidden="true">${D("arrow")}</span></span> <span class="page-copy"><span>${i}</span></span></button>`}};customElements.define("managed-admin-home",Ms);var Is=class extends T{static properties={_page:{state:!0},_history:{state:!0},_total:{state:!0},_error:{state:!0},_filter:{state:!0},_query:{state:!0},_repo:{state:!0},_actor:{state:!0},_options:{state:!0}};static styles=[x(va),x(N)];constructor(){super(),this._history=null,this._total=0,this._searchTimer=null,this._error=null,this._page=1,this._filter="all",this._query="",this._repo="",this._actor="",this._options={repos:[],users:[]},this._onActorFilter=e=>{let t=e.detail?.actor;if(typeof t!="string")return;let i=t.startsWith("user:")||t.startsWith("legacy:");this._query=i?"":t,this._filter="all",this._repo="",this._actor=i?t:"",this._load()}}connectedCallback(){super.connectedCallback(),document.addEventListener("managed-history-filter",this._onActorFilter),this._load()}disconnectedCallback(){clearTimeout(this._searchTimer),document.removeEventListener("managed-history-filter",this._onActorFilter),super.disconnectedCallback()}async _load(e=1){clearTimeout(this._searchTimer),this._error=null;let t=this._filter,i=this._query.trim(),s=this._actor,o=this._repo,n=`history:${JSON.stringify([e,t,i,o,s])}`;await this._loadCollection(n,"history",a=>ea(a,e,t,i,o,s),a=>{this._history=a.history,this._total=a.total,this._page=a.page,this._options=a.filters??{repos:[],users:[]}})}_search(e){this._query=e,clearTimeout(this._searchTimer),this._loadRequest?.abort(),this._loadRequest=null,this._loading=!0,this._searchTimer=setTimeout(()=>{this._load()},250)}_setRepo(e){return this._repo=e,this._load()}_setActor(e){return this._actor=e,this._load()}_clearContext(){return this._repo="",this._actor="",this._load()}_contextFilters(){let e=this._options.repos,t=this._options.users??[],i=[{value:"",label:"All repositories",special:!0,reset:!0},...this._repo&&!e.includes(this._repo)?[{value:this._repo,label:this._repo}]:[],...e.map(s=>({value:s,label:s}))];return c`<repository-selector label="Filter history by repository" .options="${i}" .value="${this._repo}" @repository-change="${s=>{this._setRepo(s.detail.value)}}"></repository-selector><user-selector label="Filter history by user" reset-label="All users" placeholder="${this._actor?"Selected user":"All users"}" .users="${t}" .value="${this._actor}" @user-change="${s=>{this._setActor(s.detail.value)}}"></user-selector><button type="button" class="btn" aria-label="Clear repository and user filters" ?disabled="${!this._repo&&!this._actor}" @click="${()=>{this._clearContext()}}">Clear selection</button>`}render(){let e=this._history??[],t=this._page,i=(t-1)*100;return c`<div class="wrap">${U("manage-history",this._role,this.allowShare)}<h1 class="sr-only">History</h1><div class="page-intro"><p class="intro">${this._role==="admin"?"Uploads, builds, access changes, repository changes, deletions, and triage.":"Bundle, report, and triage history within your team access."}</p><span class="result-count">${this._history?this._total:"\u2026"} entries</span></div><div class="toolbar" role="search"><input type="search" maxlength="500" aria-label="Search history" placeholder="Search history…" .value="${this._query}" @input="${s=>this._search(s.target.value)}"> <select aria-label="Filter history by type" .value="${this._filter}" @change="${s=>{this._filter=s.target.value,this._load()}}"><option value="all">All activity</option><option value="triage">Triage</option><option value="visibility">Visibility</option><option value="upload">Uploads and builds</option><option value="repository">${this._role==="admin"?"Repositories":"Assignments"}</option>${this._role==="admin"?c`<option value="access">Access</option>`:m}<option value="delete">Deletions</option></select> ${this._contextFilters()} <button type="button" class="btn" ?disabled="${this._loading}" @click="${()=>this._load(t)}">Refresh</button></div>${this._error?c`<p class="msg error" role="alert">Couldn’t load history: ${this._error} <button type="button" class="btn" @click="${()=>this._load()}">Retry</button></p>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._history==null?this._error?m:q("Loading history\u2026"):e.length===0?c`<div class="history"><p class="empty">${this._query.trim()||this._filter!=="all"||this._repo||this._actor?"No activity matches your filters.":"No history available yet."}</p></div>`:c`<div class="history" aria-label="Workspace history"><div class="history-head" aria-hidden="true"><span>Type</span><span>Activity</span><span>Repository / report / finding</span><span>Time</span></div>${e.map(s=>this._row(s))}</div>`}</div>${this._total>100?c`<nav class="pagination" aria-label="History pages"><span role="status">${i+1}–${Math.min(i+100,this._total)} of ${this._total} entries</span><button type="button" class="btn" ?disabled="${this._loading||t===1}" @click="${()=>this._changePage(t-1)}">Previous</button><span>Page ${t} of ${Math.ceil(this._total/100)}</span><button type="button" class="btn" ?disabled="${this._loading||i+100>=this._total}" @click="${()=>this._changePage(t+1)}">Next</button></nav>`:m}</div>`}async _changePage(e){await this._load(e),await this.updateComplete,this.renderRoot.querySelector(".manage-list")?.scrollTo({top:0})}_row(e){let t=[e.repo??e.repository,e.report,e.finding].filter(Boolean).join(" \xB7 "),i=e.actor??e.user??"Unknown user",s=e.action??"updated workspace data";return c`<div class="row"><span class="${`kind ${e.kind??""}`}">${e.kind??"activity"}</span><span class="activity-description" data-tooltip-truncated data-tooltip="${`${i} ${s}`}"><strong class="actor">${i}</strong> <span class="action">${s}</span></span><span class="detail" data-tooltip-truncated data-tooltip="${t}">${t||"\u2014"}</span><span class="history-time">${Ls(e.at)}</span></div>`}};customElements.define("managed-admin-history",Is);function Ls(r){if(r==null||r==="")return c`<span>Unknown</span>`;let e=typeof r=="number"?r:Number(r);if(!Number.isFinite(e))return c`<span>Unknown</span>`;let t=new Date(e);return Number.isNaN(t.getTime())?c`<span>Unknown</span>`:c`<time datetime="${t.toISOString()}">${t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}</time><span>${t.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"})}</span>`}function ic(r){if(r==null||r==="")return"Unknown";let e=typeof r=="number"?r:Number(r);return Number.isFinite(e)&&!Number.isNaN(new Date(e).getTime())?`Last seen ${new Date(e).toLocaleString()}`:"Unknown"}function sc(r){return r?.lastActivityAt??r?.lastActivity??r?.lastWriteAt??r?.lastActiveAt}var zs=class extends T{static properties={_query:{state:!0},_users:{state:!0},_teams:{state:!0},_error:{state:!0}};static styles=[x(ya),x(N)];constructor(){super(),this._users=null,this._query="",this._teams=null,this._error=null}connectedCallback(){super.connectedCallback(),this._load()}async _load(){this._error=null,await this._loadCollection("users","users",e=>Promise.all([ta(e),Ni(e)]),([e,t])=>{this._users=e,this._teams=Array.isArray(t?.teams)?t.teams:[]})}_filteredUsers(){let e=this._query.trim().toLocaleLowerCase();return(this._users??[]).filter(t=>[t.name,t.login,t.role,...(this._teams??[]).filter(i=>i.members?.some(s=>s.userId===t.id)).map(i=>i.name)].filter(Boolean).join(" ").toLocaleLowerCase().includes(e))}render(){let e=this._filteredUsers();return c`<div class="wrap">${U("admin-users",this._role,this.allowShare)}<h1 class="sr-only">Users</h1><div class="page-intro"><p class="intro">Manage workspace access and roles.</p></div><div class="collection-toolbar" role="search"><input type="search" aria-label="Search users" placeholder="Search by name, username, or team…" .value="${this._query}" @input="${t=>{this._query=t.target.value}}"><span class="result-count" role="status">${this._users&&this._query.trim()?`${e.length} matching out of `:""}${this._users?.length??"\u2026"} users</span></div>${this._error?c`<p class="msg error" role="alert">Couldn't load users: ${this._error}</p>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._users==null?this._error?m:q("Loading users\u2026"):this._list(e)}</div></div>`}_list(e){return this._users.length===0?c`<p class="msg">No users yet.</p>`:e.length===0?c`<div class="empty"><strong>No matching users</strong><p>Try another name, username, or team.</p></div>`:c`<div class="directory"><div class="list-head" aria-hidden="true"><span>Account</span><span>Team access</span><span>Last seen</span><span>Last activity</span><span>Role</span></div><ul class="users">${e.map(t=>this._row(t))}</ul></div>${this._users.some(t=>t.id===this._me)?c`<p class="self-note">Your own role can only be changed by another admin.</p>`:m}`}_row(e){let t=e.id===this._me,i=(this._teams??[]).flatMap(s=>{let o=s.members?.find(n=>n.userId===e.id);return o==null?[]:[{team:s,member:o}]});return c`<li><span class="person">${oc(e.id,e.login)} <span class="who"><span class="name"><span class="name-text">${e.name||e.login}</span>${t?c`<span class="you">You</span>`:m}</span> <span class="login">@${e.login}</span> </span></span><span class="memberships">${Ge(e.role,"manage")?c`<span class="team-access"><strong>${e.role==="admin"?"All reports":"Owned and team reports"}</strong><span class="team-perms"><span class="permission-granted">+ Deps</span><span class="permission-granted">+ Security</span></span></span>`:i.length===0?c`<span class="no-team">No team access</span>`:i.map(({team:s,member:o})=>c`<span class="team-access"><strong>${D("team")}<span>${s.name}</span></strong><span class="team-perms">${["dependencies","security"].map(n=>c`<span class="${o[n]===!0?"permission-granted":"permission-denied"}">${o[n]===!0?"+":"\u2212"} ${n==="dependencies"?"Deps":"Security"}</span>`)}</span></span>`)} </span><span class="last-seen" aria-label="${ic(e.lastSeenAt)}">${Ls(e.lastSeenAt)}</span> <button type="button" class="activity-link" aria-label="${`Show activity by ${e.login}`}" @click="${()=>this._showActivity(e.id)}"><span class="last-activity" aria-label="${`Last activity ${ic(sc(e)).replace(/^Last seen /u,"")}`}">${Ls(sc(e))}</span></button> <span class="access"><select class="role" ?disabled="${t}" aria-label="${`Change ${e.login}\u2019s role`}" aria-description="${gh[e.role]??""}" @change="${s=>this._changeRole(e,s.target.value,s.target)}">${Re.map(s=>c`<option value="${s}" ?selected="${s===e.role}">${fh[s]}</option>`)}</select></span></li>`}async _changeRole(e,t,i){let s=e.role;if(t!==s){try{await this.appState.mutate(()=>ra(e.id,t,this._csrf),["users","teams","reports","history"]),e.role=t,await this._load()}catch(o){console.warn("admin: set role failed:",o),i.value=s}this.requestUpdate()}}_showActivity(e){document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage-history",actor:`user:${e}`},bubbles:!0,composed:!0}))}};customElements.define("managed-admin-users",zs);var nc=D("repo"),Os=class extends T{static properties={_publicRepoOpen:{state:!0},_publicRepository:{state:!0},_publicRepoError:{state:!0},_addingPublic:{state:!0},_data:{state:!0},_error:{state:!0},_actionError:{state:!0},_scope:{state:!0},_showAll:{state:!0},_query:{state:!0},_organization:{state:!0},_loading:{state:!0},_busy:{state:!0},_connectingApp:{state:!0},_detail:{state:!0},_impact:{state:!0},_impactLoading:{state:!0},_removeOpen:{state:!0},_acknowledge:{state:!0},_deleteTriage:{state:!0},_confirmName:{state:!0}};static styles=[x(wa),x(N)];constructor(){super(),this._publicRepoOpen=!1,this._publicRepository="",this._publicRepoError=null,this._addingPublic=!1,this._data=null,this._error=null,this._actionError=null,this._scope="connected",this._showAll=!1,this._query="",this._organization=null,this._loading=!0,this._busy=null,this._connectingApp=!1,this._detail=null,this._impact=null,this._impactLoading=!1,this._impactFresh=!1,this._removeOpen=!1,this._acknowledge=!1,this._deleteTriage=!1,this._confirmName="",this._impactRequest=null}connectedCallback(){super.connectedCallback(),this._load()}disconnectedCallback(){super.disconnectedCallback(),this._impactRequest?.abort()}_repositoryKey(){return`repos:${JSON.stringify([this._scope,this._showAll])}`}async _load(e=!1){this._error=null;let{_scope:t,_showAll:i}=this;await this._loadCollection(this._repositoryKey(),"repositories",s=>ia(t,i,e,s),s=>{this._data=s,this._organization=this._repositoryChoices().activeFacet})}_open(e){this._impactRequest?.abort(),this._publicRepoOpen=!1,this._scope=e,this._showAll=!1,this._query="",this._organization=null,this._detail=null,this._impact=null,this._removeOpen=!1,this._acknowledge=!1,this._deleteTriage=!1,this._confirmName="",this._data=null,this._actionError=null,this._load()}_setShowAll(e){this._showAll=e,this._organization=null,this._data=null,this._load()}_search(e){this._query=e}_repositoryChoices(){let e=(this._data?.repositories??[]).map(t=>({value:t.id,label:t.fullName,repo:t}));return mr(e,this._query,this._organization,{includeSingletonOrganizations:!0})}_back(e=null){return c`<div class="breadcrumb"><button type="button" class="breadcrumb-manage" @click="${()=>{document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage"},bubbles:!0,composed:!0}))}}">Manage</button> <span class="breadcrumb-separator" aria-hidden="true">›</span> <button type="button" class="breadcrumb-manage" aria-label="Back to repositories" @click="${()=>{this._detail?(this._impactRequest?.abort(),this._detail=null,this._actionError=null):this._open("connected")}}">Repositories</button> <span class="breadcrumb-separator" aria-hidden="true">›</span> ${e?c`<h1 class="breadcrumb-current">${e}</h1>`:m}</div>`}_openDetail(e){this._detail=e,this._actionError=null,this._impact=this.appState.read(`repo-impact:${e.id}`)??null,this._impactFresh=!1,this._removeOpen=!1,this._acknowledge=!1,this._deleteTriage=!1,this._confirmName="",this._impactLoading=!0,this._impactRequest?.abort();let t=new AbortController;this._impactRequest=t,this.appState.load(`repo-impact:${e.id}`,"repository data",i=>na(e.id,i),{signal:t.signal,apply:i=>{this._impact=i}}).then(i=>(t.signal.aborted||(this._impactFresh=!0),i)).catch(i=>{!t.signal.aborted&&i?.name!=="AbortError"&&!this._impact&&(this._actionError=`Couldn't load repository data: ${i?.message??i}`)}).finally(()=>{this._impactRequest===t&&(this._impactLoading=!1)})}render(){if(this._detail)return this._detailPage(this._detail);let e=this._scope==="connected",t=e?"Repositories":`Add ${this._scope} repository`,i=this._repositoryChoices();return c`<div class="wrap">${U("manage-repos",this._role,this.allowShare)} ${e?c`<h1 class="sr-only">${t}</h1>`:this._back(t)}<div class="page-intro"><p class="intro">${e?"Manage connected repositories and their settings.":this._scope==="installed"?this._showAll?"Showing all repositories the GitHub App can read.":"Showing installed repositories you can access on GitHub.":"Choose a public repository your GitHub account is involved with."}</p>${e?c`<div class="repository-actions"><button type="button" class="btn" @click="${()=>this._open("installed")}">${this._accessIcon("private")} Add installed repository</button> <button type="button" class="btn" @click="${()=>this._open("public")}">${this._accessIcon("public")} Add your public repository</button> ${this._role==="admin"&&this._data?.canAddAnyPublicRepository?c`<button type="button" class="btn" aria-expanded="${this._publicRepoOpen}" @click="${()=>this._openPublicRepository()}">${this._accessIcon("public")} Add a public repository</button>`:m}</div>`:m}</div>${!e&&this._scope==="installed"?c`<div class="access-note"><p>Installed repositories are readable through the GitHub App. Install it on a repository or organization to make it available here.</p><span class="access-action">${this._data?.installUrl?c`<a class="btn" href="${this._data.installUrl}" target="_blank" rel="noopener noreferrer">Configure GitHub access</a>`:c`<button type="button" class="btn" disabled="disabled">Configure GitHub access</button>`}</span></div>`:m}<div class="toolbar"><label class="search"><input type="search" aria-label="${e?"Search connected repositories":`Search ${this._scope} repositories`}" placeholder="Search by repository or owner…" .value="${this._query}" @input="${s=>this._search(s.target.value)}"></label> ${this._scope==="installed"?c`<label class="show-all"><input type="checkbox" role="switch" .checked="${this._showAll}" @change="${s=>this._setShowAll(s.target.checked)}"><span>Show all</span></label><label class="show-all-paper"><input type="checkbox" .checked="${this._showAll}" @change="${s=>this._setShowAll(s.target.checked)}"><span>Show all</span></label>`:m} ${e?c`<span class="result-count" role="status">${this._data&&(this._query.trim()||i.activeFacet!=null)?`${i.count} ${i.count===1?"repository":"repositories"} out of `:""}${this._data?.connectedCount??"\u2026"} connected</span>`:c`<button type="button" class="btn" ?disabled="${this._loading}" @click="${()=>{this._load(!0)}}">Refresh</button>`}</div>${e&&this._publicRepoOpen&&this._role==="admin"&&this._data?.canAddAnyPublicRepository?this._publicRepositoryForm():m} ${this._actionError?c`<p class="msg error" role="alert">${this._actionError}</p>`:m} ${this._error?c`<p class="msg error" role="alert">Couldn't load repositories: ${this._error}</p><button type="button" class="btn" @click="${()=>{this._load()}}">Try again</button>`:m} ${!e&&this._data?c`<p class="repository-count" role="status">${i.count}${i.count===i.total?"":` of ${i.total}`} ${i.total===1?"repository":"repositories"}</p>`:m}<div aria-busy="${this._loading}">${this._body(i)}</div>${e&&this._role==="admin"?c`<managed-repository-aliases .session="${this.session}" .repositories="${this._data?.repositories}"></managed-repository-aliases>`:m}</div>`}_body(e){return this._data?c`${this._data.tokenMissing&&!this._showAll&&this._scope!=="connected"?c`<p class="msg">Log out and back in to refresh your GitHub membership access.</p>`:m}<div class="repository-browser">${e.showFacets?c`<nav class="organization-list" aria-label="Filter by organization"><button type="button" class="organization" aria-pressed="${e.activeFacet==null}" @click="${()=>{this._organization=null}}"><span class="organization-name">All organizations</span><span class="organization-count">${e.total}</span></button> ${e.facets.map(t=>c`<button type="button" class="organization" aria-pressed="${e.activeFacet===t.value}" @click="${()=>{this._organization=t.value}}"><span class="organization-name" data-tooltip-truncated data-tooltip="${t.name}">${t.name}</span><span class="organization-count">${t.count}</span></button>`)}</nav>`:m}<div class="repo-results">${e.sections.map(t=>c`<section class="repo-group" aria-label="${t.label??"Repositories"}">${t.label?c`<h2 class="owner-head"><span class="owner-icon" aria-hidden="true">${t.label[0]??"?"}</span>${t.label}</h2>`:m}<ul class="repos">${t.options.map(i=>this._row(i.repo,t.organization?i.name:i.label))}</ul></section>`)} ${e.count?m:c`<div class="empty"><strong>${e.total?"No matching repositories":this._scope==="connected"?"No connected repositories yet":`No ${this._scope} repositories available`}</strong><p>${e.total?"Try a different search or organization.":this._scope==="connected"?"Add an installed or public repository to get started.":this._scope==="installed"?this._showAll?"Install the GitHub App, then refresh this list.":"No installed repositories match your GitHub access. Turn on Show all to browse every installation.":"Public repositories associated with your GitHub account will appear here."}</p></div>`}</div></div>`:this._error?m:q("Loading repositories\u2026")}_openPublicRepository(){this._publicRepoOpen=!0,this._publicRepoError=null,this.updateComplete.then(()=>this.renderRoot?.querySelector("#public-repository")?.focus())}_publicRepositoryForm(){return c`<form class="public-repository-form" aria-label="Add a public repository" @submit="${e=>{e.preventDefault(),this._addPublicRepository()}}"><label class="confirm-field" for="public-repository"><span>Public GitHub repository</span> <input id="public-repository" class="confirm-name" type="text" placeholder="owner/repo or https://github.com/owner/repo" autocomplete="off" required .value="${this._publicRepository}" ?disabled="${this._addingPublic}" @input="${e=>{this._publicRepository=e.target.value}}"></label><div class="dialog-actions"><button type="button" class="btn" ?disabled="${this._addingPublic}" @click="${()=>{this._publicRepoOpen=!1}}">Cancel</button><button type="submit" class="btn" ?disabled="${this._addingPublic||!this._publicRepository.trim()}">${this._addingPublic?"Adding\u2026":"Add repository"}</button></div>${this._publicRepoError?c`<p class="msg error" role="alert">${this._publicRepoError}</p>`:m}</form>`}async _addPublicRepository(){if(!(this._addingPublic||!this._publicRepository.trim())){this._addingPublic=!0,this._publicRepoError=null;try{await this.appState.mutate(()=>oa(this._publicRepository.trim(),this._csrf),["repos","reports","bundles","teams","users","history","scan-sources"]),this._publicRepoOpen=!1,this._publicRepository="",await this._load()}catch(e){this._publicRepoError=e?.message??String(e)}finally{this._addingPublic=!1}}}_row(e,t){let i=`${this._accessLabel(e)}${this._scope==="connected"&&e.active===!1?" \xB7 Deactivated":""}`,s=c`${nc}<span class="repo-copy"><span class="repo-name">${t}</span><span class="repo-meta">${i}</span></span>`;return this._scope==="connected"?c`<li><button type="button" class="repo-row" aria-label="${`Manage ${e.fullName}`}" @click="${()=>this._openDetail(e)}">${s}<svg class="arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="m6 4 4 4-4 4"/></svg></button></li>`:c`<li class="repo-row">${s} ${e.selected?c`<span class="connected"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m3 8 3 3 7-7"/></svg>Connected</span>`:e.private&&!e.installed?c`<span class="repo-meta">Needs App access</span>`:c`<button type="button" class="btn" aria-label="${`Add ${e.fullName}`}" ?disabled="${this._busy!=null}" @click="${()=>{this._setActive(e,!0)}}">${this._busy===e.id?"Adding\u2026":"Add"}</button>`}</li>`}_accessLabel(e){let t=e.visibility==="public"?"Public":e.visibility==="internal"?"Internal":e.private?"Private":null,i=e.installed?"GitHub App":"GitHub";return t?`${t} \xB7 ${i}`:i}_connectAppButton(e){return e.installed?m:c`<button type="button" class="btn connect-app" aria-label="${`Connect GitHub App to ${e.fullName}`}" ?disabled="${this._busy!=null}" @click="${()=>{this._connectApp(e)}}">${this._connectingApp&&this._busy===e.id?"Connecting\u2026":"Connect GitHub App"}</button>`}async _connectApp(e){if(!(this._busy!=null||e.installed)){this._busy=e.id,this._connectingApp=!0,this._actionError=null;try{let t=await this.appState.mutate(()=>aa(e.id,this._csrf),["repos","history","scan-sources"]);if(!this.isConnected)return;if(!t.connected){globalThis.location.assign(t.installUrl);return}this._detail?.id===e.id&&(this._detail={...this._detail,installed:!0}),this._data&&(this._data={...this._data,repositories:this._data.repositories.map(i=>i.id===e.id?{...i,installed:!0}:i)}),await this._load()}catch(t){this._actionError=`Couldn't connect ${e.fullName}: ${t?.message??t}`}finally{this._busy=null,this._connectingApp=!1}}}_detailPage(e){let t=e.active!==!1,i=this._impact?.reports??[],s=this._impact?.bundles??[];return c`<div class="wrap">${U("manage-repos",this._role,this.allowShare)}<div class="head">${this._back()}<h1>${e.fullName}</h1></div><p class="intro ui-hint">Repository settings and stored data.</p>${this._actionError?c`<p class="msg error" role="alert">${this._actionError}</p>`:m}<section class="section" aria-label="Repository connection"><h2>Connection</h2><div class="settings-row"><div class="settings-copy"><strong>${this._accessLabel(e)}</strong><p>${t?"Active for new scans and uploads.":"Deactivated. Stored reports and bundles are retained."}</p></div><span class="${`status-line ${t?"":"inactive"}`}">${t?"Active":"Deactivated"}</span> ${this._connectAppButton(e)} ${e.htmlUrl?c`<a class="btn" href="${e.htmlUrl}" target="_blank" rel="noopener noreferrer">View on GitHub</a>`:m}</div><div class="settings-row"><div class="settings-copy"><strong>${t?"Deactivate repository":"Reactivate repository"}</strong><p>${t?"Pause new scans while preserving all stored data and attachments.":"Make this repository available for new scans and bundle attachments again."}</p></div><button type="button" class="btn" ?disabled="${this._busy!=null}" @click="${()=>{this._setActive(e,!t)}}">${this._busy===e.id&&!this._connectingApp?t?"Deactivating\u2026":"Reactivating\u2026":t?"Deactivate":"Reactivate"}</button></div></section><section class="data-section" aria-label="Stored repository data"><h2>Stored data</h2><div class="dialog-data" aria-busy="${this._impactLoading}">${[["Reports",i],["Bundles",s]].map(([o,n])=>c`<section><h3>${o} (${this._impact==null?"\u2026":n.length})</h3>${this._impactLoading&&this._impact==null?c`<p class="data-empty" role="status">Loading ${o.toLowerCase()}…</p>`:this._impact==null?c`<p class="data-empty">Attached data could not be loaded.</p><button type="button" class="btn" @click="${()=>this._openDetail(e)}">Try again</button>`:n.length>0?c`<ul>${n.map(a=>c`<li>${a.filename}${a.repoDirectory?` \xB7 ${a.repoDirectory}`:m}</li>`)}</ul>`:c`<p class="data-empty">No ${o.toLowerCase()} attached.</p>`}</section>`)}</div></section><section class="section" aria-label="Permanent repository removal"><h2>Permanent removal</h2><div class="settings-row"><div class="settings-copy"><strong>Delete repository and stored data</strong><p>Deactivation is reversible. Permanent removal deletes this repository’s attached reports and bundles; it cannot be undone.</p></div><button type="button" class="btn danger" ?disabled="${this._busy!=null||this._impactLoading||!this._impactFresh||this._impact==null}" @click="${()=>{this._removeOpen=!0,this._acknowledge=!1,this._deleteTriage=!1,this._confirmName=""}}">Remove permanently</button></div></section>${this._removeOpen&&this._impact!=null&&!this._impactLoading?this._removeDialog(e,i,s):m}</div>`}_removeDialog(e,t,i){let s=t.length>0||i.length>0,o=this._canRemove(e);return c`<div class="dialog-backdrop" role="presentation" @click="${n=>{n.target===n.currentTarget&&(this._removeOpen=!1)}}"><section class="${`dialog ${s?"":"small"}`}" role="dialog" aria-modal="true" aria-labelledby="remove-repo-title"><h2 id="remove-repo-title">Remove ${e.fullName} permanently?</h2><p class="dialog-copy">${s?"This destructive action will remove the repository and the stored data listed below. Deactivation keeps all of it.":"This repository has no attached reports or bundles. Permanent removal deletes its connection record."}</p>${s?c`<div class="dialog-data"><section><h3>Reports to delete (${t.length})</h3><ul>${t.map(n=>c`<li>${tt(n.filename)}${n.repoDirectory?` \xB7 ${n.repoDirectory}`:m}</li>`)}</ul></section><section><h3>Bundles to delete (${i.length})</h3><ul>${i.map(n=>c`<li>${n.filename}</li>`)}</ul></section></div>`:m} <label class="confirm-line"><input type="checkbox" .checked="${this._acknowledge}" @change="${n=>{this._acknowledge=n.target.checked}}"><span>I understand this permanently deletes the repository connection${s?", reports, and bundles":""}.</span></label> ${(this._impact?.triageCount??0)>0?c`<label class="confirm-line"><input type="checkbox" .checked="${this._deleteTriage}" @change="${n=>{this._deleteTriage=n.target.checked}}"><span>Also delete ${this._impact.triageCount} triage entr${this._impact.triageCount===1?"y":"ies"} belonging only to this repository.</span></label>`:m} ${s?c`<label class="confirm-field"><span>Type <strong>${e.fullName}</strong> to confirm.</span><input class="confirm-name" type="text" autocomplete="off" .value="${this._confirmName}" @input="${n=>{this._confirmName=n.target.value}}"></label>`:m}<div class="dialog-actions"><button type="button" class="btn" @click="${()=>{this._removeOpen=!1}}">Cancel</button><button type="button" class="btn danger" ?disabled="${!o}" @click="${()=>{this._remove(e)}}">${this._busy===e.id?"Removing\u2026":"Remove permanently"}</button></div></section></div>`}_accessIcon(e){return e==="private"?c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="7" width="10" height="7" rx="1"/><path d="M5 7V5a3 3 0 0 1 6 0v2"/></svg>`:c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="8" r="6"/><path d="M2.5 8h11M8 2c1.5 1.7 2.2 3.7 2.2 6S9.5 12.3 8 14c-1.5-1.7-2.2-3.7-2.2-6S6.5 3.7 8 2Z"/></svg>`}async _setActive(e,t){if(this._busy==null){this._busy=e.id,this._actionError=null;try{if(await this.appState.mutate(()=>sa(e.id,t,this._csrf),["repos","reports","bundles","teams","users","history"]),!this.isConnected)return;this._detail?.id===e.id&&(this._detail={...this._detail,active:t}),this._data&&(this._data={...this._data,repositories:this._data.repositories.map(i=>i.id===e.id?{...i,active:t}:i)}),await this._load()}catch(i){let s=t?e.active===!1?"reactivate":"add":"deactivate";this._actionError=`Couldn't ${s} ${e.fullName}: ${i?.message??i}`}finally{this._busy=null}}}_canRemove(e){return this._busy!=null||this._impactLoading||!this._impactFresh||this._impact?.repoId!==e.id||!this._acknowledge?!1:!(this._impact.reports.length>0||this._impact.bundles.length>0)||this._confirmName===e.fullName}async _remove(e){if(this._canRemove(e)){this._busy=e.id,this._actionError=null;try{await this.appState.mutate(()=>la(e.id,e.fullName,this._deleteTriage,this._csrf),["repos","repo-impact","reports","report-preview","bundles","teams","users","history","scan-sources"]),this._removeOpen=!1,this._detail=null,this._impact=null,await this._load()}catch(t){this._actionError=`Couldn't remove ${e.fullName}: ${t?.message??t}`}finally{this._busy=null}}}};customElements.define("managed-admin-repos",Os);function Ts(r){return typeof r!="number"||!Number.isFinite(r)?"":r<1024?`${r} B`:r<1048576?`${(r/1024).toFixed(1)} KB`:`${(r/1048576).toFixed(1)} MB`}function ac(r){return[{value:null,label:"No repository",special:!0},...r.map(e=>({value:e.repoId,label:e.fullName}))]}var Ns=class extends T{static properties={localImportSource:{attribute:!1},_query:{state:!0},_visibility:{state:!0},_data:{state:!0},_error:{state:!0},_busy:{state:!0},_dragOver:{state:!0},_preview:{state:!0},_previewLoading:{state:!0},_locationReport:{state:!0},_locationRepo:{state:!0},_locationDirectory:{state:!0},_locationBusy:{state:!0}};static styles=[x(ur),x(Di),x(N),x(Bi)];constructor(){super(),this._query="",this._visibility="all",this._data=null,this._error=null,this._busy=!1,this._dragOver=!1,this._preview=null,this._previewLoading=null,this._previewRequest=null,this._locationReport=null,this._locationRepo=null,this._locationDirectory="",this._locationBusy=!1,this._teardownDrop=null,this._queue=[],this._localImport=new kt(this,"report",e=>Pi(this,e,t=>zi(t,this._csrf),["reports","repo-impact","history","scan-sources"]))}connectedCallback(){super.connectedCallback(),this._load(),this._teardownDrop=Ct(this,e=>{this._upload(e)},e=>{this._dragOver=e})}disconnectedCallback(){super.disconnectedCallback(),this._teardownDrop?.(),this._cancelPreview()}async _load({preserveError:e=!1}={}){e||(this._error=null),await this._loadCollection("reports","reports",ca,t=>{this._data=t,this._preview&&!t.reports?.some(i=>i.id===this._preview)&&this._cancelPreview()})}render(){return c`${this._dragOver?c`<div class="dropzone">Drop reports to upload</div>`:m}<div class="wrap">${U("manage-reports",this._role,this.allowShare)}<h1 class="sr-only">Reports</h1><div class="page-intro"><p class="intro">Upload reports. New reports stay hidden until you make them visible.</p>${this._localImport.renderAction()}</div>${this._localImport.renderPanel(this._busy||!this._csrf)}<div class="drop-card"><span class="drop-icon" aria-hidden="true">${D("upload")}</span><span class="drop-copy"><strong>Upload reports</strong><span>Drop files anywhere on this page.</span></span><button type="button" class="drop-browse" ?disabled="${this._busy}" @click="${()=>St(e=>{this._upload(e)})}">${this._busy?"Uploading\u2026":"Browse files"}</button></div>${this._data?.repoScopes?.length?c`<p class="intro">Team paths: ${this._data.repoScopes.map(e=>`${this._data.repos.find(t=>t.repoId===e.repoId)?.fullName??e.repoId}/${e.path??""}`).join(", ")}</p>`:m} ${this._body()}</div>`}_body(){let e=Array.isArray(this._data?.reports)?this._data.reports:[],t=this._query.trim().toLocaleLowerCase(),i=e.filter(o=>[o.filename,tt(o.filename),o.repoFullName,o.repoDirectory,o.uploadedByLogin].filter(Boolean).join(" ").toLocaleLowerCase().includes(t)&&(this._visibility==="all"||!!o.visible==(this._visibility==="visible"))),s=`${t||this._visibility!=="all"?`${i.length} of `:""}${e.length} ${e.length===1?"report":"reports"}`;return c`<div class="collection-toolbar" role="search"><input type="search" aria-label="Search reports" placeholder="Search reports or repositories…" .value="${this._query}" @input="${o=>{this._query=o.target.value}}"><select aria-label="Report visibility" .value="${this._visibility}" @change="${o=>{this._visibility=o.target.value}}"><option value="all">All reports</option><option value="visible">Visible to teams</option><option value="hidden">Hidden reports</option></select><span class="result-count" role="status">${this._data==null?"\u2026 reports":s}</span></div>${this._error?c`<p class="msg error" role="alert">${this._error}</p>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._data==null?this._error?m:q("Loading reports\u2026"):i.length>0?c`<div class="report-list"><div class="report-list-head" aria-hidden="true"><span class="report-heading">Report</span><span>Repository</span><span>Uploaded by</span><span>Date</span><span class="size-heading">Size</span><span>Visibility</span><span class="actions-heading">Actions</span></div><ul class="reports">${i.map(o=>this._row(o))}</ul></div>`:c`<div class="empty"><strong>${e.length===0?"No reports uploaded yet":"No matching reports"}</strong><p>${e.length===0?"Drop a report here or browse files above.":"Try a different search or visibility filter."}</p></div>`}</div>`}_row(e){let t=tt(e.filename),i=e.analyzer??e.source??e.producer??"default",s=Ai[i]??Ai.default,o=e.repoEmbedded!==!0&&e.canChangeRepo!==!1,n=e.repoEmbedded===!0||e.repoId!=null,a=e.repoFullName?`${e.repoFullName}${e.repoDirectory?`/${e.repoDirectory}`:""}`:"No repository assigned",l=Number.isFinite(e.uploadedAt)?new Date(e.uploadedAt).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"}):"";return c`<li class="${`report${e.visible===!1?" content-hidden":""}`}"><div class="report-main"><span class="report-mark" aria-hidden="true">${P(s)}</span> <span class="report-name" data-tooltip-truncated data-tooltip="${t}">${t}</span> <span class="report-location" data-tooltip-truncated data-tooltip="${a}">${a}</span> <span class="report-meta report-uploader" data-tooltip-truncated data-tooltip="${e.uploadedByLogin??"Uploader removed"}">${e.uploadedByLogin??"Uploader removed"}</span> <span class="report-meta report-date">${l}</span> <span class="report-meta report-size">${Ts(e.byteSize)}</span> <span class="${`status ${e.visible?"visible":"hidden"}`}">${e.visible?"Visible":"Hidden"}</span> <span class="report-actions">${o?c`<button type="button" class="action" data-tooltip="Set repository location" aria-label="${`Set location for ${t}`}" @click="${()=>this._openLocation(e)}">${D("repo")}</button>`:c`<span class="action-spacer"></span>`} <button type="button" class="action" aria-label="${`Preview ${t}`}" aria-expanded="${this._preview===e.id}" @click="${()=>{this._togglePreview(e)}}">${D("preview")}</button> <button type="button" class="action" data-tooltip="${e.visible?"Hide from teams":n?"Make visible to teams":"Assign a repository before publishing"}" aria-label="${`${e.visible?"Hide":"Make visible"} ${t}`}" ?disabled="${e.canChangeRepo===!1||!n&&!e.visible}" @click="${()=>{this._setVisible(e,!e.visible)}}">${D(e.visible?"hide":"show")}</button> <a class="action" aria-label="${`Download ${t}`}" href="${`/api/admin/reports/${encodeURIComponent(e.id)}`}">${D("download")}</a> <button type="button" class="action danger" aria-label="${`Delete ${t}`}" ?disabled="${e.canChangeRepo===!1}" @click="${()=>this._delete(e)}">${js}</button></span></div>${this._preview===e.id?c`<div class="preview">${this._previewLoading===e.id?c`<span class="preview-loading">Loading preview…</span>`:c`<pre>${this._previewText??""}</pre>`}</div>`:m} ${this._locationReport===e.id?this._locationEditor(e):m}</li>`}_openLocation(e){e.canChangeRepo!==!1&&(this._locationReport=e.id,this._locationRepo=e.repoId??null,this._locationDirectory=e.repoDirectory??"",this._error=null)}_locationEditor(e){let t=Array.isArray(this._data?.repos)?this._data.repos:[];return c`<div class="location-editor"><div class="location-field"><span>Repository</span><repository-selector label="Repository for report" .options="${ac(t)}" .value="${this._locationRepo}" ?disabled="${this._locationBusy}" @repository-change="${i=>{this._locationRepo=i.detail.value}}"></repository-selector></div><div class="location-field"><label for="${`report-dir-${e.id}`}">Directory (optional)</label><input id="${`report-dir-${e.id}`}" type="text" placeholder="Repository root" .value="${this._locationDirectory}" @input="${i=>{this._locationDirectory=i.target.value}}"></div><div class="location-actions"><button type="button" class="action" @click="${()=>{this._locationReport=null}}">Cancel</button><button type="button" class="action" ?disabled="${this._locationBusy}" @click="${()=>{this._saveLocation(e)}}">Save</button></div></div>`}async _saveLocation(e){if(!this._locationBusy){this._locationBusy=!0,this._error=null;try{await this.appState.mutate(()=>ua(e.id,this._locationRepo,this._locationDirectory.trim(),this._csrf),["reports","repo-impact","history","scan-sources"]),this._locationReport=null,await this._load({preserveError:!0})}catch(t){this._error=`Couldn't set report location: ${String(t?.message??t)}`}finally{this._locationBusy=!1}}}_cancelPreview(){this._previewRequest?.abort(),this._previewRequest=null,this._preview=null,this._previewLoading=null,this._previewText=""}async _togglePreview(e){let t=this._preview===e.id;if(this._cancelPreview(),t)return;let i=new AbortController;this._previewRequest=i;let s=()=>this._previewRequest===i&&!i.signal.aborted;this._preview=e.id,this._previewText=this.appState.read(`report-preview:${e.id}`)??"",this._previewLoading=this.appState.read(`report-preview:${e.id}`)===void 0?e.id:null;try{await this.appState.load(`report-preview:${e.id}`,"report preview",async o=>{let n=await $(`/api/admin/reports/${encodeURIComponent(e.id)}`,{credentials:"same-origin",signal:o});if(!n.ok)throw new Error(`HTTP ${n.status}`);let a=await n.text();return a.slice(0,4e3)+(a.length>4e3?`
|
|
268
268
|
\u2026`:"")},{signal:i.signal,apply:o=>{this._previewText=o}})}catch(o){s()&&o?.name!=="AbortError"&&!this._previewText&&(this._previewText=`Preview unavailable: ${o?.message??o}`)}finally{s()&&(this._previewLoading=null)}}async _setVisible(e,t){this._error=null;try{await this.appState.mutate(()=>pa(e.id,t,this._csrf),["reports","history","scan-sources"]),e.visible=t,this.requestUpdate(),await this._load()}catch(i){this._error=`Couldn't change report visibility: ${String(i?.message??i)}`}}async _upload(e){await Rt(this,e,t=>zi(t,this._csrf),["reports","repo-impact","history","scan-sources"])}async _delete(e){if(globalThis.confirm?.(`Delete \u201C${tt(e.filename)}\u201D? This can't be undone.`)){this._error=null;try{await this.appState.mutate(()=>ha(e.id,this._csrf),["reports",`report-preview:${e.id}`,"repo-impact","history","scan-sources"])}catch(t){this._error=`Delete failed: ${String(t?.message??t)}`}await this._load({preserveError:!0})}}};customElements.define("managed-admin-reports",Ns);var bh=c`<svg class="report-icon" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M8.878.392a1.75 1.75 0 0 0-1.756 0l-5.25 3.045A1.75 1.75 0 0 0 1 4.951v6.098c0 .624.332 1.2.872 1.514l5.25 3.045a1.75 1.75 0 0 0 1.756 0l5.25-3.045c.54-.313.872-.89.872-1.514V4.951c0-.624-.332-1.2-.872-1.514ZM7.875 1.69a.25.25 0 0 1 .25 0l4.63 2.685L8 7.133 3.245 4.375Zm-5.125 4.4 4.5 2.61v5.317l-4.375-2.537a.25.25 0 0 1-.125-.216Zm6 7.927V8.7l4.5-2.61v3.96a.25.25 0 0 1-.125.216Z"/></svg>`,Ps=class extends T{static properties={createRepoId:{attribute:!1},installTooltips:{attribute:!1},localImportSource:{attribute:!1},_query:{state:!0},_visibility:{state:!0},_visibilityBusy:{state:!0},_creating:{state:!0},_data:{state:!0},_locationBundle:{state:!0},_locationOrigin:{state:!0},_locationOriginError:{state:!0},_locationRepo:{state:!0},_locationDirectory:{state:!0},_locationBusy:{state:!0},_error:{state:!0},_busy:{state:!0},_dragOver:{state:!0}};static styles=[x(_a),x(Di),x(N),x(Bi)];constructor(){super(),this._query="",this._visibility="all",this._visibilityBusy=null,this._creating=!1,this._data=null,this._error=null,this._busy=!1,this._locationBundle=null,this._locationOrigin=null,this._locationOriginError=null,this._locationOriginRequest=null,this._locationRepo=null,this._locationDirectory="",this._locationBusy=!1,this._dragOver=!1,this._teardownDrop=null,this._queue=[],this._localImport=new kt(this,"bundle",e=>Pi(this,e,t=>Ti(t,this._csrf),["bundles","reports","repo-impact","history","scan-sources"]))}connectedCallback(){super.connectedCallback(),this._load(),this._teardownDrop=Ct(this,e=>{this._creating||this._upload(e)},e=>{this._dragOver=!this._creating&&e})}disconnectedCallback(){super.disconnectedCallback(),this._teardownDrop?.(),this._closeLocation()}async _load({preserveError:e=!1}={}){e||(this._error=null),await this._loadCollection("bundles","bundles",Oi,t=>{this._data=t,this._locationBundle&&!t.bundles?.some(i=>i.id===this._locationBundle)&&this._closeLocation()})}_showCreate(e){if(!e&&this.createRepoId!=null){document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage-bundles"},bubbles:!0,composed:!0}));return}this._creating=e,this._dragOver=!1,e||this.updateComplete.then(()=>this.renderRoot.querySelector(".create-bundle-action")?.focus())}willUpdate(e){e.has("createRepoId")&&(this._creating=this.createRepoId!=null)}render(){return this._creating?c`<div class="wrap">${U("manage-bundles",this._role,this.allowShare)}<div class="breadcrumb"><button type="button" class="breadcrumb-manage" @click="${()=>document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage"},bubbles:!0,composed:!0}))}">Manage</button> <span class="breadcrumb-separator" aria-hidden="true">›</span> <button type="button" class="breadcrumb-manage" aria-label="Back to bundles" @click="${()=>this._showCreate(!1)}">Bundles</button> <span class="breadcrumb-separator" aria-hidden="true">›</span><h1 class="breadcrumb-current">Create a bundle</h1></div><managed-create-bundle .initialRepoId="${this.createRepoId??null}" .installTooltips="${this.installTooltips}" .createBundle="${this._csrf?(e,t)=>this.appState.mutate(()=>da(e,this._csrf,t),["bundles","bundle-metadata","reports","repo-impact","history","scan-sources"]):void 0}" @bundle-created="${e=>this.dispatchEvent(new CustomEvent("managed-bundle-open",{detail:e.detail,bubbles:!0,composed:!0}))}"></managed-create-bundle></div>`:c`${this._dragOver?c`<div class="dropzone">Drop bundles to upload</div>`:m}<div class="wrap">${U("manage-bundles",this._role,this.allowShare)}<h1 class="sr-only">Bundles</h1><div class="page-intro"><p class="intro">Source bundles for your repositories.</p><div class="bundle-actions">${this._localImport.renderAction()}<button type="button" class="local-import-toggle create-bundle-action" ?disabled="${!this._data}" @click="${()=>this._showCreate(!0)}">Create</button></div></div>${this._localImport.renderPanel(this._busy||!this._csrf)}<section class="drop-card" aria-label="Upload bundles"><span class="drop-icon" aria-hidden="true">${D("upload")}</span><span class="drop-copy"><strong>Upload source bundles</strong><span>Drop source archives anywhere on this page.</span></span> <button type="button" class="drop-browse" ?disabled="${this._busy}" @click="${()=>St(e=>{this._upload(e)})}">${this._busy?"Uploading\u2026":"Browse files"}</button></section>${this._body()}</div>`}_body(){let e=Array.isArray(this._data?.bundles)?this._data.bundles:[],t=this._query.trim().toLocaleLowerCase(),i=e.filter(l=>[l.filename,l.repoFullName,l.repoDirectory,l.kind,l.provenance==="build"?"built":null,l.uploadedByLogin].filter(Boolean).join(" ").toLocaleLowerCase().includes(t)&&(this._visibility==="all"||l.visible!==!1==(this._visibility==="visible"))),s=i.filter(l=>l.repoId==null).length,o=i.reduce((l,d)=>l+(Number.isFinite(d.byteSize)?d.byteSize:0),0),n=`${t||this._visibility!=="all"?`${i.length} of `:""}${e.length} ${e.length===1?"bundle":"bundles"}`,a=Map.groupBy(i,l=>l.repoFullName||"Unattached");return c`<div class="collection-toolbar" role="search"><input type="search" aria-label="Search bundles" placeholder="Search bundles or repositories…" .value="${this._query}" @input="${l=>{this._query=l.target.value}}"> <select aria-label="Bundle visibility" .value="${this._visibility}" @change="${l=>{this._visibility=l.target.value}}"><option value="all">All bundles</option><option value="visible">Visible to teams</option><option value="hidden">Hidden bundles</option></select> <span class="summary result-count" role="status"><span>${this._data==null?"\u2026 bundles":n}</span><span>${this._data==null?"\u2026":Ts(o)}</span> ${this._data==null||s?c`<span class="unassigned">${this._data==null?"\u2026 unattached":`${s} unattached`}</span>`:m}</span></div>${this._error?c`<p class="msg error" role="alert">${this._error}</p>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._data==null?this._error?m:q("Loading bundles\u2026"):i.length>0?c`<div class="bundle-groups">${[...a].toSorted(([l],[d])=>l==="Unattached"?-1:d==="Unattached"?1:l.localeCompare(d)).map(([l,d])=>c`<section class="bundle-group"><div class="bundle-group-head"><strong>${l}</strong><span>${d.length} ${d.length===1?"bundle":"bundles"}</span></div><ul class="bundles">${d.map(u=>this._row(u))}</ul></section>`)}</div>`:c`<div class="empty"><strong>${e.length>0?"No matching bundles":"No bundles uploaded yet"}</strong><p>${e.length>0?"Try a different search or visibility filter.":"Drop source archives here or browse files above."}</p></div>`}</div>`}_row(e){let t=e.visible!==!1,i=e.repoFullName?`${e.repoFullName}${e.repoDirectory?`/${e.repoDirectory}`:""}`:"No repository assigned",s=Number.isFinite(e.uploadedAt)?new Date(e.uploadedAt).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"}):"";return c`<li class="${`bundle-row${t?"":" content-hidden"}`}"><span class="identity"><span class="bundle-icon" aria-hidden="true">${e.kind==="stasis"?c`<img src="./stasis.svg" width="16" height="16" alt="">`:bh}</span> <button type="button" class="filename bundle-open" data-tooltip-truncated data-tooltip="${e.filename}" @click="${()=>this.dispatchEvent(new CustomEvent("managed-bundle-open",{detail:e,bubbles:!0,composed:!0}))}">${e.filename}</button> ${e.provenance==="build"?c`<span class="bundle-provenance" data-tooltip="Generated on this server from the repository">Built</span>`:m} </span><span class="meta bundle-uploader" data-tooltip-truncated data-tooltip="${e.uploadedByLogin?`@${e.uploadedByLogin}`:""}">${e.uploadedByLogin?`@${e.uploadedByLogin}`:""}</span> <span class="meta bundle-date">${s}</span> <span class="meta bundle-size">${Ts(e.byteSize)}</span> <span class="bundle-location" data-tooltip-truncated data-tooltip="${i}">${i}</span> <span class="${`status ${t?"visible":"hidden"}`}">${t?"Visible":"Hidden"}</span> <span class="actions">${e.canChangeRepo===!1?m:c`<button type="button" class="action" aria-label="${`Set location for ${e.filename}`}" data-tooltip="Set repository location" ?disabled="${this._locationBusy}" @click="${()=>this._openLocation(e)}">${D("repo")}</button>`} <button type="button" class="action" aria-label="${`${t?"Hide":"Make visible"} ${e.filename}`}" data-tooltip="${t?"Hide from teams":e.repoId==null?"Assign a repository before publishing":"Make visible to teams"}" ?disabled="${this._visibilityBusy!=null||e.canChangeRepo===!1||!t&&e.repoId==null}" @click="${()=>{this._setVisible(e,!t)}}">${D(t?"hide":"show")}</button> <a class="action" aria-label="${`Download ${e.filename}`}" href="${`/api/admin/bundles/${encodeURIComponent(e.id)}`}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 2v8m-3-3 3 3 3-3M3 11v3h10v-3"/></svg></a><button type="button" class="action danger" aria-label="${`Delete ${e.filename}`}" ?disabled="${e.canChangeRepo===!1}" data-tooltip="${e.canChangeRepo===!1?"Repository access is required to detach or delete this bundle":m}" @click="${()=>this._delete(e)}">${js}</button> </span>${this._locationBundle===e.id?this._locationEditor(e):m}</li>`}async _setVisible(e,t){if(!(this._visibilityBusy!=null||e.canChangeRepo===!1)){this._visibilityBusy=e.id,this._error=null;try{await this.appState.mutate(()=>fa(e.id,t,this._csrf),["bundles","teams","history","scan-sources"]),e.visible=t,this.requestUpdate(),await this._load()}catch(i){this._error=`Couldn't change bundle visibility: ${String(i?.message??i)}`}finally{this._visibilityBusy=null}}}_openLocation(e){this._locationBusy||e.canChangeRepo===!1||(this._closeLocation(),this._locationBundle=e.id,this._locationRepo=e.repoId??null,this._locationDirectory=e.repoDirectory??"",this._error=null,e.kind==="stasis"&&this._loadLocationOrigin(e))}_closeLocation(){this._locationOriginRequest?.abort(),this._locationOriginRequest=null,this._locationBundle=null,this._locationOrigin=null,this._locationOriginError=null}async _loadLocationOrigin(e){this._locationOriginRequest?.abort();let t=new AbortController;this._locationOriginRequest=t,this._locationOrigin=void 0,this._locationOriginError=null;try{let i=await Yn(e.id,{signal:t.signal});if(this._locationOriginRequest!==t)return;i?.repoId!=null&&this._data&&(this._data={...this._data,repos:[...(this._data.repos??[]).filter(s=>s.repoId!==i.repoId),{repoId:i.repoId,fullName:i.github}]}),this._locationOrigin=typeof i?.github=="string"&&i.github?{github:i.github,directory:typeof i.directory=="string"?i.directory:i.root===!0?"/":null}:null}catch(i){if(this._locationOriginRequest!==t)return;this._locationOrigin=null,i?.name!=="AbortError"&&(this._locationOriginError="Couldn't load the bundle\u2019s suggested location.")}}_locationEditor(e){let t=Array.isArray(this._data?.repos)?this._data.repos:[],i=this._locationOrigin,s=Xe({repo:i})?.toLowerCase(),o=s&&t.find(a=>a.fullName.toLowerCase()===s),n=(a,l,d)=>{let u=c`<span class="ui-hint">metadata: </span><span class="location-metadata-value" data-tooltip-truncated data-tooltip="${a}">${a}</span>`;return d?c`<button type="button" class="location-metadata" aria-label="${`Use ${l} from metadata: ${a}`}" ?disabled="${this._locationBusy}" @click="${d}">${u}</button>`:c`<span class="location-metadata">${u}</span>`};return c`<div class="location-editor"><div class="location-field"><div class="location-field-header"><span class="ui-hint">Repository</span>${i?n(i.github,"repository",o?()=>{this._locationRepo=o.repoId,i.directory!=null&&(this._locationDirectory=i.directory)}:null):m}</div><repository-selector label="Repository for bundle" .options="${ac(t)}" .value="${this._locationRepo}" ?disabled="${this._locationBusy}" @repository-change="${a=>{this._locationRepo=a.detail.value}}"></repository-selector></div><div class="location-field"><div class="location-field-header"><label for="${`bundle-dir-${e.id}`}">Directory (optional)</label>${i?n(i.directory??"Directory not specified","directory",i.directory==null?null:()=>{this._locationDirectory=i.directory}):m}</div><input id="${`bundle-dir-${e.id}`}" type="text" placeholder="Repository root" .value="${this._locationDirectory}" ?disabled="${this._locationBusy}" @input="${a=>{this._locationDirectory=a.target.value}}"></div><div class="location-actions"><button type="button" class="action" ?disabled="${this._locationBusy}" @click="${()=>this._closeLocation()}">Cancel</button><button type="button" class="action" ?disabled="${this._locationBusy}" @click="${()=>{this._saveLocation(e)}}">Save</button></div>${this._locationOriginError?c`<p class="location-origin" role="status">${this._locationOriginError} <button type="button" class="origin-retry" @click="${()=>{this._loadLocationOrigin(e)}}">Retry</button></p>`:m}</div>`}async _saveLocation(e){if(!(this._locationBusy||e.canChangeRepo===!1)){this._locationBusy=!0,this._error=null;try{await this.appState.mutate(()=>ga(e.id,this._locationRepo,this._locationDirectory.trim(),this._csrf),["bundles","teams","repo-impact","history","scan-sources"]),this._closeLocation(),await this._load({preserveError:!0})}catch(t){this._error=`Couldn't set bundle location: ${String(t?.message??t)}`}finally{this._locationBusy=!1}}}async _upload(e){await Rt(this,e,t=>Ti(t,this._csrf),["bundles","bundle-metadata","reports","repo-impact","history","scan-sources"])}async _delete(e){if(globalThis.confirm?.(`Delete \u201C${e.filename}\u201D? Linked reports will keep their pending link.`)){this._error=null;try{await this.appState.mutate(()=>ma(e.id,this._csrf),["bundles","bundle-metadata","reports","repo-impact","history","scan-sources"])}catch(t){this._error=`Delete failed: ${String(t?.message??t)}`}await this._load({preserveError:!0})}}};customElements.define("managed-admin-bundles",Ps);var Bs=class extends T{static properties={selection:{attribute:!1},_source:{state:!0},_error:{state:!0}};static styles=x(N);constructor(){super(),this._loadModels=(e,t)=>this.appState.load("models","scan models",i=>ot(i,$),{signal:e,apply:t}),this._source=null,this._error=null,this._loadReportSources=(e,t)=>this.appState.load("scan-sources","scan report inputs",async i=>{let[s,o]=await Promise.all([$("/api/admin/reports",{signal:i,credentials:"same-origin"}),$("/api/admin/scan-results",{signal:i,credentials:"same-origin"})]);if(!s.ok)throw new Error(`Reports: HTTP ${s.status}`);if(!o.ok&&o.status!==404)throw new Error(`Scan results: HTTP ${o.status}`);let n=await s.json();return n.reports=await Promise.all((n.reports??[]).filter(a=>a.visible&&a.repoId!=null).map(async a=>{let l=await $(`/api/admin/reports/${encodeURIComponent(a.id)}`,{signal:i,credentials:"same-origin"});if(!l.ok)throw new Error(`Report ${tt(a.filename)}: HTTP ${l.status}`);return{...a,content:await l.text()}})),Zl(n,o.ok?await o.json():{bundles:[],results:[]})},{signal:e,apply:t})}connectedCallback(){super.connectedCallback(),this._load()}async _load(){this._error=null,await this._loadCollection("bundles","bundles",Oi,e=>{this._source=Ul(e)})}render(){return c`<div class="wrap">${U("manage-scans",this._role,this.allowShare)} ${this._error?c`<p class="msg error" role="alert">Couldn’t load scan sources: ${this._error} <button type="button" class="btn" @click="${()=>{this._load()}}">Retry</button></p>`:m}<deepview-scan-page hide-heading .selection="${this.selection}" .source="${this._source}" .sourceLoading="${this._loading&&this._source==null}" .loadBundle="${Fl}" .loadModels="${this._loadModels}" .loadReportSources="${this._loadReportSources}" .createBundleHref="${e=>Number.isSafeInteger(e)&&e>0?Wl({view:"manage-bundles",createRepoId:e}):null}"></deepview-scan-page></div>`}};customElements.define("managed-admin-scans",Bs);var Ds=class extends T{static properties={_data:{state:!0},_error:{state:!0},_busy:{state:!0},_renamingId:{state:!0},_repoChoices:{state:!0},_memberChoices:{state:!0}};static styles=[x(xa),x(N)];constructor(){super(),this._data=null,this._error=null,this._busy=!1,this._renamingId=null,this._repoChoices=new Map,this._memberChoices=new Map}connectedCallback(){super.connectedCallback(),this._load()}async _load({preserveError:e=!1}={}){e||(this._error=null),await this._loadCollection("teams","teams",Ni,t=>{this._data=t})}async _do(e){if(!this._busy){this._busy=!0,this._error=null;try{await this.appState.mutate(e,["teams","users","reports","history"])}catch(t){this._error=String(t?.message??t)}finally{this._busy=!1,await this._load({preserveError:!0})}}}render(){return c`<div class="wrap">${U("manage-teams",this._role,this.allowShare)}<h1 class="sr-only">Teams</h1><div class="page-intro"><p class="intro">Manage repository and finding access for each team.</p><span class="result-count">${this._data?.teams?.length??"\u2026"} teams</span></div><div class="create-team"><label class="sr-only" for="new-team-name">New team</label> <input id="new-team-name" class="new-name" type="text" placeholder="Team name" maxlength="100" ?disabled="${this._busy}" @keydown="${e=>{e.key==="Enter"&&this._create()}}"> <button class="btn primary" ?disabled="${this._busy}" @click="${()=>this._create()}">${As} Create team</button><p class="access-note">All members can view standard findings. Set dependencies and security access per member.</p></div><div class="manage-list" aria-busy="${this._loading}">${this._body()}</div></div>`}_body(){if(this._error!=null&&this._data==null)return c`<p class="msg error">Couldn't load teams: ${this._error}</p>`;if(this._data==null)return q("Loading teams\u2026");let e=Array.isArray(this._data.teams)?this._data.teams:[];return c`${this._error==null?m:c`<p class="msg error">${this._error}</p>`} ${e.length===0?c`<p class="msg">No teams yet. Create one above.</p>`:e.map(t=>this._team(t))}`}_team(e){return c`<section class="team" aria-label="${e.name}"><div class="team-head"><span class="team-icon" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="5" r="2.5"/><path d="M1.5 13v-1c0-2 1.8-3.5 4.5-3.5s4.5 1.5 4.5 3.5v1M11 2.5a2.5 2.5 0 0 1 0 5M12 9c1.7.5 2.5 1.5 2.5 3v1"/></svg></span>${this._renamingId===e.id?c`<input class="rename-input" type="text" .value="${e.name}" maxlength="100" aria-label="Team name" @keydown="${t=>this._renameKey(t,e)}"> <button class="btn" ?disabled="${this._busy}" @click="${t=>this._saveRename(e,t)}">Save</button> <button class="btn" @click="${()=>{this._renamingId=null}}">Cancel</button>`:c`<h2 class="team-name">${e.name}</h2>${e.hidden?c`<span class="muted ui-hint">Hidden</span>`:m} <span class="team-actions"><button class="btn" aria-label="${`${e.hidden?"Restore":"Hide"} ${e.name}`}" ?disabled="${this._busy}" @click="${()=>this._do(()=>ie("/api/admin/teams/set-hidden",this._csrf,{teamId:e.id,hidden:!e.hidden}))}">${e.hidden?"Restore":"Hide"}</button> <button class="icon-btn" aria-label="${`Rename ${e.name}`}" ?disabled="${this._busy}" @click="${()=>{this._renamingId=e.id}}">${mh}</button> <button class="icon-btn danger" aria-label="${`Delete ${e.name}`}" ?disabled="${this._busy}" @click="${()=>this._deleteTeam(e)}">${js}</button></span>`}</div>${e.hidden?c`<p class="team-hidden-note muted ui-hint">Hidden from everyone's sidebar. Access grants and public links are disabled until this team is restored.</p>`:m}<div class="team-body"><div class="sub"><h3 class="sub-title">Repositories <span class="count">${e.repos.length}</span></h3>${e.repos.length===0?c`<p class="muted ui-hint">No repositories linked.</p>`:c`<ul class="links">${e.repos.map(t=>this._repoRow(e,t))}</ul>`} ${this._addRepoRow(e)}</div><div class="sub"><h3 class="sub-title">Members <span class="count">${e.members.length}</span></h3>${e.members.length===0?c`<p class="muted ui-hint">No members.</p>`:c`<ul class="links">${e.members.map(t=>this._memberRow(e,t))}</ul>`} ${this._addMemberRow(e)}</div></div></section>`}_repoRow(e,t){return c`<li class="repo-row">${nc} <span class="repo-copy"><span class="ln">${t.fullName}</span>${t.path?c`<span class="path">/${t.path.replace(/^\/+/u,"")}</span>`:m}</span> <button class="icon-btn danger" aria-label="${`Remove ${t.fullName}${t.path?`/${t.path}`:""} from ${e.name}`}" ?disabled="${this._busy}" @click="${()=>this._do(()=>ie("/api/admin/teams/remove-repo",this._csrf,{teamId:e.id,repoId:t.repoId,path:t.path??null}))}">${rc}</button></li>`}_addRepoRow(e){let t=Array.isArray(this._data.repos)?this._data.repos:[];return t.length===0?c`<p class="muted ui-hint">No selected repositories to link — pick some on “Manage repositories”.</p>`:c`<div class="add-row"><repository-selector class="add-repo-sel" label="${`Repository to add to ${e.name}`}" placeholder="Add repository…" ?disabled="${this._busy}" .options="${t.map(i=>({value:i.repoId,label:i.fullName}))}" .value="${this._repoChoices.get(e.id)??null}" @repository-change="${i=>{this._repoChoices=new Map(this._repoChoices).set(e.id,i.detail.value)}}"></repository-selector><input class="add-repo-path" type="text" placeholder="Path (optional)" aria-label="${`Repository path in ${e.name} (optional)`}" maxlength="500" ?disabled="${this._busy}"> <button class="btn" aria-label="${`Add repository to ${e.name}`}" ?disabled="${this._busy||!this._repoChoices.has(e.id)}" @click="${i=>this._addRepo(e,i)}">${As} Add</button></div>`}_memberRow(e,t){let i=Array.isArray(this._data.permissions)?this._data.permissions:[],s=this._data.users?.some(o=>o.id===t.userId&&Ge(o.role,"manage"));return c`<li class="member-row"><span class="member">${oc(t.userId,t.login)}<span class="ln">${t.login}</span></span> <span class="perms">${i.map(o=>c`<label class="perm"><input type="checkbox" .checked="${s||t[o]===!0}" ?disabled="${this._busy||s}" aria-label="${`${Br[o]??o} access for ${t.login} in ${e.name}`}" @change="${n=>this._togglePerm(e,t,o,n.target.checked)}"> ${Br[o]??o}</label>`)} </span><button class="icon-btn danger" aria-label="${`Remove ${t.login} from ${e.name}`}" ?disabled="${this._busy}" @click="${()=>this._do(()=>ie("/api/admin/teams/remove-member",this._csrf,{teamId:e.id,userId:t.userId}))}">${rc}</button></li>`}_addMemberRow(e){let t=Array.isArray(this._data.users)?this._data.users:[],i=new Set(e.members.map(s=>s.userId));return c`<div class="add-row"><user-selector class="add-member-sel" label="${`Member to add to ${e.name}`}" placeholder="Add member…" ?disabled="${this._busy}" .users="${t.map(s=>({...s,disabled:i.has(s.id),detail:i.has(s.id)?"Member":""}))}" .value="${this._memberChoices.get(e.id)??null}" @user-change="${s=>{this._memberChoices=new Map(this._memberChoices).set(e.id,s.detail.value)}}"></user-selector><button class="btn" aria-label="${`Add member to ${e.name}`}" ?disabled="${this._busy||!this._memberChoices.has(e.id)||i.has(this._memberChoices.get(e.id))}" @click="${()=>this._addMember(e)}">${As} Add</button></div>`}_create(){let e=this.renderRoot.querySelector(".new-name"),t=e?.value.trim();t&&this._do(async()=>{await ie("/api/admin/teams",this._csrf,{name:t}),e&&(e.value="")})}_deleteTeam(e){globalThis.confirm?.(`Delete team \u201C${e.name}\u201D? Its repo + member links are removed.`)&&this._do(()=>ie("/api/admin/teams/delete",this._csrf,{teamId:e.id}))}_renameKey(e,t){e.key==="Enter"?this._saveRename(t,e):e.key==="Escape"&&(this._renamingId=null)}_saveRename(e,t){if(this._busy)return;let i=t.target.closest(".team-head")?.querySelector(".rename-input")?.value.trim()??"";this._renamingId=null,!(i===""||i===e.name)&&this._do(()=>ie("/api/admin/teams/rename",this._csrf,{teamId:e.id,name:i}))}_addRepo(e,t){let i=t.target.closest(".add-row"),s=this._repoChoices.get(e.id);if(!Number.isSafeInteger(s)||s<=0)return;let o=i?.querySelector(".add-repo-path")?.value??"";this._do(async()=>{await ie("/api/admin/teams/set-repo",this._csrf,{teamId:e.id,repoId:s,path:o});let n=new Map(this._repoChoices);n.delete(e.id),this._repoChoices=n;let a=i?.querySelector(".add-repo-path");a&&(a.value="")})}_addMember(e){let t=this._memberChoices.get(e.id);!t||e.members.some(i=>i.userId===t)||this._do(async()=>{await ie("/api/admin/teams/set-member",this._csrf,{teamId:e.id,userId:t});let i=new Map(this._memberChoices);i.delete(e.id),this._memberChoices=i})}_togglePerm(e,t,i,s){if(this._data.users?.some(n=>n.id===t.userId&&Ge(n.role,"manage")))return;let o={};for(let n of this._data.permissions??[])o[n]=t[n]===!0;o[i]=s,this._do(()=>ie("/api/admin/teams/set-member",this._csrf,{teamId:e.id,userId:t.userId,...o}))}};customElements.define("managed-admin-teams",Ds);S();B();var Er=`.link-team{margin-top:1.5rem}.link-team h2{margin:0 0 .5rem;font-size:1rem;font-weight:600}.link-table{overflow-x:auto}table{width:100%;border-collapse:collapse;text-align:left;font-size:.8rem}th{color:var(--muted);font-weight:500}th,td{padding:.6rem .65rem;border-bottom:1px solid var(--border);white-space:nowrap}th:first-child,td:first-child{padding-left:0}th:last-child,td:last-child{padding-right:0;text-align:right}
|
|
269
269
|
`;async function Ah(r){let e=await $("/api/admin/links",{signal:r,credentials:"same-origin"});if(!e.ok)throw new Error(`HTTP ${e.status}`);let t=await e.json();if(!Array.isArray(t?.shares))throw new Error("No public links returned");return t}var Ws=class extends T{static properties={_data:{state:!0},_error:{state:!0}};static styles=[x(N),x(Er)];constructor(){super(),this._data=null,this._error=null}connectedCallback(){super.connectedCallback(),this._load()}async _load(){this._error=null,await this._loadCollection("links","public links",Ah,e=>{this._data=e})}async _edit(e){let{openManagedShareDialog:t}=await Promise.resolve().then(()=>(Gs(),Vs));await t({id:e.teamId,name:e.teamName},e.id,this.session),this.isConnected&&await this._load()}_groups(){let e=new Map;for(let t of this._data?.shares??[])e.has(t.teamId)||e.set(t.teamId,{name:t.teamName,links:[]}),e.get(t.teamId).links.push(t);return[...e.values()]}_body(){return this._data==null?this._error?c`<p class="msg error">Couldn't load public links: ${this._error}</p>`:q("Loading public links\u2026"):this._data.shares.length===0?c`<p class="msg">No public links. Create one with the share button beside a workspace in the sidebar.</p>`:this._groups().map(e=>c`<section class="link-team" aria-label="${e.name}"><h2>${e.name}</h2><div class="link-table"><table><thead><tr><th>Link</th><th>Created by</th><th>Created</th><th>Security</th><th>Dependencies</th><th><span class="sr-only">Actions</span></th></tr></thead><tbody>${e.links.map(t=>c`<tr><td><span data-tooltip="${t.id}">${t.id.slice(0,8)}</span></td><td>${t.createdBy}</td><td>${new Date(t.createdAt).toLocaleString()}</td><td>${t.permissions.security?"On":"Off"}</td><td>${t.permissions.dependencies?"On":"Off"}</td><td><button class="btn" aria-label="${`Edit public link ${t.id.slice(0,8)} for ${e.name}`}" @click="${()=>this._edit(t)}">Edit</button></td></tr>`)}</tbody></table></div></section>`)}render(){return c`<div class="wrap">${U("manage-links",this._role,this.allowShare)}<h1 class="sr-only">Public links</h1><div class="page-intro"><p class="intro">Manage public links and the findings each link can show.</p><span class="result-count">${this._data?.shares.length??"\u2026"} links</span></div>${this._loading&&this._data?c`<span class="sr-only" role="status">Refreshing public links…</span>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._body()}</div></div>`}};customElements.define("managed-admin-links",Ws);S();B();var Mh="/api/admin/deduplication";async function Ks(r="",e={}){let t=await $(`${Mh}${r}`,{credentials:"same-origin",...e}),i=await t.json();if(!t.ok){let s={"storage-encryption-required":"Configure MANAGED_STORAGE_ENCRYPTION_KEY on the server to import encrypted link reports.","invalid-link-report":'Choose a link report containing arrays of finding IDs, such as [["id1", "id2"]].',"too-large":"This link report exceeds the server upload limit."};throw new Error(s[i?.error]??`HTTP ${t.status}`)}return i}var Zs=class extends T{static properties={_data:{state:!0},_error:{state:!0},_busy:{state:!0},_dragOver:{state:!0}};static styles=[x(N),x(ur),x(Er)];constructor(){super(),this._data=null,this._error=null,this._busy=!1,this._dragOver=!1,this._queue=[]}connectedCallback(){super.connectedCallback(),this._load(),this._teardownDrop=Ct(this,e=>{this._upload(e)},e=>{this._dragOver=e})}disconnectedCallback(){this._teardownDrop?.(),super.disconnectedCallback()}async _load({preserveError:e=!1}={}){e||(this._error=null),await this._loadCollection("deduplication","deduplication reports",t=>Ks("",{signal:t}),t=>{this._data=t})}_upload(e){if(!(!this._csrf||this._role!=="admin"))return Rt(this,e,t=>Ks("",{method:"POST",headers:{"content-type":"application/json","x-report-filename":encodeURIComponent(t.name),"x-csrf-token":this._csrf},body:t}),["deduplication","reports","teams"])}async _toggle(e){if(!(this._busy||!this._csrf)){this._busy=!0,this._error=null;try{await this.appState.mutate(()=>Ks(`/${encodeURIComponent(e.id)}`,{method:"PATCH",headers:{"content-type":"application/json","x-csrf-token":this._csrf},body:JSON.stringify({enabled:!e.enabled})}),["deduplication","reports","teams"])}catch(t){this._error=String(t?.message??t)}finally{this._busy=!1,await this._load({preserveError:!0});let t=this._queue.splice(0);t.length>0&&this._upload(t)}}}_view(e){document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage-deduplication",linkId:e.id},bubbles:!0,composed:!0}))}_linkReports(){document.dispatchEvent(new CustomEvent("managed-admin-navigate",{detail:{view:"manage-scans",scanMode:"link"},bubbles:!0,composed:!0}))}render(){let e=this._data?.reports??[];return c`${this._dragOver?c`<div class="dropzone">Drop link reports to import</div>`:m}<div class="wrap">${U("manage-deduplication",this._role,this.allowShare)}<h1 class="sr-only">Deduplication</h1><div class="page-intro"><p class="intro">Link duplicate findings across all teams.</p><span class="result-count">${this._data?e.length:"\u2026"} reports</span><button type="button" class="btn" @click="${()=>this._linkReports()}">Link reports</button></div><div class="drop-card"><span class="drop-icon" aria-hidden="true">${D("upload")}</span><span class="drop-copy"><strong>Import link reports</strong><span>Drop *.link.json files anywhere on this page.</span></span><button type="button" class="drop-browse" ?disabled="${this._busy||!this._csrf}" @click="${()=>St(t=>{this._upload(t)})}">${this._busy?"Saving\u2026":"Browse files"}</button></div>${this._error?c`<p class="msg error" role="alert">${this._error}</p>`:m}<div class="manage-list" aria-busy="${this._loading}">${this._data===null?this._error?m:q("Loading deduplication reports\u2026"):e.length===0?c`<div class="empty"><strong>No link reports imported yet</strong><p>Each row in a link report lists IDs for the same finding.</p></div>`:c`<div class="link-table"><table><thead><tr><th>Report</th><th>Groups</th><th>Finding IDs</th><th>Imported by</th><th>Imported</th><th>Status</th><th><span class="sr-only">Actions</span></th></tr></thead><tbody>${e.map(t=>c`<tr><td>${t.filename}</td><td>${t.groupCount}</td><td>${t.findingCount}</td><td>${t.uploadedByLogin??"Removed user"}</td><td>${new Date(t.uploadedAt).toLocaleDateString()}</td><td>${t.enabled?"Enabled":"Disabled"}</td><td><button type="button" class="btn" aria-label="${`View ${t.filename}`}" @click="${()=>this._view(t)}">View</button> <button type="button" class="btn" ?disabled="${this._busy}" aria-label="${`${t.enabled?"Disable":"Enable"} ${t.filename}`}" @click="${()=>{this._toggle(t)}}">${t.enabled?"Disable":"Enable"}</button></td></tr>`)}</tbody></table></div>`}</div></div>`}};customElements.define("managed-admin-deduplication",Zs);B();ae();at();B();function Ih(r,e){return new Promise(t=>{if(e.aborted){t();return}let i=()=>{clearTimeout(s),e.removeEventListener("abort",i),t()},s=setTimeout(i,r);e.addEventListener("abort",i,{once:!0})})}async function Lh(r,{signal:e,onUpdate:t,onTeams:i,onClose:s,reportId:o=null}){if(Ee())return;let n=1e3,a=async(l,d,u)=>{if(u.throwIfAborted(),l==="close")return await s(),!1;if(l==="triage"||l==="teams"){let p=null;if(l==="teams")try{let h=JSON.parse(d);typeof h?.revision=="string"&&(p=h.revision)}catch{}if(await(l==="teams"?i?.(u,p):t(u))===!1)throw new Error("Team refresh failed");u.throwIfAborted(),n=1e3}return!0};for(;!e.aborted;){let l=new AbortController,d=()=>l.abort();e.addEventListener("abort",d,{once:!0});let u,p,h=()=>{clearTimeout(p),p=setTimeout(d,45e3)};try{h();let f=o===null?"":`?reportId=${encodeURIComponent(o)}`,b=await $(r?`/api/teams/${encodeURIComponent(r)}/feed${f}`:"/api/teams/feed",{credentials:"same-origin",headers:{accept:"text/event-stream"},signal:l.signal});if([401,403,404].includes(b.status)){await b.body?.cancel(),e.aborted||await s();return}if(!b.ok||!b.headers.get("content-type")?.startsWith("text/event-stream"))throw await b.body?.cancel(),new Error("Team feed unavailable");if(u=b.body.getReader(),await zh(u,e,h,(y,g)=>a(y,g,l.signal)))return}catch{}finally{clearTimeout(p),d(),await u?.cancel().catch(()=>{}),e.removeEventListener("abort",d)}await Ih(n,e),n=Math.min(n*2,3e4)}}async function zh(r,e,t,i){let s=new TextDecoder,o="";for(;!e.aborted;){let{done:n,value:a}=await r.read();if(n)return!1;if(t(),o=(o+s.decode(a,{stream:!0})).replaceAll(`\r
|