web_plsql 1.8.0 → 1.8.1

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.
@@ -144,4 +144,4 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
144
144
  <td class="text-right font-mono">${r}</td>
145
145
  </tr>
146
146
  `}).join(``)}catch(e){console.error(`Failed to load stats history:`,e),t&&(t.textContent=`Failed to load stats`)}}async function AC(){let e=document.getElementById(`access-filter`),t=document.getElementById(`access-limit`),n=e?.value??``,r=t?Number.parseInt(t.value):100,i=await Qp.getAccessLogs(r,n),a=document.getElementById(`access-log-view`),o=document.getElementById(`access-log-range`);if(!a)return;let s=0;Array.isArray(i)?(a.textContent=i.join(`
147
- `),s=i.length):i&&typeof i==`object`&&`message`in i?(a.textContent=i.message,s=0):(a.textContent=`No logs available`,s=0),o&&(o.textContent=s>0?`Showing last ${s} log entries`:`No logs available`),a.parentElement&&(a.parentElement.scrollTop=a.parentElement.scrollHeight)}async function jC(){let e=document.getElementById(`trace-filter`),t=document.getElementById(`trace-limit`),n=document.getElementById(`trace-status-toggle`),r=e?.value??``,i=t?Number.parseInt(t.value):100;try{let{enabled:e}=await Qp.getTraceStatus();n&&(n.textContent=e?`Tracing: ON`:`Tracing: OFF`,n.dataset.enabled=String(e),n.className=`px-4 py-2 rounded-lg text-sm font-bold transition-colors ${e?`bg-success text-black hover:bg-success/80`:`bg-white/10 text-white hover:bg-white/20`}`)}catch(e){console.error(`Failed to get trace status`,e)}let a=await Qp.getTraceLogs(i,r);new DC(`trace-table`,{columns:[{id:`timestamp`,header:`Timestamp`,headerTitle:`Time of request`,width:`1%`,accessor:e=>new Date(e.timestamp).toLocaleString(),className:`font-mono text-xs text-dim whitespace-nowrap`},{id:`source`,header:`Source`,headerTitle:`Request source (IP/User)`,width:`1%`,accessor:e=>e.source,className:`text-dim text-xs truncate max-w-[150px]`,cellTitle:e=>e.source},{id:`method`,header:`Method`,headerTitle:`HTTP Method`,width:`1%`,accessor:e=>e.method,className:`font-mono text-xs whitespace-nowrap`},{id:`url`,header:`Request URL`,headerTitle:`Request URL`,accessor:e=>e.url,className:`text-bright font-mono text-xs truncate max-w-[800px]`,cellTitle:e=>e.url},{id:`status`,header:`Status`,headerTitle:`HTTP Status Code`,width:`1%`,accessor:e=>e.status,className:e=>`font-bold text-xs uppercase whitespace-nowrap ${e.status===`success`?`text-success`:`text-danger`}`},{id:`duration`,header:`Duration`,headerTitle:`Execution time in ms`,width:`1%`,align:`right`,accessor:e=>gC(e.duration),className:`font-mono text-xs text-dim whitespace-nowrap`}],dense:!0,tableLayout:`auto`,onRowClick:e=>{let t=document.getElementById(`trace-modal`),n=document.getElementById(`trace-detail-content`);t&&n&&(n.textContent=JSON.stringify(e,null,2),t.style.display=`flex`)}}).render(a)}function MC(e){let t=document.getElementById(`pools-container`);!t||!e.pools||(t.innerHTML=e.pools.map(e=>SC(e)).join(``))}function NC(e){let t=e.status.config;if(!t)return;let n=document.getElementById(`config-view`);n&&(n.innerHTML=EC(t))}function PC(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return`${Number.parseFloat((e/t**+r).toFixed(2))} ${n[r]}`}function FC(e){return gC(e/1e3)}function IC(e,t){let n=document.getElementById(`middleware-version`);n&&e.version&&(n.textContent=`${e.version} (4/12/2026, 12:14:13 PM)`,n.title=`The version of the web_plsql gateway and admin console build time`);let r=document.getElementById(`node-version`);r&&e.system&&(r.textContent=e.system.nodeVersion,r.title=`The version of the Node.js runtime`);let i=document.getElementById(`platform-info`);i&&e.system&&(i.textContent=`${e.system.platform} (${e.system.arch})`,i.title=`The operating system and architecture`);let a=document.getElementById(`system-uptime`);a&&e.uptime&&(a.textContent=hC(e.uptime));let o=document.getElementById(`system-start-time`);o&&e.startTime&&(o.textContent=_C(e.startTime));let s=document.getElementById(`system-status-text`);s&&(s.textContent=e.status?.toUpperCase()??`-`);let c=document.getElementById(`total-requests`);c&&e.metrics&&(c.textContent=e.metrics.requestCount.toLocaleString(),c.title=`Cumulative number of requests handled by the server`);let l=document.getElementById(`total-errors`);l&&e.metrics&&(l.textContent=e.metrics.errorCount.toLocaleString(),l.title=`Cumulative number of failed requests`);let u=document.getElementById(`active-pools`);if(u&&e.pools&&(u.textContent=e.pools.length.toString(),u.title=`Number of database connection pools currently active`),e.system){let t=e.system,n={heapUsed:t.memory.heapUsed,heapTotal:t.memory.heapTotal,rss:t.memory.rss,external:t.memory.external,cpuUser:t.cpu.user,cpuSystem:t.cpu.system},r=(e,r,i)=>{let a=n[r],o=t.memory[i],s=document.getElementById(e),c=document.getElementById(`${e}-max`);s&&(s.textContent=PC(a)),c&&typeof o==`number`&&(c.textContent=PC(o))},i=(e,r,i)=>{let a=n[r],o=document.getElementById(e);if(o&&(o.textContent=FC(a)),i){let n=t.cpu[i],r=document.getElementById(`${e}-max`);r&&typeof n==`number`&&(r.textContent=FC(n))}};r(`memory-heap-used`,`heapUsed`,`heapUsedMax`),r(`memory-heap-total`,`heapTotal`,`heapTotalMax`),r(`memory-rss`,`rss`,`rssMax`),r(`memory-external`,`external`,`externalMax`),i(`cpu-user`,`cpuUser`,`userMax`),i(`cpu-system`,`cpuSystem`,`systemMax`);let a=document.getElementById(`cpu-percent`);a&&t.cpu.max!==void 0&&(a.textContent=`${t.cpu.max.toFixed(1)}%`,a.title=`Max System CPU usage`);let o=document.getElementById(`memory-percent`);o&&t.memory.totalMemory&&(o.textContent=`${(t.memory.rss/t.memory.totalMemory*100).toFixed(1)}%`,o.title=`System Memory Used relative to Total (${PC(t.memory.totalMemory)})`);let s=document.getElementById(`cpu-cores-info`);s&&t.cpuCores&&(s.textContent=`${t.cpuCores} Cores`)}}async function LC(e,t){let n=e.querySelector(`.material-symbols-rounded`),r=n?.textContent;e.disabled=!0,e.classList.add(`loading`),n&&(n.textContent=`sync`,n.classList.add(`animate-spin`));try{return await t()}finally{e.disabled=!1,e.classList.remove(`loading`),n&&(n.textContent=r??``,n.classList.remove(`animate-spin`))}}function RC(e,t){let n=document.getElementById(e);return n&&n.addEventListener(`click`,()=>void LC(n,t)),n}var zC={overview:`dashboard`,trace:`bolt`,errors:`error`,access:`list_alt`,pools:`database`,stats:`query_stats`,config:`settings`,system:`terminal`},$={currentView:`overview`,status:{},maxHistoryPoints:30,lastRequestCount:0,lastErrorCount:0,lastUpdateTime:Date.now(),lastBucketTimestamp:0,nextRefreshTimeout:null,nextRefreshTime:0,countdownInterval:null,history:{labels:[],requests:[],avgResponseTimes:[],p95ResponseTimes:[],p99ResponseTimes:[],cpuUsage:[],memoryUsage:[],poolUsage:{}},charts:{},metricsMin:{},metricsMax:{}},BC={REFRESH_INTERVAL:`admin_refresh_interval`,HISTORY_DURATION:`admin_history_duration`,AUTO_REFRESH:`admin_auto_refresh`,THEME:`theme`,LAST_VIEW:`admin_last_view`};function VC(e){console.error(`Connection lost:`,e);let t=document.getElementById(`server-status-dot`),n=document.getElementById(`server-status-text`);t&&(t.className=`dot offline`),n&&(n.textContent=`OFFLINE`);let r=document.getElementById(`btn-pause`);r&&(r.style.display=`none`);let i=document.getElementById(`btn-resume`);i&&(i.style.display=`none`);let a=document.querySelector(`#system-status .dot`),o=document.getElementById(`system-status-text`);a&&(a.className=`dot offline`),o&&(o.textContent=`OFFLINE`);let s=document.getElementById(`offline-modal`);s&&s.style.display!==`flex`&&(s.style.display=`flex`),GC(6e4),HC(6e4)}function HC(e){$.countdownInterval&&clearInterval($.countdownInterval);let t=Date.now()+e,n=document.getElementById(`offline-countdown`),r=document.getElementById(`reconnect-text`);r&&(r.textContent=`Try Reconnect`);let i=()=>{if(!n)return;let e=Math.max(0,Math.ceil((t-Date.now())/1e3));n.textContent=`Retrying in ${e}s...`,e<=0&&$.countdownInterval&&(clearInterval($.countdownInterval),$.countdownInterval=null)};i(),$.countdownInterval=setInterval(i,1e3)}function UC(){$.countdownInterval&&=(clearInterval($.countdownInterval),null);let e=document.getElementById(`offline-countdown`);e&&(e.textContent=``)}async function WC(e=!1,t=!1){let n=document.getElementById(`reconnect-spinner`),r=document.getElementById(`reconnect-icon`),i=document.getElementById(`reconnect-text`);n&&(n.style.display=`inline-block`),r&&(r.style.display=`none`),i&&(i.textContent=`Connecting...`);try{let a=Date.now(),o=await Qp.getStatus(e,t),s=document.getElementById(`offline-modal`);if(s?.style.display===`flex`&&s&&(s.style.display=`none`,UC()),n&&(n.style.display=`none`),r&&(r.style.display=`inline-block`),i&&(i.textContent=`Try Reconnect`),o.history&&$.history.labels.length===0&&pC($,o.history),!o.config&&$.status.config&&(o.config=$.status.config),$.status=o,!o.metrics||!o.pools)return;let c=o.history?.at(-1),l=(o.intervalMs??5e3)/1e3,u=c?c.requests/l:0,d=c?c.durationAvg:o.metrics.avgResponseTime;if($.lastRequestCount=o.metrics.requestCount,$.lastErrorCount=o.metrics.errorCount,$.lastUpdateTime=a,o.system){let e=o.system;vC({heapUsed:e.memory.heapUsed,heapTotal:e.memory.heapTotal,rss:e.memory.rss,external:e.memory.external,cpuUser:e.cpu.user,cpuSystem:e.cpu.system},$.metricsMin,$.metricsMax)}c&&c.timestamp>$.lastBucketTimestamp?($.lastBucketTimestamp=c.timestamp,mC($,new Date(c.timestamp).toLocaleTimeString(),u,d,o.pools)):!c&&$.history.labels.length===0&&mC($,new Date().toLocaleTimeString(),0,0,o.pools);let f=document.getElementById(`sidebar-version`);f&&(f.textContent=`v${o.version}`);let p=document.getElementById(`uptime-val`);p&&(p.textContent=hC(o.uptime));let m=document.getElementById(`start-time-val`);m&&(m.textContent=`Started: ${_C(o.startTime)}`);let h=document.getElementById(`req-per-sec`);h&&(h.textContent=u.toFixed(2));let g=document.getElementById(`max-req-per-sec`);g&&(g.textContent=o.metrics.maxRequestsPerSecond.toFixed(2));let _=document.getElementById(`avg-resp-time`);_&&(_.textContent=`${o.metrics.avgResponseTime.toFixed(1)}ms`);let v=document.getElementById(`max-resp-time`);v&&(v.textContent=`${o.metrics.maxResponseTime.toFixed(1)}ms`);let y=document.getElementById(`err-count`);y&&(y.textContent=o.metrics.errorCount.toLocaleString());let b=0,x=0;o.pools.forEach(e=>{e.cache&&(b+=e.cache.procedureName.hits+e.cache.argument.hits,x+=e.cache.procedureName.misses+e.cache.argument.misses)});let S=b+x,C=S>0?Math.round(b/S*100):0,w=document.getElementById(`cache-hit-rate-val`);w&&(w.textContent=`${C}%`,w.style.color=C>80?`var(--success)`:C>50?`var(--warning)`:`var(--danger)`);let T=document.getElementById(`cache-hits-val`);T&&(T.textContent=b.toLocaleString());let E=document.getElementById(`cache-misses-val`);E&&(E.textContent=x.toLocaleString());let ee=document.getElementById(`server-status-dot`),te=document.getElementById(`server-status-text`);ee&&(ee.className=`dot `+o.status),te&&(te.textContent=o.status.toUpperCase());let ne=document.getElementById(`btn-pause`);ne&&(ne.style.display=o.status===`running`?`flex`:`none`);let re=document.getElementById(`btn-resume`);re&&(re.style.display=o.status===`paused`?`flex`:`none`),$.currentView===`errors`&&await OC(),$.currentView===`trace`&&await jC(),$.currentView===`pools`&&MC(o),$.currentView===`config`&&NC($),$.currentView===`system`&&IC(o,$),YC?.checked&&XC&&GC(Number.parseInt(XC.value,10))}catch(e){document.getElementById(`offline-modal`)?.style.display===`flex`?(GC(6e4),HC(6e4),n&&(n.style.display=`none`),r&&(r.style.display=`inline-block`),i&&(i.textContent=`Try Reconnect`)):VC(e)}}function GC(e){$.nextRefreshTimeout&&=(clearTimeout($.nextRefreshTimeout),null),$.nextRefreshTime=Date.now()+e,$.nextRefreshTimeout=setTimeout(()=>{WC()},e)}function KC(){let e=document.getElementById(`refresh-interval`);e&&GC(Number.parseInt(e.value))}function qC(){$.nextRefreshTimeout&&=(clearTimeout($.nextRefreshTimeout),null)}function JC(){let e=document.getElementById(`chart-history-points`);e&&Array.from(e.options).forEach(e=>{let t=Number.parseInt(e.value),n=``;if(t<60)n=`${t}s`;else if(t<3600)n=`${Math.round(t/60)} min`;else{let e=t/3600;n=e===Math.round(e)?`${e} hour${e>1?`s`:``}`:`${e.toFixed(1)} hours`}e.textContent=`Last ${n}`})}document.querySelectorAll(`nav button`).forEach(e=>{let t=e;t.addEventListener(`click`,async()=>{try{let e=t.dataset.view;if(!e)return;$.currentView=e,localStorage.setItem(BC.LAST_VIEW,e),document.querySelectorAll(`.view`).forEach(e=>{let t=e;t.style.display=`none`});let n=document.getElementById(`view-`+e);n&&(n.style.display=`block`),document.querySelectorAll(`nav button`).forEach(e=>e.classList.remove(`active`)),t.classList.add(`active`);let r=document.getElementById(`view-title`);if(r){let n=Array.from(t.childNodes).filter(e=>e.nodeType===Node.TEXT_NODE).map(e=>e.textContent?.trim()).join(``);r.innerHTML=`<span class="material-symbols-rounded">${zC[e]??`chevron_right`}</span>${n}`}e===`errors`&&await OC(),e===`trace`&&await jC(),e===`pools`&&MC($.status),e===`stats`&&await kC(),e===`config`&&NC($),e===`system`&&IC($.status,$)}catch(e){VC(e)}})});var YC=document.getElementById(`auto-refresh-toggle`);YC&&YC.addEventListener(`change`,e=>{let t=e.target;localStorage.setItem(BC.AUTO_REFRESH,String(t.checked)),t.checked?KC():qC()});var XC=document.getElementById(`refresh-interval`);XC&&XC.addEventListener(`change`,()=>{localStorage.setItem(BC.REFRESH_INTERVAL,XC.value);let e=Number.parseInt(XC.value),t=Number.parseInt(ZC?.value??`60`);$.maxHistoryPoints=Math.max(1,Math.floor(t/(e/1e3))),$.history.labels=[],$.history.requests=[],$.history.avgResponseTimes=[],$.history.cpuUsage=[],$.history.memoryUsage=[],$.history.poolUsage={},JC(),IC($.status,$),WC()});var ZC=document.getElementById(`chart-history-points`);ZC&&ZC.addEventListener(`change`,()=>{localStorage.setItem(BC.HISTORY_DURATION,ZC.value);let e=document.getElementById(`refresh-interval`);if(!e)return;let t=Number.parseInt(e.value),n=Number.parseInt(ZC.value);$.maxHistoryPoints=Math.max(1,Math.floor(n/(t/1e3))),$.history.labels=[],$.history.requests=[],$.history.avgResponseTimes=[],$.history.cpuUsage=[],$.history.memoryUsage=[],$.history.poolUsage={},WC()});var QC=document.getElementById(`manual-refresh`);QC&&QC.addEventListener(`click`,()=>{LC(QC,WC)});var $C=document.getElementById(`error-filter`);$C&&$C.addEventListener(`keydown`,e=>{e.key===`Enter`&&OC()}),RC(`error-load-btn`,OC),RC(`trace-load-btn`,jC),RC(`access-load-btn`,AC),RC(`stats-load-btn`,kC);var ew=document.getElementById(`trace-filter`);ew&&ew.addEventListener(`keydown`,e=>{e.key===`Enter`&&jC()});var tw=document.getElementById(`trace-clear-btn`);tw&&tw.addEventListener(`click`,async()=>{confirm(`Are you sure you want to clear all traces?`)&&await LC(tw,async()=>{await Qp.clearTraces(),await jC()})});var nw=document.getElementById(`trace-status-toggle`);nw&&nw.addEventListener(`click`,async()=>{await LC(nw,async()=>{let{enabled:e}=await Qp.getTraceStatus();await Qp.toggleTrace(!e),await jC()})});var rw=document.getElementById(`access-filter`);rw&&rw.addEventListener(`keydown`,e=>{e.key===`Enter`&&AC()});var iw=document.getElementById(`stats-limit`);iw&&iw.addEventListener(`keydown`,e=>{e.key===`Enter`&&kC()}),RC(`btn-pause`,async()=>{confirm(`Are you sure you want to pause the server?`)&&(await Qp.post(`api/server/pause`),await WC())}),RC(`btn-resume`,async()=>{await Qp.post(`api/server/resume`),await WC()}),RC(`btn-stop`,async()=>{confirm(`Are you sure you want to STOP the server? This action cannot be undone from the web interface.`)&&(await Qp.post(`api/server/stop`),alert(`Server stop requested. The interface will now become unresponsive.`))}),RC(`btn-clear-all-cache`,async()=>{confirm(`Are you sure you want to clear ALL caches?`)&&(await Qp.post(`api/cache/clear`),await WC())});var aw=document.getElementById(`btn-reconnect`);aw&&aw.addEventListener(`click`,()=>{LC(aw,WC)}),globalThis.addEventListener(`keydown`,e=>{if(e.key===`Escape`){let e=document.getElementById(`error-modal`);e&&(e.style.display=`none`);let t=document.getElementById(`trace-modal`);t&&(t.style.display=`none`)}});var ow=localStorage.getItem(BC.REFRESH_INTERVAL);ow&&XC&&(XC.value=ow);var sw=localStorage.getItem(BC.HISTORY_DURATION);sw&&ZC&&(ZC.value=sw);var cw=localStorage.getItem(BC.AUTO_REFRESH);if(cw!==null&&YC&&(YC.checked=cw===`true`),xC($),fC($),JC(),XC&&ZC){let e=Number.parseInt(XC.value),t=Number.parseInt(ZC.value);$.maxHistoryPoints=Math.max(1,Math.floor(t/(e/1e3)))}var lw=localStorage.getItem(BC.LAST_VIEW);if(lw){let e=document.querySelector(`nav button[data-view="${lw}"]`);e&&e.click()}WC(!0,!0).then(()=>{YC?.checked&&KC()}).catch(console.error);
147
+ `),s=i.length):i&&typeof i==`object`&&`message`in i?(a.textContent=i.message,s=0):(a.textContent=`No logs available`,s=0),o&&(o.textContent=s>0?`Showing last ${s} log entries`:`No logs available`),a.parentElement&&(a.parentElement.scrollTop=a.parentElement.scrollHeight)}async function jC(){let e=document.getElementById(`trace-filter`),t=document.getElementById(`trace-limit`),n=document.getElementById(`trace-status-toggle`),r=e?.value??``,i=t?Number.parseInt(t.value):100;try{let{enabled:e}=await Qp.getTraceStatus();n&&(n.textContent=e?`Tracing: ON`:`Tracing: OFF`,n.dataset.enabled=String(e),n.className=`px-4 py-2 rounded-lg text-sm font-bold transition-colors ${e?`bg-success text-black hover:bg-success/80`:`bg-white/10 text-white hover:bg-white/20`}`)}catch(e){console.error(`Failed to get trace status`,e)}let a=await Qp.getTraceLogs(i,r);new DC(`trace-table`,{columns:[{id:`timestamp`,header:`Timestamp`,headerTitle:`Time of request`,width:`1%`,accessor:e=>new Date(e.timestamp).toLocaleString(),className:`font-mono text-xs text-dim whitespace-nowrap`},{id:`source`,header:`Source`,headerTitle:`Request source (IP/User)`,width:`1%`,accessor:e=>e.source,className:`text-dim text-xs truncate max-w-[150px]`,cellTitle:e=>e.source},{id:`method`,header:`Method`,headerTitle:`HTTP Method`,width:`1%`,accessor:e=>e.method,className:`font-mono text-xs whitespace-nowrap`},{id:`url`,header:`Request URL`,headerTitle:`Request URL`,accessor:e=>e.url,className:`text-bright font-mono text-xs truncate max-w-[800px]`,cellTitle:e=>e.url},{id:`status`,header:`Status`,headerTitle:`HTTP Status Code`,width:`1%`,accessor:e=>e.status,className:e=>`font-bold text-xs uppercase whitespace-nowrap ${e.status===`success`?`text-success`:`text-danger`}`},{id:`duration`,header:`Duration`,headerTitle:`Execution time in ms`,width:`1%`,align:`right`,accessor:e=>gC(e.duration),className:`font-mono text-xs text-dim whitespace-nowrap`}],dense:!0,tableLayout:`auto`,onRowClick:e=>{let t=document.getElementById(`trace-modal`),n=document.getElementById(`trace-detail-content`);t&&n&&(n.textContent=JSON.stringify(e,null,2),t.style.display=`flex`)}}).render(a)}function MC(e){let t=document.getElementById(`pools-container`);!t||!e.pools||(t.innerHTML=e.pools.map(e=>SC(e)).join(``))}function NC(e){let t=e.status.config;if(!t)return;let n=document.getElementById(`config-view`);n&&(n.innerHTML=EC(t))}function PC(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return`${Number.parseFloat((e/t**+r).toFixed(2))} ${n[r]}`}function FC(e){return gC(e/1e3)}function IC(e,t){let n=document.getElementById(`middleware-version`);n&&e.version&&(n.textContent=`${e.version} (4/12/2026, 1:07:42 PM)`,n.title=`The version of the web_plsql gateway and admin console build time`);let r=document.getElementById(`node-version`);r&&e.system&&(r.textContent=e.system.nodeVersion,r.title=`The version of the Node.js runtime`);let i=document.getElementById(`platform-info`);i&&e.system&&(i.textContent=`${e.system.platform} (${e.system.arch})`,i.title=`The operating system and architecture`);let a=document.getElementById(`system-uptime`);a&&e.uptime&&(a.textContent=hC(e.uptime));let o=document.getElementById(`system-start-time`);o&&e.startTime&&(o.textContent=_C(e.startTime));let s=document.getElementById(`system-status-text`);s&&(s.textContent=e.status?.toUpperCase()??`-`);let c=document.getElementById(`total-requests`);c&&e.metrics&&(c.textContent=e.metrics.requestCount.toLocaleString(),c.title=`Cumulative number of requests handled by the server`);let l=document.getElementById(`total-errors`);l&&e.metrics&&(l.textContent=e.metrics.errorCount.toLocaleString(),l.title=`Cumulative number of failed requests`);let u=document.getElementById(`active-pools`);if(u&&e.pools&&(u.textContent=e.pools.length.toString(),u.title=`Number of database connection pools currently active`),e.system){let t=e.system,n={heapUsed:t.memory.heapUsed,heapTotal:t.memory.heapTotal,rss:t.memory.rss,external:t.memory.external,cpuUser:t.cpu.user,cpuSystem:t.cpu.system},r=(e,r,i)=>{let a=n[r],o=t.memory[i],s=document.getElementById(e),c=document.getElementById(`${e}-max`);s&&(s.textContent=PC(a)),c&&typeof o==`number`&&(c.textContent=PC(o))},i=(e,r,i)=>{let a=n[r],o=document.getElementById(e);if(o&&(o.textContent=FC(a)),i){let n=t.cpu[i],r=document.getElementById(`${e}-max`);r&&typeof n==`number`&&(r.textContent=FC(n))}};r(`memory-heap-used`,`heapUsed`,`heapUsedMax`),r(`memory-heap-total`,`heapTotal`,`heapTotalMax`),r(`memory-rss`,`rss`,`rssMax`),r(`memory-external`,`external`,`externalMax`),i(`cpu-user`,`cpuUser`,`userMax`),i(`cpu-system`,`cpuSystem`,`systemMax`);let a=document.getElementById(`cpu-percent`);a&&t.cpu.max!==void 0&&(a.textContent=`${t.cpu.max.toFixed(1)}%`,a.title=`Max System CPU usage`);let o=document.getElementById(`memory-percent`);o&&t.memory.totalMemory&&(o.textContent=`${(t.memory.rss/t.memory.totalMemory*100).toFixed(1)}%`,o.title=`System Memory Used relative to Total (${PC(t.memory.totalMemory)})`);let s=document.getElementById(`cpu-cores-info`);s&&t.cpuCores&&(s.textContent=`${t.cpuCores} Cores`)}}async function LC(e,t){let n=e.querySelector(`.material-symbols-rounded`),r=n?.textContent;e.disabled=!0,e.classList.add(`loading`),n&&(n.textContent=`sync`,n.classList.add(`animate-spin`));try{return await t()}finally{e.disabled=!1,e.classList.remove(`loading`),n&&(n.textContent=r??``,n.classList.remove(`animate-spin`))}}function RC(e,t){let n=document.getElementById(e);return n&&n.addEventListener(`click`,()=>void LC(n,t)),n}var zC={overview:`dashboard`,trace:`bolt`,errors:`error`,access:`list_alt`,pools:`database`,stats:`query_stats`,config:`settings`,system:`terminal`},$={currentView:`overview`,status:{},maxHistoryPoints:30,lastRequestCount:0,lastErrorCount:0,lastUpdateTime:Date.now(),lastBucketTimestamp:0,nextRefreshTimeout:null,nextRefreshTime:0,countdownInterval:null,history:{labels:[],requests:[],avgResponseTimes:[],p95ResponseTimes:[],p99ResponseTimes:[],cpuUsage:[],memoryUsage:[],poolUsage:{}},charts:{},metricsMin:{},metricsMax:{}},BC={REFRESH_INTERVAL:`admin_refresh_interval`,HISTORY_DURATION:`admin_history_duration`,AUTO_REFRESH:`admin_auto_refresh`,THEME:`theme`,LAST_VIEW:`admin_last_view`};function VC(e){console.error(`Connection lost:`,e);let t=document.getElementById(`server-status-dot`),n=document.getElementById(`server-status-text`);t&&(t.className=`dot offline`),n&&(n.textContent=`OFFLINE`);let r=document.getElementById(`btn-pause`);r&&(r.style.display=`none`);let i=document.getElementById(`btn-resume`);i&&(i.style.display=`none`);let a=document.querySelector(`#system-status .dot`),o=document.getElementById(`system-status-text`);a&&(a.className=`dot offline`),o&&(o.textContent=`OFFLINE`);let s=document.getElementById(`offline-modal`);s&&s.style.display!==`flex`&&(s.style.display=`flex`),GC(6e4),HC(6e4)}function HC(e){$.countdownInterval&&clearInterval($.countdownInterval);let t=Date.now()+e,n=document.getElementById(`offline-countdown`),r=document.getElementById(`reconnect-text`);r&&(r.textContent=`Try Reconnect`);let i=()=>{if(!n)return;let e=Math.max(0,Math.ceil((t-Date.now())/1e3));n.textContent=`Retrying in ${e}s...`,e<=0&&$.countdownInterval&&(clearInterval($.countdownInterval),$.countdownInterval=null)};i(),$.countdownInterval=setInterval(i,1e3)}function UC(){$.countdownInterval&&=(clearInterval($.countdownInterval),null);let e=document.getElementById(`offline-countdown`);e&&(e.textContent=``)}async function WC(e=!1,t=!1){let n=document.getElementById(`reconnect-spinner`),r=document.getElementById(`reconnect-icon`),i=document.getElementById(`reconnect-text`);n&&(n.style.display=`inline-block`),r&&(r.style.display=`none`),i&&(i.textContent=`Connecting...`);try{let a=Date.now(),o=await Qp.getStatus(e,t),s=document.getElementById(`offline-modal`);if(s?.style.display===`flex`&&s&&(s.style.display=`none`,UC()),n&&(n.style.display=`none`),r&&(r.style.display=`inline-block`),i&&(i.textContent=`Try Reconnect`),o.history&&$.history.labels.length===0&&pC($,o.history),!o.config&&$.status.config&&(o.config=$.status.config),$.status=o,!o.metrics||!o.pools)return;let c=o.history?.at(-1),l=(o.intervalMs??5e3)/1e3,u=c?c.requests/l:0,d=c?c.durationAvg:o.metrics.avgResponseTime;if($.lastRequestCount=o.metrics.requestCount,$.lastErrorCount=o.metrics.errorCount,$.lastUpdateTime=a,o.system){let e=o.system;vC({heapUsed:e.memory.heapUsed,heapTotal:e.memory.heapTotal,rss:e.memory.rss,external:e.memory.external,cpuUser:e.cpu.user,cpuSystem:e.cpu.system},$.metricsMin,$.metricsMax)}c&&c.timestamp>$.lastBucketTimestamp?($.lastBucketTimestamp=c.timestamp,mC($,new Date(c.timestamp).toLocaleTimeString(),u,d,o.pools)):!c&&$.history.labels.length===0&&mC($,new Date().toLocaleTimeString(),0,0,o.pools);let f=document.getElementById(`sidebar-version`);f&&(f.textContent=`v${o.version}`);let p=document.getElementById(`uptime-val`);p&&(p.textContent=hC(o.uptime));let m=document.getElementById(`start-time-val`);m&&(m.textContent=`Started: ${_C(o.startTime)}`);let h=document.getElementById(`req-per-sec`);h&&(h.textContent=u.toFixed(2));let g=document.getElementById(`max-req-per-sec`);g&&(g.textContent=o.metrics.maxRequestsPerSecond.toFixed(2));let _=document.getElementById(`avg-resp-time`);_&&(_.textContent=`${o.metrics.avgResponseTime.toFixed(1)}ms`);let v=document.getElementById(`max-resp-time`);v&&(v.textContent=`${o.metrics.maxResponseTime.toFixed(1)}ms`);let y=document.getElementById(`err-count`);y&&(y.textContent=o.metrics.errorCount.toLocaleString());let b=0,x=0;o.pools.forEach(e=>{e.cache&&(b+=e.cache.procedureName.hits+e.cache.argument.hits,x+=e.cache.procedureName.misses+e.cache.argument.misses)});let S=b+x,C=S>0?Math.round(b/S*100):0,w=document.getElementById(`cache-hit-rate-val`);w&&(w.textContent=`${C}%`,w.style.color=C>80?`var(--success)`:C>50?`var(--warning)`:`var(--danger)`);let T=document.getElementById(`cache-hits-val`);T&&(T.textContent=b.toLocaleString());let E=document.getElementById(`cache-misses-val`);E&&(E.textContent=x.toLocaleString());let ee=document.getElementById(`server-status-dot`),te=document.getElementById(`server-status-text`);ee&&(ee.className=`dot `+o.status),te&&(te.textContent=o.status.toUpperCase());let ne=document.getElementById(`btn-pause`);ne&&(ne.style.display=o.status===`running`?`flex`:`none`);let re=document.getElementById(`btn-resume`);re&&(re.style.display=o.status===`paused`?`flex`:`none`),$.currentView===`errors`&&await OC(),$.currentView===`trace`&&await jC(),$.currentView===`pools`&&MC(o),$.currentView===`config`&&NC($),$.currentView===`system`&&IC(o,$),YC?.checked&&XC&&GC(Number.parseInt(XC.value,10))}catch(e){document.getElementById(`offline-modal`)?.style.display===`flex`?(GC(6e4),HC(6e4),n&&(n.style.display=`none`),r&&(r.style.display=`inline-block`),i&&(i.textContent=`Try Reconnect`)):VC(e)}}function GC(e){$.nextRefreshTimeout&&=(clearTimeout($.nextRefreshTimeout),null),$.nextRefreshTime=Date.now()+e,$.nextRefreshTimeout=setTimeout(()=>{WC()},e)}function KC(){let e=document.getElementById(`refresh-interval`);e&&GC(Number.parseInt(e.value))}function qC(){$.nextRefreshTimeout&&=(clearTimeout($.nextRefreshTimeout),null)}function JC(){let e=document.getElementById(`chart-history-points`);e&&Array.from(e.options).forEach(e=>{let t=Number.parseInt(e.value),n=``;if(t<60)n=`${t}s`;else if(t<3600)n=`${Math.round(t/60)} min`;else{let e=t/3600;n=e===Math.round(e)?`${e} hour${e>1?`s`:``}`:`${e.toFixed(1)} hours`}e.textContent=`Last ${n}`})}document.querySelectorAll(`nav button`).forEach(e=>{let t=e;t.addEventListener(`click`,async()=>{try{let e=t.dataset.view;if(!e)return;$.currentView=e,localStorage.setItem(BC.LAST_VIEW,e),document.querySelectorAll(`.view`).forEach(e=>{let t=e;t.style.display=`none`});let n=document.getElementById(`view-`+e);n&&(n.style.display=`block`),document.querySelectorAll(`nav button`).forEach(e=>e.classList.remove(`active`)),t.classList.add(`active`);let r=document.getElementById(`view-title`);if(r){let n=Array.from(t.childNodes).filter(e=>e.nodeType===Node.TEXT_NODE).map(e=>e.textContent?.trim()).join(``);r.innerHTML=`<span class="material-symbols-rounded">${zC[e]??`chevron_right`}</span>${n}`}e===`errors`&&await OC(),e===`trace`&&await jC(),e===`pools`&&MC($.status),e===`stats`&&await kC(),e===`config`&&NC($),e===`system`&&IC($.status,$)}catch(e){VC(e)}})});var YC=document.getElementById(`auto-refresh-toggle`);YC&&YC.addEventListener(`change`,e=>{let t=e.target;localStorage.setItem(BC.AUTO_REFRESH,String(t.checked)),t.checked?KC():qC()});var XC=document.getElementById(`refresh-interval`);XC&&XC.addEventListener(`change`,()=>{localStorage.setItem(BC.REFRESH_INTERVAL,XC.value);let e=Number.parseInt(XC.value),t=Number.parseInt(ZC?.value??`60`);$.maxHistoryPoints=Math.max(1,Math.floor(t/(e/1e3))),$.history.labels=[],$.history.requests=[],$.history.avgResponseTimes=[],$.history.cpuUsage=[],$.history.memoryUsage=[],$.history.poolUsage={},JC(),IC($.status,$),WC()});var ZC=document.getElementById(`chart-history-points`);ZC&&ZC.addEventListener(`change`,()=>{localStorage.setItem(BC.HISTORY_DURATION,ZC.value);let e=document.getElementById(`refresh-interval`);if(!e)return;let t=Number.parseInt(e.value),n=Number.parseInt(ZC.value);$.maxHistoryPoints=Math.max(1,Math.floor(n/(t/1e3))),$.history.labels=[],$.history.requests=[],$.history.avgResponseTimes=[],$.history.cpuUsage=[],$.history.memoryUsage=[],$.history.poolUsage={},WC()});var QC=document.getElementById(`manual-refresh`);QC&&QC.addEventListener(`click`,()=>{LC(QC,WC)});var $C=document.getElementById(`error-filter`);$C&&$C.addEventListener(`keydown`,e=>{e.key===`Enter`&&OC()}),RC(`error-load-btn`,OC),RC(`trace-load-btn`,jC),RC(`access-load-btn`,AC),RC(`stats-load-btn`,kC);var ew=document.getElementById(`trace-filter`);ew&&ew.addEventListener(`keydown`,e=>{e.key===`Enter`&&jC()});var tw=document.getElementById(`trace-clear-btn`);tw&&tw.addEventListener(`click`,async()=>{confirm(`Are you sure you want to clear all traces?`)&&await LC(tw,async()=>{await Qp.clearTraces(),await jC()})});var nw=document.getElementById(`trace-status-toggle`);nw&&nw.addEventListener(`click`,async()=>{await LC(nw,async()=>{let{enabled:e}=await Qp.getTraceStatus();await Qp.toggleTrace(!e),await jC()})});var rw=document.getElementById(`access-filter`);rw&&rw.addEventListener(`keydown`,e=>{e.key===`Enter`&&AC()});var iw=document.getElementById(`stats-limit`);iw&&iw.addEventListener(`keydown`,e=>{e.key===`Enter`&&kC()}),RC(`btn-pause`,async()=>{confirm(`Are you sure you want to pause the server?`)&&(await Qp.post(`api/server/pause`),await WC())}),RC(`btn-resume`,async()=>{await Qp.post(`api/server/resume`),await WC()}),RC(`btn-stop`,async()=>{confirm(`Are you sure you want to STOP the server? This action cannot be undone from the web interface.`)&&(await Qp.post(`api/server/stop`),alert(`Server stop requested. The interface will now become unresponsive.`))}),RC(`btn-clear-all-cache`,async()=>{confirm(`Are you sure you want to clear ALL caches?`)&&(await Qp.post(`api/cache/clear`),await WC())});var aw=document.getElementById(`btn-reconnect`);aw&&aw.addEventListener(`click`,()=>{LC(aw,WC)}),globalThis.addEventListener(`keydown`,e=>{if(e.key===`Escape`){let e=document.getElementById(`error-modal`);e&&(e.style.display=`none`);let t=document.getElementById(`trace-modal`);t&&(t.style.display=`none`)}});var ow=localStorage.getItem(BC.REFRESH_INTERVAL);ow&&XC&&(XC.value=ow);var sw=localStorage.getItem(BC.HISTORY_DURATION);sw&&ZC&&(ZC.value=sw);var cw=localStorage.getItem(BC.AUTO_REFRESH);if(cw!==null&&YC&&(YC.checked=cw===`true`),xC($),fC($),JC(),XC&&ZC){let e=Number.parseInt(XC.value),t=Number.parseInt(ZC.value);$.maxHistoryPoints=Math.max(1,Math.floor(t/(e/1e3)))}var lw=localStorage.getItem(BC.LAST_VIEW);if(lw){let e=document.querySelector(`nav button[data-view="${lw}"]`);e&&e.click()}WC(!0,!0).then(()=>{YC?.checked&&KC()}).catch(console.error);
@@ -6,7 +6,7 @@
6
6
  <title>web_plsql Admin Console</title>
7
7
  <link rel="icon" type="image/svg+xml" href="/admin/assets/favicon-mQAM4tVu.svg" />
8
8
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
9
- <script type="module" crossorigin src="/admin/assets/main-Co9Kke3j.js"></script>
9
+ <script type="module" crossorigin src="/admin/assets/main-soziFoIv.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="/admin/assets/main-CoERzZAr.css">
11
11
  </head>
12
12
  <body class="dark">
Binary file
Binary file
package/dist/index.mjs CHANGED
@@ -222,9 +222,10 @@ globalThis.__VERSION__ ??= "**development**";
222
222
  * Returns the current library version
223
223
  * @returns {string} - Version.
224
224
  */
225
- const getVersion = () => "1.8.0";
225
+ const getVersion = () => "1.8.1";
226
226
  //#endregion
227
227
  //#region src/backend/server/printBanner.ts
228
+ const IS_TTY = process.stdout.isTTY === true;
228
229
  const ICON_GLOBE = "🌐";
229
230
  const ICON_KEY = "🔑";
230
231
  const ICON_DOC = "📄";
@@ -252,8 +253,9 @@ const padTo = (s, w) => {
252
253
  return delta > 0 ? s + " ".repeat(delta) : s;
253
254
  };
254
255
  const truncateTo = (s, w) => w > 0 ? sliceAnsi(s, 0, w) : "";
255
- const divider = () => chalk.dim(BOX.ml + BOX.h.repeat(W - 2) + BOX.mr);
256
- const bottom = () => chalk.dim(BOX.bl + BOX.h.repeat(W - 2) + BOX.br);
256
+ const divider = () => IS_TTY ? chalk.dim(BOX.ml + BOX.h.repeat(W - 2) + BOX.mr) : "-".repeat(W);
257
+ const borderOpen = () => IS_TTY ? chalk.dim(BOX.tl + BOX.h.repeat(W - 2) + BOX.tr) : divider();
258
+ const borderClose = () => IS_TTY ? chalk.dim(BOX.bl + BOX.h.repeat(W - 2) + BOX.br) : divider();
257
259
  /**
258
260
  * Single key/value row.
259
261
  * @param key - Label text.
@@ -262,12 +264,12 @@ const bottom = () => chalk.dim(BOX.bl + BOX.h.repeat(W - 2) + BOX.br);
262
264
  * @returns Formatted string.
263
265
  */
264
266
  const row = (key, value, icon) => {
265
- const label = padTo(icon ? `${icon} ${key}` : ` ${key}`, LABEL_W);
267
+ const label = padTo(IS_TTY ? icon ? `${icon} ${key}` : ` ${key}` : `${key}`, LABEL_W);
266
268
  const hasValue = value !== null && value !== void 0 && value !== "";
267
269
  const valueText = hasValue ? String(value) : "—";
268
270
  const colorFn = hasValue ? chalk.white : chalk.dim;
269
271
  const valueCell = padTo(truncateTo(valueText, VALUE_W), VALUE_W);
270
- return chalk.dim(BOX.v) + " " + chalk.dim(label) + " " + colorFn(valueCell) + " " + chalk.dim(BOX.v);
272
+ return IS_TTY ? chalk.dim(BOX.v) + " " + chalk.dim(label) + " " + colorFn(valueCell) + " " + chalk.dim(BOX.v) : label + " " + valueCell;
271
273
  };
272
274
  /**
273
275
  * Renders the server startup banner to stdout.
@@ -277,10 +279,10 @@ const printBanner = (cfg) => {
277
279
  const adminRoute = cfg.adminRoute ?? "/admin";
278
280
  const baseUrl = `http://localhost:${cfg.port}`;
279
281
  const lines = [];
282
+ lines.push(borderOpen());
280
283
  const title = `NODE PL/SQL SERVER ${getVersion()}`;
281
284
  const pad = W - 2 - displayWidth(title);
282
- lines.push(chalk.dim(BOX.tl + BOX.h.repeat(W - 2) + BOX.tr));
283
- lines.push(chalk.dim(BOX.v) + " ".repeat(Math.floor(pad / 2)) + chalk.bold.cyan(title) + " ".repeat(Math.ceil(pad / 2)) + chalk.dim(BOX.v));
285
+ lines.push(IS_TTY ? chalk.dim(BOX.v) + " ".repeat(Math.floor(pad / 2)) + chalk.bold.cyan(title) + " ".repeat(Math.ceil(pad / 2)) + chalk.dim(BOX.v) : title);
284
286
  lines.push(divider());
285
287
  lines.push(row("Port", cfg.port, ICON_GLOBE));
286
288
  lines.push(row("Admin route", `${adminRoute}${cfg.adminUser ? " (authenticated)" : ""}`, ICON_KEY));
@@ -321,7 +323,7 @@ const printBanner = (cfg) => {
321
323
  cfg.routePlSql.forEach((r) => {
322
324
  lines.push(row(r.route, `${baseUrl}${r.route}`, ICON_GEAR));
323
325
  });
324
- lines.push(bottom());
326
+ lines.push(borderClose());
325
327
  console.log(lines.join("\n"));
326
328
  };
327
329
  //#endregion