@serve.zone/dcrouter 5.5.0 → 6.2.0

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.
@@ -29066,7 +29066,7 @@ html\`&lt;dees-button&gt;Click me&lt;/dees-button&gt;\`</code></pre>
29066
29066
  <h1>Markdown Preview</h1>
29067
29067
  <p>Content will appear here when markdown is parsed.</p>
29068
29068
  </div>
29069
- `}async firstUpdated(n){await super.firstUpdated(n),this.outlet=this.shadowRoot.querySelector(".outlet")}async updateHtmlText(n){await this.updateComplete,this.outlet||(this.outlet=this.shadowRoot.querySelector(".outlet")),this.outlet.innerHTML=n}static{yUt(i,a)}};return s=i})()});var $yt=v(()=>{Lyt()});var Ayt=v(()=>{Lj()});var Dyt=v(()=>{Aj()});var Eyt=v(()=>{byt();vyt();xyt();wyt();Myt();kyt();$yt();Ayt();Dyt()});var Pyt=v(()=>{});var Nyt=v(()=>{Pyt()});var Iyt=v(()=>{ue()});var Fyt=v(()=>{Iyt()});var Oyt=v(()=>{fi();qe();yft();Aft();Wft();rmt();$mt();Emt();qgt();Abt();qvt();Qvt();Sw();Gxt();dyt();Eyt();Nyt();Fyt()});var Ryt,Byt=v(()=>{Ryt={name:"@design.estate/dees-catalog",version:"3.42.0",description:"A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."}});var bo={};Je(bo,{CanvasPool:()=>El,DeesActionbar:()=>smt,DeesAppui:()=>cft,DeesAppuiActivitylog:()=>cpt,DeesAppuiBar:()=>Spt,DeesAppuiBottombar:()=>_pt,DeesAppuiMaincontent:()=>lft,DeesAppuiMainmenu:()=>tft,DeesAppuiProfileDropdown:()=>zpt,DeesAppuiSecondarymenu:()=>rft,DeesAppuiTabs:()=>oft,DeesAudioViewer:()=>Obt,DeesBadge:()=>dmt,DeesButton:()=>Z9t,DeesButtonExit:()=>zft,DeesButtonGroup:()=>_ft,DeesChartArea:()=>Rft,DeesChartLog:()=>Vft,DeesChips:()=>Ugt,DeesContextmenu:()=>jt,DeesDashboardgrid:()=>dbt,DeesDataviewCodebox:()=>Zft,DeesDataviewStatusobject:()=>emt,DeesForm:()=>W9t,DeesFormSubmit:()=>Ry,DeesFormattingMenu:()=>nw,DeesHeading:()=>gbt,DeesHint:()=>gmt,DeesIcon:()=>ipt,DeesImageViewer:()=>Pbt,DeesInputBase:()=>Ze,DeesInputCheckbox:()=>Ly,DeesInputCode:()=>Ey,DeesInputDatepicker:()=>Py,DeesInputDropdown:()=>By,DeesInputFileupload:()=>qy,DeesInputIban:()=>Uy,DeesInputList:()=>Hmt,DeesInputMultitoggle:()=>Wy,DeesInputPhone:()=>Yy,DeesInputProfilePicture:()=>Hgt,DeesInputQuantitySelector:()=>Iy,DeesInputRadiogroup:()=>Fy,DeesInputRichtext:()=>egt,DeesInputTags:()=>ogt,DeesInputText:()=>Ny,DeesInputToggle:()=>Zy,DeesInputTypelist:()=>Xy,DeesInputWysiwyg:()=>DV,DeesLabel:()=>Vpt,DeesMobilenavigation:()=>bft,DeesModal:()=>s1,DeesPagination:()=>Mbt,DeesPanel:()=>Ept,DeesPdf:()=>avt,DeesPdfPreview:()=>cvt,DeesPdfViewer:()=>Ybt,DeesPreview:()=>Kbt,DeesProgressbar:()=>Mmt,DeesSearchbar:()=>Kxt,DeesShoppingProductcard:()=>t9t,DeesSimpleAppDash:()=>Oxt,DeesSimpleLogin:()=>jxt,DeesSlashMenu:()=>rw,DeesSpeechbubble:()=>Gvt,DeesSpinner:()=>Smt,DeesStatsGrid:()=>X9t,DeesStepper:()=>_bt,DeesTable:()=>Ky,DeesTheme:()=>iyt,DeesTileAudio:()=>zvt,DeesTileBase:()=>ga,DeesTileFolder:()=>Rvt,DeesTileImage:()=>vvt,DeesTileNote:()=>Evt,DeesTilePdf:()=>dw,DeesTileVideo:()=>_vt,DeesToast:()=>Ot,DeesUpdater:()=>kw,DeesVideoViewer:()=>qbt,DeesWindowControls:()=>Mpt,DeesWindowLayer:()=>mi,DeesWorkspace:()=>myt,DeesWorkspaceBottombar:()=>pyt,DeesWorkspaceDiffEditor:()=>fyt,DeesWorkspaceFiletree:()=>hyt,DeesWorkspaceMarkdown:()=>zyt,DeesWorkspaceMarkdownoutlet:()=>_yt,DeesWorkspaceMonaco:()=>jpt,DeesWorkspaceTerminal:()=>yj,DeesWorkspaceTerminalPreview:()=>uyt,DeesWysiwygBlock:()=>Pgt,PROGRAMMING_LANGUAGES:()=>_8,PdfManager:()=>Br,PerformanceMonitor:()=>Pl,TerminalTabManager:()=>ed,TypeScriptIntelliSenseManager:()=>sd,ViewRegistry:()=>z8,WebContainerEnvironment:()=>d4,WysiwygBlockOperations:()=>L8,WysiwygBlocks:()=>A2,WysiwygConverters:()=>wi,WysiwygDragDropHandler:()=>V8,WysiwygFormatting:()=>Is,WysiwygHistory:()=>j8,WysiwygInputHandler:()=>H8,WysiwygKeyboardHandler:()=>q8,WysiwygModalManager:()=>B8,WysiwygSelection:()=>Re,WysiwygShortcuts:()=>q1,ZIndexRegistry:()=>xf,colors:()=>H0,commitinfo:()=>Ryt,componentZIndex:()=>pBt,debounce:()=>Fjt,formatFileSize:()=>Rjt,getZIndex:()=>uBt,icons:()=>Cy,isInViewport:()=>Bjt,registerAllBlockHandlers:()=>Lgt,themeDefaultStyles:()=>ke,themeDefaults:()=>Zn,throttle:()=>Ojt,tileBaseStyles:()=>J2,wysiwygStyles:()=>SV,zIndexLayers:()=>a2,zIndexRegistry:()=>c1});var p4=v(()=>{Oyt();bi();Byt()});ue();p4();var N1=rt;Tc();var Hyt={};var qyt={};var vo=new N1.plugins.smartstate.Smartstate,zi=await vo.getStatePart("login",{identity:null,isLoggedIn:!1},"persistent"),o2=await vo.getStatePart("stats",{serverStats:null,emailStats:null,dnsStats:null,securityMetrics:null,lastUpdated:0,isLoading:!1,error:null},"soft"),Vr=await vo.getStatePart("config",{config:null,isLoading:!1,error:null}),wUt=()=>{let t=typeof window<"u"?window.location.pathname:"/",e=["overview","network","emails","logs","configuration","security","certificates"],i=t.split("/").filter(Boolean)[0];return e.includes(i)?i:"overview"},Da=await vo.getStatePart("ui",{activeView:wUt(),sidebarCollapsed:!1,autoRefresh:!0,refreshInterval:1e3,theme:"light"}),Tw=await vo.getStatePart("logs",{recentLogs:[],isStreaming:!1,filters:{}},"soft"),qr=await vo.getStatePart("network",{connections:[],connectionsByIP:{},throughputRate:{bytesInPerSecond:0,bytesOutPerSecond:0},totalBytes:{in:0,out:0},topIPs:[],throughputByIP:[],throughputHistory:[],requestsPerSecond:0,requestsTotal:0,lastUpdated:0,isLoading:!1,error:null},"soft"),T1=await vo.getStatePart("emailOps",{currentView:"queued",queuedEmails:[],sentEmails:[],failedEmails:[],securityIncidents:[],bounceRecords:[],suppressionList:[],selectedEmailId:null,isLoading:!1,error:null,lastUpdated:0},"soft"),ar=await vo.getStatePart("certificates",{certificates:[],summary:{total:0,valid:0,expiring:0,expired:0,failed:0,unknown:0},isLoading:!1,error:null,lastUpdated:0},"soft"),xa=()=>({identity:zi.getState().identity}),Vyt=zi.createAction(async(t,e)=>{let a=new N1.plugins.typedrequest.TypedRequest("/typedrequest","adminLoginWithUsernameAndPassword");try{let i=await a.fire({username:e.username,password:e.password});return i.identity?{identity:i.identity,isLoggedIn:!0}:t.getState()}catch(i){return console.error("Login failed:",i),t.getState()}}),Pj=zi.createAction(async t=>{let e=xa();if(!e.identity)return t.getState();let a=new N1.plugins.typedrequest.TypedRequest("/typedrequest","adminLogout");try{await a.fire({identity:e.identity})}catch(i){console.error("Logout error:",i)}return{identity:null,isLoggedIn:!1}}),Vl=o2.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCombinedMetrics").fire({identity:e.identity,sections:{server:!0,email:!0,dns:!0,security:!0,network:!1}});return{serverStats:r.metrics.server||a.serverStats,emailStats:r.metrics.email||a.emailStats,dnsStats:r.metrics.dns||a.dnsStats,securityMetrics:r.metrics.security||a.securityMetrics,lastUpdated:Date.now(),isLoading:!1,error:null}}catch(i){return{...a,isLoading:!1,error:i.message||"Failed to fetch statistics"}}}),jl=Vr.createAction(async t=>{let e=xa(),a=t.getState();try{return{config:(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getConfiguration").fire({identity:e.identity})).config,isLoading:!1,error:null}}catch(i){return{...a,isLoading:!1,error:i.message||"Failed to fetch configuration"}}}),jyt=Tw.createAction(async(t,e)=>{let a=xa(),r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getRecentLogs").fire({identity:a.identity,limit:e.limit||100,level:e.level,category:e.category});return{...t.getState(),recentLogs:r.logs}}),f92=Da.createAction(async t=>{let e=t.getState();return{...e,autoRefresh:!e.autoRefresh}}),m92=Da.createAction(async(t,e)=>{let a=t.getState();return e==="network"&&a.activeView!=="network"&&setTimeout(()=>{qr.dispatchAction(Nj,null)},100),e==="certificates"&&a.activeView!=="certificates"&&setTimeout(()=>{ar.dispatchAction(ql,null)},100),{...a,activeView:e}}),Nj=qr.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getActiveConnections").fire({identity:e.identity}),n=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getNetworkStats").fire({identity:e.identity}),o={};return n.connectionsByIP&&Array.isArray(n.connectionsByIP)?n.connectionsByIP.forEach(d=>{o[d.ip]=d.count}):r.connections.forEach(d=>{let c=d.remoteAddress;o[c]=(o[c]||0)+1}),{connections:r.connections,connectionsByIP:o,throughputRate:n.throughputRate||{bytesInPerSecond:0,bytesOutPerSecond:0},totalBytes:n.totalDataTransferred?{in:n.totalDataTransferred.bytesIn,out:n.totalDataTransferred.bytesOut}:{in:0,out:0},topIPs:n.topIPs||[],throughputByIP:n.throughputByIP||[],throughputHistory:n.throughputHistory||[],requestsPerSecond:n.requestsPerSecond||0,requestsTotal:n.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null}}catch(i){return console.error("Failed to fetch network stats:",i),{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch network stats"}}}),g92=T1.createAction(async(t,e)=>({...t.getState(),currentView:e})),Ij=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getQueuedEmails").fire({identity:e.identity,status:"pending",limit:100});return{...a,queuedEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch queued emails"}}}),Uyt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getSentEmails").fire({identity:e.identity,limit:100});return{...a,sentEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch sent emails"}}}),Fj=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getFailedEmails").fire({identity:e.identity,limit:100});return{...a,failedEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch failed emails"}}}),Wyt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getSecurityIncidents").fire({identity:e.identity,limit:100});return{...a,securityIncidents:r.incidents,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch security incidents"}}}),MUt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getBounceRecords").fire({identity:e.identity,limit:100});return{...a,bounceRecords:r.records,suppressionList:r.suppressionList,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch bounce records"}}}),Gyt=T1.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","resendEmail").fire({identity:a.identity,emailId:e})).success&&(await T1.dispatchAction(Fj,null),await T1.dispatchAction(Ij,null)),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to resend email"}}}),b92=T1.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","removeFromSuppressionList").fire({identity:a.identity,email:e})).success&&await T1.dispatchAction(MUt,null),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to remove from suppression list"}}}),ql=ar.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCertificateOverview").fire({identity:e.identity});return{certificates:r.certificates,summary:r.summary,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch certificate overview"}}}),Yyt=ar.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return await new N1.plugins.typedrequest.TypedRequest("/typedrequest","reprovisionCertificate").fire({identity:a.identity,routeName:e}),await ar.dispatchAction(ql,null),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to reprovision certificate"}}});async function zUt(){let t=xa(),e=Da.getState().activeView;try{let i=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCombinedMetrics").fire({identity:t.identity,sections:{server:!0,email:!0,dns:!0,security:!0,network:e==="network"}});if(o2.setState({...o2.getState(),serverStats:i.metrics.server||o2.getState().serverStats,emailStats:i.metrics.email||o2.getState().emailStats,dnsStats:i.metrics.dns||o2.getState().dnsStats,securityMetrics:i.metrics.security||o2.getState().securityMetrics,lastUpdated:Date.now(),isLoading:!1,error:null}),i.metrics.network&&e==="network"){let r=i.metrics.network,s={};r.connectionDetails.forEach(n=>{s[n.remoteAddress]=(s[n.remoteAddress]||0)+1});try{let o=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getActiveConnections").fire({identity:t.identity});qr.setState({...qr.getState(),connections:o.connections,connectionsByIP:s,throughputRate:{bytesInPerSecond:r.totalBandwidth.in,bytesOutPerSecond:r.totalBandwidth.out},totalBytes:r.totalBytes||{in:0,out:0},topIPs:r.topEndpoints.map(d=>({ip:d.endpoint,count:d.requests})),throughputByIP:r.topEndpoints.map(d=>({ip:d.endpoint,in:d.bandwidth?.in||0,out:d.bandwidth?.out||0})),throughputHistory:r.throughputHistory||[],requestsPerSecond:r.requestsPerSecond||0,requestsTotal:r.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null})}catch(n){console.error("Failed to fetch connections:",n),qr.setState({...qr.getState(),connections:[],connectionsByIP:s,throughputRate:{bytesInPerSecond:r.totalBandwidth.in,bytesOutPerSecond:r.totalBandwidth.out},totalBytes:r.totalBytes||{in:0,out:0},topIPs:r.topEndpoints.map(o=>({ip:o.endpoint,count:o.requests})),throughputByIP:r.topEndpoints.map(o=>({ip:o.endpoint,in:o.bandwidth?.in||0,out:o.bandwidth?.out||0})),throughputHistory:r.throughputHistory||[],requestsPerSecond:r.requestsPerSecond||0,requestsTotal:r.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null})}}if(e==="certificates")try{await ar.dispatchAction(ql,null)}catch(r){console.error("Certificate refresh failed:",r)}}catch(a){console.error("Combined refresh failed:",a)}}var od=null,Ej=1e3;(()=>{let t=()=>{let s=Da.getState(),n=zi.getState();s.autoRefresh&&n.isLoggedIn?(!od||Ej!==s.refreshInterval)&&(e(),Ej=s.refreshInterval,od=setInterval(()=>{zUt()},s.refreshInterval)):e()},e=()=>{od&&(clearInterval(od),od=null,Ej=0)},a=Da.getState().autoRefresh,i=Da.getState().refreshInterval,r=zi.getState().isLoggedIn;Da.state.subscribe(s=>{(s.autoRefresh!==a||s.refreshInterval!==i)&&(a=s.autoRefresh,i=s.refreshInterval,t())}),zi.state.subscribe(s=>{s.isLoggedIn!==r&&(r=s.isLoggedIn,t())}),t()})();var SUt=N1.plugins.smartrouter.SmartRouter,Oj=["overview","network","emails","logs","configuration","security","certificates"],Rj=["queued","sent","failed","security"],Bj=class{router;initialized=!1;suppressStateUpdate=!1;constructor(){this.router=new SUt({debug:!1})}init(){this.initialized||(this.setupRoutes(),this.setupStateSync(),this.handleInitialRoute(),this.initialized=!0)}setupRoutes(){for(let e of Oj)e==="emails"?(this.router.on("/emails",async()=>{this.updateViewState("emails"),this.updateEmailFolder("queued")}),this.router.on("/emails/:folder",async a=>{let i=a.params.folder;Rj.includes(i)?(this.updateViewState("emails"),this.updateEmailFolder(i)):this.navigateTo("/emails/queued")})):this.router.on(`/${e}`,async()=>{this.updateViewState(e)});this.router.on("/",async()=>{this.navigateTo("/overview")})}setupStateSync(){Da.state.subscribe(e=>{if(this.suppressStateUpdate)return;let a=window.location.pathname,i=this.getExpectedPath(e.activeView);if(!a.startsWith(i)){if(this.suppressStateUpdate=!0,e.activeView==="emails"){let r=T1.getState();this.router.pushUrl(`/emails/${r.currentView}`)}else this.router.pushUrl(`/${e.activeView}`);this.suppressStateUpdate=!1}})}getExpectedPath(e){return e==="emails"?"/emails":`/${e}`}handleInitialRoute(){let e=window.location.pathname;if(!e||e==="/")this.router.pushUrl("/overview");else{let a=e.split("/").filter(Boolean),i=a[0];if(Oj.includes(i))if(this.updateViewState(i),i==="emails"&&a[1]){let r=a[1];Rj.includes(r)?this.updateEmailFolder(r):this.updateEmailFolder("queued")}else i==="emails"&&this.updateEmailFolder("queued");else this.router.pushUrl("/overview")}}updateViewState(e){this.suppressStateUpdate=!0;let a=Da.getState();a.activeView!==e&&Da.setState({...a,activeView:e}),this.suppressStateUpdate=!1}updateEmailFolder(e){this.suppressStateUpdate=!0;let a=T1.getState();a.currentView!==e&&T1.setState({...a,currentView:e}),this.suppressStateUpdate=!1}navigateTo(e){this.router.pushUrl(e)}navigateToView(e){Oj.includes(e)?this.navigateTo(`/${e}`):this.navigateTo("/overview")}navigateToEmailFolder(e){Rj.includes(e)?this.navigateTo(`/emails/${e}`):this.navigateTo("/emails/queued")}getCurrentView(){return Da.getState().activeView}getCurrentEmailFolder(){return T1.getState().currentView}destroy(){this.router.destroy(),this.initialized=!1}},Ul=new Bj;ue();var Ea=X`
29069
+ `}async firstUpdated(n){await super.firstUpdated(n),this.outlet=this.shadowRoot.querySelector(".outlet")}async updateHtmlText(n){await this.updateComplete,this.outlet||(this.outlet=this.shadowRoot.querySelector(".outlet")),this.outlet.innerHTML=n}static{yUt(i,a)}};return s=i})()});var $yt=v(()=>{Lyt()});var Ayt=v(()=>{Lj()});var Dyt=v(()=>{Aj()});var Eyt=v(()=>{byt();vyt();xyt();wyt();Myt();kyt();$yt();Ayt();Dyt()});var Pyt=v(()=>{});var Nyt=v(()=>{Pyt()});var Iyt=v(()=>{ue()});var Fyt=v(()=>{Iyt()});var Oyt=v(()=>{fi();qe();yft();Aft();Wft();rmt();$mt();Emt();qgt();Abt();qvt();Qvt();Sw();Gxt();dyt();Eyt();Nyt();Fyt()});var Ryt,Byt=v(()=>{Ryt={name:"@design.estate/dees-catalog",version:"3.42.0",description:"A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."}});var bo={};Je(bo,{CanvasPool:()=>El,DeesActionbar:()=>smt,DeesAppui:()=>cft,DeesAppuiActivitylog:()=>cpt,DeesAppuiBar:()=>Spt,DeesAppuiBottombar:()=>_pt,DeesAppuiMaincontent:()=>lft,DeesAppuiMainmenu:()=>tft,DeesAppuiProfileDropdown:()=>zpt,DeesAppuiSecondarymenu:()=>rft,DeesAppuiTabs:()=>oft,DeesAudioViewer:()=>Obt,DeesBadge:()=>dmt,DeesButton:()=>Z9t,DeesButtonExit:()=>zft,DeesButtonGroup:()=>_ft,DeesChartArea:()=>Rft,DeesChartLog:()=>Vft,DeesChips:()=>Ugt,DeesContextmenu:()=>jt,DeesDashboardgrid:()=>dbt,DeesDataviewCodebox:()=>Zft,DeesDataviewStatusobject:()=>emt,DeesForm:()=>W9t,DeesFormSubmit:()=>Ry,DeesFormattingMenu:()=>nw,DeesHeading:()=>gbt,DeesHint:()=>gmt,DeesIcon:()=>ipt,DeesImageViewer:()=>Pbt,DeesInputBase:()=>Ze,DeesInputCheckbox:()=>Ly,DeesInputCode:()=>Ey,DeesInputDatepicker:()=>Py,DeesInputDropdown:()=>By,DeesInputFileupload:()=>qy,DeesInputIban:()=>Uy,DeesInputList:()=>Hmt,DeesInputMultitoggle:()=>Wy,DeesInputPhone:()=>Yy,DeesInputProfilePicture:()=>Hgt,DeesInputQuantitySelector:()=>Iy,DeesInputRadiogroup:()=>Fy,DeesInputRichtext:()=>egt,DeesInputTags:()=>ogt,DeesInputText:()=>Ny,DeesInputToggle:()=>Zy,DeesInputTypelist:()=>Xy,DeesInputWysiwyg:()=>DV,DeesLabel:()=>Vpt,DeesMobilenavigation:()=>bft,DeesModal:()=>s1,DeesPagination:()=>Mbt,DeesPanel:()=>Ept,DeesPdf:()=>avt,DeesPdfPreview:()=>cvt,DeesPdfViewer:()=>Ybt,DeesPreview:()=>Kbt,DeesProgressbar:()=>Mmt,DeesSearchbar:()=>Kxt,DeesShoppingProductcard:()=>t9t,DeesSimpleAppDash:()=>Oxt,DeesSimpleLogin:()=>jxt,DeesSlashMenu:()=>rw,DeesSpeechbubble:()=>Gvt,DeesSpinner:()=>Smt,DeesStatsGrid:()=>X9t,DeesStepper:()=>_bt,DeesTable:()=>Ky,DeesTheme:()=>iyt,DeesTileAudio:()=>zvt,DeesTileBase:()=>ga,DeesTileFolder:()=>Rvt,DeesTileImage:()=>vvt,DeesTileNote:()=>Evt,DeesTilePdf:()=>dw,DeesTileVideo:()=>_vt,DeesToast:()=>Ot,DeesUpdater:()=>kw,DeesVideoViewer:()=>qbt,DeesWindowControls:()=>Mpt,DeesWindowLayer:()=>mi,DeesWorkspace:()=>myt,DeesWorkspaceBottombar:()=>pyt,DeesWorkspaceDiffEditor:()=>fyt,DeesWorkspaceFiletree:()=>hyt,DeesWorkspaceMarkdown:()=>zyt,DeesWorkspaceMarkdownoutlet:()=>_yt,DeesWorkspaceMonaco:()=>jpt,DeesWorkspaceTerminal:()=>yj,DeesWorkspaceTerminalPreview:()=>uyt,DeesWysiwygBlock:()=>Pgt,PROGRAMMING_LANGUAGES:()=>_8,PdfManager:()=>Br,PerformanceMonitor:()=>Pl,TerminalTabManager:()=>ed,TypeScriptIntelliSenseManager:()=>sd,ViewRegistry:()=>z8,WebContainerEnvironment:()=>d4,WysiwygBlockOperations:()=>L8,WysiwygBlocks:()=>A2,WysiwygConverters:()=>wi,WysiwygDragDropHandler:()=>V8,WysiwygFormatting:()=>Is,WysiwygHistory:()=>j8,WysiwygInputHandler:()=>H8,WysiwygKeyboardHandler:()=>q8,WysiwygModalManager:()=>B8,WysiwygSelection:()=>Re,WysiwygShortcuts:()=>q1,ZIndexRegistry:()=>xf,colors:()=>H0,commitinfo:()=>Ryt,componentZIndex:()=>pBt,debounce:()=>Fjt,formatFileSize:()=>Rjt,getZIndex:()=>uBt,icons:()=>Cy,isInViewport:()=>Bjt,registerAllBlockHandlers:()=>Lgt,themeDefaultStyles:()=>ke,themeDefaults:()=>Zn,throttle:()=>Ojt,tileBaseStyles:()=>J2,wysiwygStyles:()=>SV,zIndexLayers:()=>a2,zIndexRegistry:()=>c1});var p4=v(()=>{Oyt();bi();Byt()});ue();p4();var N1=rt;Tc();var Hyt={};var qyt={};var vo=new N1.plugins.smartstate.Smartstate,zi=await vo.getStatePart("login",{identity:null,isLoggedIn:!1},"persistent"),o2=await vo.getStatePart("stats",{serverStats:null,emailStats:null,dnsStats:null,securityMetrics:null,lastUpdated:0,isLoading:!1,error:null},"soft"),Vr=await vo.getStatePart("config",{config:null,isLoading:!1,error:null}),wUt=()=>{let t=typeof window<"u"?window.location.pathname:"/",e=["overview","network","emails","logs","configuration","security","certificates"],i=t.split("/").filter(Boolean)[0];return e.includes(i)?i:"overview"},Da=await vo.getStatePart("ui",{activeView:wUt(),sidebarCollapsed:!1,autoRefresh:!0,refreshInterval:1e3,theme:"light"}),Tw=await vo.getStatePart("logs",{recentLogs:[],isStreaming:!1,filters:{}},"soft"),qr=await vo.getStatePart("network",{connections:[],connectionsByIP:{},throughputRate:{bytesInPerSecond:0,bytesOutPerSecond:0},totalBytes:{in:0,out:0},topIPs:[],throughputByIP:[],throughputHistory:[],requestsPerSecond:0,requestsTotal:0,lastUpdated:0,isLoading:!1,error:null},"soft"),T1=await vo.getStatePart("emailOps",{currentView:"queued",queuedEmails:[],sentEmails:[],failedEmails:[],securityIncidents:[],bounceRecords:[],suppressionList:[],selectedEmailId:null,isLoading:!1,error:null,lastUpdated:0},"soft"),ar=await vo.getStatePart("certificates",{certificates:[],summary:{total:0,valid:0,expiring:0,expired:0,failed:0,unknown:0},isLoading:!1,error:null,lastUpdated:0},"soft"),xa=()=>({identity:zi.getState().identity}),Vyt=zi.createAction(async(t,e)=>{let a=new N1.plugins.typedrequest.TypedRequest("/typedrequest","adminLoginWithUsernameAndPassword");try{let i=await a.fire({username:e.username,password:e.password});return i.identity?{identity:i.identity,isLoggedIn:!0}:t.getState()}catch(i){return console.error("Login failed:",i),t.getState()}}),Pj=zi.createAction(async t=>{let e=xa();if(!e.identity)return t.getState();let a=new N1.plugins.typedrequest.TypedRequest("/typedrequest","adminLogout");try{await a.fire({identity:e.identity})}catch(i){console.error("Logout error:",i)}return{identity:null,isLoggedIn:!1}}),Vl=o2.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCombinedMetrics").fire({identity:e.identity,sections:{server:!0,email:!0,dns:!0,security:!0,network:!1}});return{serverStats:r.metrics.server||a.serverStats,emailStats:r.metrics.email||a.emailStats,dnsStats:r.metrics.dns||a.dnsStats,securityMetrics:r.metrics.security||a.securityMetrics,lastUpdated:Date.now(),isLoading:!1,error:null}}catch(i){return{...a,isLoading:!1,error:i.message||"Failed to fetch statistics"}}}),jl=Vr.createAction(async t=>{let e=xa(),a=t.getState();try{return{config:(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getConfiguration").fire({identity:e.identity})).config,isLoading:!1,error:null}}catch(i){return{...a,isLoading:!1,error:i.message||"Failed to fetch configuration"}}}),jyt=Tw.createAction(async(t,e)=>{let a=xa(),r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getRecentLogs").fire({identity:a.identity,limit:e.limit||100,level:e.level,category:e.category});return{...t.getState(),recentLogs:r.logs}}),f92=Da.createAction(async t=>{let e=t.getState();return{...e,autoRefresh:!e.autoRefresh}}),m92=Da.createAction(async(t,e)=>{let a=t.getState();return e==="network"&&a.activeView!=="network"&&setTimeout(()=>{qr.dispatchAction(Nj,null)},100),e==="certificates"&&a.activeView!=="certificates"&&setTimeout(()=>{ar.dispatchAction(ql,null)},100),{...a,activeView:e}}),Nj=qr.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getActiveConnections").fire({identity:e.identity}),n=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getNetworkStats").fire({identity:e.identity}),o={};return n.connectionsByIP&&Array.isArray(n.connectionsByIP)?n.connectionsByIP.forEach(d=>{o[d.ip]=d.count}):r.connections.forEach(d=>{let c=d.remoteAddress;o[c]=(o[c]||0)+1}),{connections:r.connections,connectionsByIP:o,throughputRate:n.throughputRate||{bytesInPerSecond:0,bytesOutPerSecond:0},totalBytes:n.totalDataTransferred?{in:n.totalDataTransferred.bytesIn,out:n.totalDataTransferred.bytesOut}:{in:0,out:0},topIPs:n.topIPs||[],throughputByIP:n.throughputByIP||[],throughputHistory:n.throughputHistory||[],requestsPerSecond:n.requestsPerSecond||0,requestsTotal:n.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null}}catch(i){return console.error("Failed to fetch network stats:",i),{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch network stats"}}}),g92=T1.createAction(async(t,e)=>({...t.getState(),currentView:e})),Ij=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getQueuedEmails").fire({identity:e.identity,status:"pending",limit:100});return{...a,queuedEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch queued emails"}}}),Uyt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getSentEmails").fire({identity:e.identity,limit:100});return{...a,sentEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch sent emails"}}}),Fj=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getFailedEmails").fire({identity:e.identity,limit:100});return{...a,failedEmails:r.items,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch failed emails"}}}),Wyt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getSecurityIncidents").fire({identity:e.identity,limit:100});return{...a,securityIncidents:r.incidents,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch security incidents"}}}),MUt=T1.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getBounceRecords").fire({identity:e.identity,limit:100});return{...a,bounceRecords:r.records,suppressionList:r.suppressionList,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch bounce records"}}}),Gyt=T1.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","resendEmail").fire({identity:a.identity,emailId:e})).success&&(await T1.dispatchAction(Fj,null),await T1.dispatchAction(Ij,null)),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to resend email"}}}),b92=T1.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return(await new N1.plugins.typedrequest.TypedRequest("/typedrequest","removeFromSuppressionList").fire({identity:a.identity,email:e})).success&&await T1.dispatchAction(MUt,null),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to remove from suppression list"}}}),ql=ar.createAction(async t=>{let e=xa(),a=t.getState();try{let r=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCertificateOverview").fire({identity:e.identity});return{certificates:r.certificates,summary:r.summary,isLoading:!1,error:null,lastUpdated:Date.now()}}catch(i){return{...a,isLoading:!1,error:i instanceof Error?i.message:"Failed to fetch certificate overview"}}}),Yyt=ar.createAction(async(t,e)=>{let a=xa(),i=t.getState();try{return await new N1.plugins.typedrequest.TypedRequest("/typedrequest","reprovisionCertificateDomain").fire({identity:a.identity,domain:e}),await ar.dispatchAction(ql,null),t.getState()}catch(r){return{...i,error:r instanceof Error?r.message:"Failed to reprovision certificate"}}});async function zUt(){let t=xa(),e=Da.getState().activeView;try{let i=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getCombinedMetrics").fire({identity:t.identity,sections:{server:!0,email:!0,dns:!0,security:!0,network:e==="network"}});if(o2.setState({...o2.getState(),serverStats:i.metrics.server||o2.getState().serverStats,emailStats:i.metrics.email||o2.getState().emailStats,dnsStats:i.metrics.dns||o2.getState().dnsStats,securityMetrics:i.metrics.security||o2.getState().securityMetrics,lastUpdated:Date.now(),isLoading:!1,error:null}),i.metrics.network&&e==="network"){let r=i.metrics.network,s={};r.connectionDetails.forEach(n=>{s[n.remoteAddress]=(s[n.remoteAddress]||0)+1});try{let o=await new N1.plugins.typedrequest.TypedRequest("/typedrequest","getActiveConnections").fire({identity:t.identity});qr.setState({...qr.getState(),connections:o.connections,connectionsByIP:s,throughputRate:{bytesInPerSecond:r.totalBandwidth.in,bytesOutPerSecond:r.totalBandwidth.out},totalBytes:r.totalBytes||{in:0,out:0},topIPs:r.topEndpoints.map(d=>({ip:d.endpoint,count:d.requests})),throughputByIP:r.topEndpoints.map(d=>({ip:d.endpoint,in:d.bandwidth?.in||0,out:d.bandwidth?.out||0})),throughputHistory:r.throughputHistory||[],requestsPerSecond:r.requestsPerSecond||0,requestsTotal:r.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null})}catch(n){console.error("Failed to fetch connections:",n),qr.setState({...qr.getState(),connections:[],connectionsByIP:s,throughputRate:{bytesInPerSecond:r.totalBandwidth.in,bytesOutPerSecond:r.totalBandwidth.out},totalBytes:r.totalBytes||{in:0,out:0},topIPs:r.topEndpoints.map(o=>({ip:o.endpoint,count:o.requests})),throughputByIP:r.topEndpoints.map(o=>({ip:o.endpoint,in:o.bandwidth?.in||0,out:o.bandwidth?.out||0})),throughputHistory:r.throughputHistory||[],requestsPerSecond:r.requestsPerSecond||0,requestsTotal:r.requestsTotal||0,lastUpdated:Date.now(),isLoading:!1,error:null})}}if(e==="certificates")try{await ar.dispatchAction(ql,null)}catch(r){console.error("Certificate refresh failed:",r)}}catch(a){console.error("Combined refresh failed:",a)}}var od=null,Ej=1e3;(()=>{let t=()=>{let s=Da.getState(),n=zi.getState();s.autoRefresh&&n.isLoggedIn?(!od||Ej!==s.refreshInterval)&&(e(),Ej=s.refreshInterval,od=setInterval(()=>{zUt()},s.refreshInterval)):e()},e=()=>{od&&(clearInterval(od),od=null,Ej=0)},a=Da.getState().autoRefresh,i=Da.getState().refreshInterval,r=zi.getState().isLoggedIn;Da.state.subscribe(s=>{(s.autoRefresh!==a||s.refreshInterval!==i)&&(a=s.autoRefresh,i=s.refreshInterval,t())}),zi.state.subscribe(s=>{s.isLoggedIn!==r&&(r=s.isLoggedIn,t())}),t()})();var SUt=N1.plugins.smartrouter.SmartRouter,Oj=["overview","network","emails","logs","configuration","security","certificates"],Rj=["queued","sent","failed","security"],Bj=class{router;initialized=!1;suppressStateUpdate=!1;constructor(){this.router=new SUt({debug:!1})}init(){this.initialized||(this.setupRoutes(),this.setupStateSync(),this.handleInitialRoute(),this.initialized=!0)}setupRoutes(){for(let e of Oj)e==="emails"?(this.router.on("/emails",async()=>{this.updateViewState("emails"),this.updateEmailFolder("queued")}),this.router.on("/emails/:folder",async a=>{let i=a.params.folder;Rj.includes(i)?(this.updateViewState("emails"),this.updateEmailFolder(i)):this.navigateTo("/emails/queued")})):this.router.on(`/${e}`,async()=>{this.updateViewState(e)});this.router.on("/",async()=>{this.navigateTo("/overview")})}setupStateSync(){Da.state.subscribe(e=>{if(this.suppressStateUpdate)return;let a=window.location.pathname,i=this.getExpectedPath(e.activeView);if(!a.startsWith(i)){if(this.suppressStateUpdate=!0,e.activeView==="emails"){let r=T1.getState();this.router.pushUrl(`/emails/${r.currentView}`)}else this.router.pushUrl(`/${e.activeView}`);this.suppressStateUpdate=!1}})}getExpectedPath(e){return e==="emails"?"/emails":`/${e}`}handleInitialRoute(){let e=window.location.pathname;if(!e||e==="/")this.router.pushUrl("/overview");else{let a=e.split("/").filter(Boolean),i=a[0];if(Oj.includes(i))if(this.updateViewState(i),i==="emails"&&a[1]){let r=a[1];Rj.includes(r)?this.updateEmailFolder(r):this.updateEmailFolder("queued")}else i==="emails"&&this.updateEmailFolder("queued");else this.router.pushUrl("/overview")}}updateViewState(e){this.suppressStateUpdate=!0;let a=Da.getState();a.activeView!==e&&Da.setState({...a,activeView:e}),this.suppressStateUpdate=!1}updateEmailFolder(e){this.suppressStateUpdate=!0;let a=T1.getState();a.currentView!==e&&T1.setState({...a,currentView:e}),this.suppressStateUpdate=!1}navigateTo(e){this.router.pushUrl(e)}navigateToView(e){Oj.includes(e)?this.navigateTo(`/${e}`):this.navigateTo("/overview")}navigateToEmailFolder(e){Rj.includes(e)?this.navigateTo(`/emails/${e}`):this.navigateTo("/emails/queued")}getCurrentView(){return Da.getState().activeView}getCurrentEmailFolder(){return T1.getState().currentView}destroy(){this.router.destroy(),this.initialized=!1}},Ul=new Bj;ue();var Ea=X`
29070
29070
  :host {
29071
29071
  display: block;
29072
29072
  margin: auto;
@@ -30410,8 +30410,8 @@ ${JSON.stringify(a.details,null,2)}
30410
30410
  `}renderCertificateTable(){return w`
30411
30411
  <dees-table
30412
30412
  .data=${this.certState.certificates}
30413
- .displayFunction=${a=>({Route:a.routeName,Domains:this.renderDomainPills(a.domains),Status:this.renderStatusBadge(a.status),Source:this.renderSourceBadge(a.source),Expires:this.renderExpiry(a.expiryDate),Error:a.error?w`<span class="errorText" title="${a.error}">${a.error}</span>`:""})}
30414
- .dataActions=${[{name:"Reprovision",iconName:"arrowsRotate",type:["inRow"],actionFunc:async a=>{let i=a.item;if(!i.canReprovision){let{DeesToast:s}=await Promise.resolve().then(()=>(p4(),bo));s.show({message:"This certificate source does not support reprovisioning.",type:"warning",duration:3e3});return}await ar.dispatchAction(Yyt,i.routeName);let{DeesToast:r}=await Promise.resolve().then(()=>(p4(),bo));r.show({message:`Reprovisioning triggered for ${i.routeName}`,type:"success",duration:3e3})}},{name:"View Details",iconName:"magnifyingGlass",type:["doubleClick","contextmenu"],actionFunc:async a=>{let i=a.item,{DeesModal:r}=await Promise.resolve().then(()=>(p4(),bo));await r.createAndShow({heading:`Certificate: ${i.routeName}`,content:w`
30413
+ .displayFunction=${a=>({Domain:a.domain,Routes:this.renderRoutePills(a.routeNames),Status:this.renderStatusBadge(a.status),Source:this.renderSourceBadge(a.source),Expires:this.renderExpiry(a.expiryDate),Error:a.backoffInfo?w`<span class="backoffIndicator">${a.backoffInfo.failures} failures, retry ${this.formatRetryTime(a.backoffInfo.retryAfter)}</span>`:a.error?w`<span class="errorText" title="${a.error}">${a.error}</span>`:""})}
30414
+ .dataActions=${[{name:"Reprovision",iconName:"arrowsRotate",type:["inRow"],actionFunc:async a=>{let i=a.item;if(!i.canReprovision){let{DeesToast:s}=await Promise.resolve().then(()=>(p4(),bo));s.show({message:"This certificate source does not support reprovisioning.",type:"warning",duration:3e3});return}await ar.dispatchAction(Yyt,i.domain);let{DeesToast:r}=await Promise.resolve().then(()=>(p4(),bo));r.show({message:`Reprovisioning triggered for ${i.domain}`,type:"success",duration:3e3})}},{name:"View Details",iconName:"magnifyingGlass",type:["doubleClick","contextmenu"],actionFunc:async a=>{let i=a.item,{DeesModal:r}=await Promise.resolve().then(()=>(p4(),bo));await r.createAndShow({heading:`Certificate: ${i.domain}`,content:w`
30415
30415
  <div style="padding: 20px;">
30416
30416
  <dees-dataview-codebox
30417
30417
  .heading=${"Certificate Details"}
@@ -30419,24 +30419,24 @@ ${JSON.stringify(a.details,null,2)}
30419
30419
  .codeToDisplay=${JSON.stringify(i,null,2)}
30420
30420
  ></dees-dataview-codebox>
30421
30421
  </div>
30422
- `,menuOptions:[{name:"Copy Route Name",iconName:"copy",action:async()=>{await navigator.clipboard.writeText(i.routeName)}}]})}}]}
30422
+ `,menuOptions:[{name:"Copy Domain",iconName:"copy",action:async()=>{await navigator.clipboard.writeText(i.domain)}}]})}}]}
30423
30423
  heading1="Certificate Status"
30424
- heading2="TLS certificates across all routes"
30424
+ heading2="TLS certificates by domain"
30425
30425
  searchable
30426
30426
  .pagination=${!0}
30427
30427
  .paginationSize=${50}
30428
30428
  dataName="certificate"
30429
30429
  ></dees-table>
30430
- `}renderDomainPills(a){let r=a.slice(0,3),s=a.length-3;return w`
30431
- <span class="domainPills">
30432
- ${r.map(n=>w`<span class="domainPill">${n}</span>`)}
30430
+ `}renderRoutePills(a){let r=a.slice(0,3),s=a.length-3;return w`
30431
+ <span class="routePills">
30432
+ ${r.map(n=>w`<span class="routePill">${n}</span>`)}
30433
30433
  ${s>0?w`<span class="moreCount">+${s} more</span>`:""}
30434
30434
  </span>
30435
30435
  `}renderStatusBadge(a){return w`<span class="statusBadge ${a}">${a}</span>`}renderSourceBadge(a){return w`<span class="sourceBadge">${{acme:"ACME","provision-function":"Custom",static:"Static",none:"None"}[a]||a}</span>`}renderExpiry(a){if(!a)return w`<span style="color: ${u.bdTheme("#9ca3af","#4b5563")}">--</span>`;let i=new Date(a),r=new Date,s=Math.ceil((i.getTime()-r.getTime())/(1e3*60*60*24)),n=i.toLocaleDateString(),o="",d="";return s<0?(o="danger",d="(expired)"):s<30?(o="warn",d=`(${s}d left)`):d=`(${s}d left)`,w`
30436
30436
  <span class="expiryInfo">
30437
30437
  ${n} <span class="daysLeft ${o}">${d}</span>
30438
30438
  </span>
30439
- `}};Zl=c2($wt),cU=new WeakMap,gt(Zl,4,"certState",Lwt,Xs,cU),Xs=gt(Zl,0,"OpsViewCertificates",Awt,Xs),h1(Xs,"styles",[u.defaultStyles,Ea,X`
30439
+ `}formatRetryTime(a){if(!a)return"soon";let i=new Date(a),r=new Date,s=i.getTime()-r.getTime();if(s<=0)return"now";let n=Math.ceil(s/6e4);return n<60?`in ${n}m`:`in ${Math.ceil(n/60)}h`}};Zl=c2($wt),cU=new WeakMap,gt(Zl,4,"certState",Lwt,Xs,cU),Xs=gt(Zl,0,"OpsViewCertificates",Awt,Xs),h1(Xs,"styles",[u.defaultStyles,Ea,X`
30440
30440
  .certificatesContainer {
30441
30441
  display: flex;
30442
30442
  flex-direction: column;
@@ -30491,13 +30491,13 @@ ${JSON.stringify(a.details,null,2)}
30491
30491
  color: ${u.bdTheme("#374151","#d1d5db")};
30492
30492
  }
30493
30493
 
30494
- .domainPills {
30494
+ .routePills {
30495
30495
  display: flex;
30496
30496
  flex-wrap: wrap;
30497
30497
  gap: 4px;
30498
30498
  }
30499
30499
 
30500
- .domainPill {
30500
+ .routePill {
30501
30501
  display: inline-flex;
30502
30502
  align-items: center;
30503
30503
  padding: 2px 8px;
@@ -30522,6 +30522,17 @@ ${JSON.stringify(a.details,null,2)}
30522
30522
  white-space: nowrap;
30523
30523
  }
30524
30524
 
30525
+ .backoffIndicator {
30526
+ display: inline-flex;
30527
+ align-items: center;
30528
+ gap: 4px;
30529
+ font-size: 11px;
30530
+ color: ${u.bdTheme("#9a3412","#fb923c")};
30531
+ padding: 2px 6px;
30532
+ border-radius: 4px;
30533
+ background: ${u.bdTheme("#fff7ed","#431407")};
30534
+ }
30535
+
30525
30536
  .expiryInfo {
30526
30537
  font-size: 12px;
30527
30538
  }
@@ -30680,4 +30691,4 @@ ibantools/jsnext/ibantools.js:
30680
30691
  * @preferred
30681
30692
  *)
30682
30693
  */
30683
- //# sourceMappingURL=bundle-1771079296177.js.map
30694
+ //# sourceMappingURL=bundle-1771201612459.js.map
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '5.5.0',
6
+ version: '6.2.0',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBFQUEwRTtDQUN4RixDQUFBIn0=
@@ -0,0 +1,49 @@
1
+ import type { StorageManager } from './storage/index.js';
2
+ /**
3
+ * Manages certificate provisioning scheduling with:
4
+ * - Per-domain exponential backoff persisted in StorageManager
5
+ *
6
+ * Note: Serial stagger queue was removed — smartacme v9 handles
7
+ * concurrency, per-domain dedup, and rate limiting internally.
8
+ */
9
+ export declare class CertProvisionScheduler {
10
+ private storageManager;
11
+ private maxBackoffHours;
12
+ private backoffCache;
13
+ constructor(storageManager: StorageManager, options?: {
14
+ maxBackoffHours?: number;
15
+ });
16
+ /**
17
+ * Storage key for a domain's backoff entry
18
+ */
19
+ private backoffKey;
20
+ /**
21
+ * Load backoff entry from storage (with in-memory cache)
22
+ */
23
+ private loadBackoff;
24
+ /**
25
+ * Save backoff entry to both cache and storage
26
+ */
27
+ private saveBackoff;
28
+ /**
29
+ * Check if a domain is currently in backoff
30
+ */
31
+ isInBackoff(domain: string): Promise<boolean>;
32
+ /**
33
+ * Record a provisioning failure for a domain.
34
+ * Sets exponential backoff: min(failures^2 * 1h, maxBackoffHours)
35
+ */
36
+ recordFailure(domain: string, error?: string): Promise<void>;
37
+ /**
38
+ * Clear backoff for a domain (on success or manual override)
39
+ */
40
+ clearBackoff(domain: string): Promise<void>;
41
+ /**
42
+ * Get backoff info for UI display
43
+ */
44
+ getBackoffInfo(domain: string): Promise<{
45
+ failures: number;
46
+ retryAfter?: string;
47
+ lastError?: string;
48
+ } | null>;
49
+ }
@@ -0,0 +1,104 @@
1
+ import { logger } from './logger.js';
2
+ /**
3
+ * Manages certificate provisioning scheduling with:
4
+ * - Per-domain exponential backoff persisted in StorageManager
5
+ *
6
+ * Note: Serial stagger queue was removed — smartacme v9 handles
7
+ * concurrency, per-domain dedup, and rate limiting internally.
8
+ */
9
+ export class CertProvisionScheduler {
10
+ storageManager;
11
+ maxBackoffHours;
12
+ // In-memory backoff cache (mirrors storage for fast lookups)
13
+ backoffCache = new Map();
14
+ constructor(storageManager, options) {
15
+ this.storageManager = storageManager;
16
+ this.maxBackoffHours = options?.maxBackoffHours ?? 24;
17
+ }
18
+ /**
19
+ * Storage key for a domain's backoff entry
20
+ */
21
+ backoffKey(domain) {
22
+ const clean = domain.replace(/\*/g, '_wildcard_').replace(/[^a-zA-Z0-9._-]/g, '_');
23
+ return `/cert-backoff/${clean}`;
24
+ }
25
+ /**
26
+ * Load backoff entry from storage (with in-memory cache)
27
+ */
28
+ async loadBackoff(domain) {
29
+ const cached = this.backoffCache.get(domain);
30
+ if (cached)
31
+ return cached;
32
+ const entry = await this.storageManager.getJSON(this.backoffKey(domain));
33
+ if (entry) {
34
+ this.backoffCache.set(domain, entry);
35
+ }
36
+ return entry;
37
+ }
38
+ /**
39
+ * Save backoff entry to both cache and storage
40
+ */
41
+ async saveBackoff(domain, entry) {
42
+ this.backoffCache.set(domain, entry);
43
+ await this.storageManager.setJSON(this.backoffKey(domain), entry);
44
+ }
45
+ /**
46
+ * Check if a domain is currently in backoff
47
+ */
48
+ async isInBackoff(domain) {
49
+ const entry = await this.loadBackoff(domain);
50
+ if (!entry)
51
+ return false;
52
+ const retryAfter = new Date(entry.retryAfter);
53
+ return retryAfter.getTime() > Date.now();
54
+ }
55
+ /**
56
+ * Record a provisioning failure for a domain.
57
+ * Sets exponential backoff: min(failures^2 * 1h, maxBackoffHours)
58
+ */
59
+ async recordFailure(domain, error) {
60
+ const existing = await this.loadBackoff(domain);
61
+ const failures = (existing?.failures ?? 0) + 1;
62
+ // Exponential backoff: failures^2 hours, capped
63
+ const backoffHours = Math.min(failures * failures, this.maxBackoffHours);
64
+ const retryAfter = new Date(Date.now() + backoffHours * 60 * 60 * 1000);
65
+ const entry = {
66
+ failures,
67
+ lastFailure: new Date().toISOString(),
68
+ retryAfter: retryAfter.toISOString(),
69
+ lastError: error,
70
+ };
71
+ await this.saveBackoff(domain, entry);
72
+ logger.log('warn', `Cert backoff for ${domain}: ${failures} failures, retry after ${retryAfter.toISOString()}`);
73
+ }
74
+ /**
75
+ * Clear backoff for a domain (on success or manual override)
76
+ */
77
+ async clearBackoff(domain) {
78
+ this.backoffCache.delete(domain);
79
+ try {
80
+ await this.storageManager.delete(this.backoffKey(domain));
81
+ }
82
+ catch {
83
+ // Ignore delete errors (key may not exist)
84
+ }
85
+ }
86
+ /**
87
+ * Get backoff info for UI display
88
+ */
89
+ async getBackoffInfo(domain) {
90
+ const entry = await this.loadBackoff(domain);
91
+ if (!entry)
92
+ return null;
93
+ // Only return if still in backoff
94
+ const retryAfter = new Date(entry.retryAfter);
95
+ if (retryAfter.getTime() <= Date.now())
96
+ return null;
97
+ return {
98
+ failures: entry.failures,
99
+ retryAfter: entry.retryAfter,
100
+ lastError: entry.lastError,
101
+ };
102
+ }
103
+ }
104
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jZXJ0LXByb3Zpc2lvbi1zY2hlZHVsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jbGFzc2VzLmNlcnQtcHJvdmlzaW9uLXNjaGVkdWxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBVXJDOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxzQkFBc0I7SUFDekIsY0FBYyxDQUFpQjtJQUMvQixlQUFlLENBQVM7SUFFaEMsNkRBQTZEO0lBQ3JELFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQUV4RCxZQUNFLGNBQThCLEVBQzlCLE9BQXNDO1FBRXRDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxFQUFFLGVBQWUsSUFBSSxFQUFFLENBQUM7SUFDeEQsQ0FBQztJQUVEOztPQUVHO0lBQ0ssVUFBVSxDQUFDLE1BQWM7UUFDL0IsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUMsT0FBTyxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ25GLE9BQU8saUJBQWlCLEtBQUssRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBYztRQUN0QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM3QyxJQUFJLE1BQU07WUFBRSxPQUFPLE1BQU0sQ0FBQztRQUUxQixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFnQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDeEYsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLElB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
@@ -1,6 +1,7 @@
1
1
  import * as plugins from './plugins.js';
2
2
  import { UnifiedEmailServer, type IUnifiedEmailServerOptions, type IEmailRoute } from '@push.rocks/smartmta';
3
3
  import { StorageManager, type IStorageConfig } from './storage/index.js';
4
+ import { CertProvisionScheduler } from './classes.cert-provision-scheduler.js';
4
5
  import { CacheDb, CacheCleaner } from './cache/index.js';
5
6
  import { OpsServer } from './opsserver/index.js';
6
7
  import { MetricsManager } from './monitoring/index.js';
@@ -150,12 +151,13 @@ export declare class DcRouter {
150
151
  cacheCleaner?: CacheCleaner;
151
152
  certificateStatusMap: Map<string, {
152
153
  status: "valid" | "failed";
153
- domain: string;
154
+ routeNames: string[];
154
155
  expiryDate?: string;
155
156
  issuedAt?: string;
156
157
  source?: string;
157
158
  error?: string;
158
159
  }>;
160
+ certProvisionScheduler?: CertProvisionScheduler;
159
161
  typedrouter: plugins.typedrequest.TypedRouter;
160
162
  private qenv;
161
163
  constructor(optionsArg: IDcRouterOptions);
@@ -188,9 +190,13 @@ export declare class DcRouter {
188
190
  */
189
191
  private isDomainMatch;
190
192
  /**
191
- * Find the route name that matches a given domain
193
+ * Find the first route name that matches a given domain
192
194
  */
193
195
  private findRouteNameForDomain;
196
+ /**
197
+ * Find ALL route names that match a given domain
198
+ */
199
+ findRouteNamesForDomain(domain: string): string[];
194
200
  stop(): Promise<void>;
195
201
  /**
196
202
  * Update SmartProxy configuration