@api.global/typedserver
Version:
A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.
328 lines (322 loc) • 28.8 kB
JavaScript
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
import { LitElement, html, css, property, state, customElement } from './plugins.js';
import { sharedStyles, panelStyles, gaugeStyles, buttonStyles, speedtestStyles } from './sw-dash-styles.js';
import { SwDashTable } from './sw-dash-table.js';
/**
* Overview panel component with metrics gauges and stats
*/
let SwDashOverview = (() => {
let _classDecorators = [customElement('sw-dash-overview')];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = LitElement;
let _metrics_decorators;
let _metrics_initializers = [];
let _metrics_extraInitializers = [];
let _eventCountLastHour_decorators;
let _eventCountLastHour_initializers = [];
let _eventCountLastHour_extraInitializers = [];
let _speedtestRunning_decorators;
let _speedtestRunning_initializers = [];
let _speedtestRunning_extraInitializers = [];
let _speedtestPhase_decorators;
let _speedtestPhase_initializers = [];
let _speedtestPhase_extraInitializers = [];
let _speedtestProgress_decorators;
let _speedtestProgress_initializers = [];
let _speedtestProgress_extraInitializers = [];
let _speedtestElapsed_decorators;
let _speedtestElapsed_initializers = [];
let _speedtestElapsed_extraInitializers = [];
var SwDashOverview = class extends _classSuper {
static { _classThis = this; }
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_metrics_decorators = [property({ type: Object })];
_eventCountLastHour_decorators = [property({ type: Number })];
_speedtestRunning_decorators = [state()];
_speedtestPhase_decorators = [state()];
_speedtestProgress_decorators = [state()];
_speedtestElapsed_decorators = [state()];
__esDecorate(this, null, _metrics_decorators, { kind: "accessor", name: "metrics", static: false, private: false, access: { has: obj => "metrics" in obj, get: obj => obj.metrics, set: (obj, value) => { obj.metrics = value; } }, metadata: _metadata }, _metrics_initializers, _metrics_extraInitializers);
__esDecorate(this, null, _eventCountLastHour_decorators, { kind: "accessor", name: "eventCountLastHour", static: false, private: false, access: { has: obj => "eventCountLastHour" in obj, get: obj => obj.eventCountLastHour, set: (obj, value) => { obj.eventCountLastHour = value; } }, metadata: _metadata }, _eventCountLastHour_initializers, _eventCountLastHour_extraInitializers);
__esDecorate(this, null, _speedtestRunning_decorators, { kind: "accessor", name: "speedtestRunning", static: false, private: false, access: { has: obj => "speedtestRunning" in obj, get: obj => obj.speedtestRunning, set: (obj, value) => { obj.speedtestRunning = value; } }, metadata: _metadata }, _speedtestRunning_initializers, _speedtestRunning_extraInitializers);
__esDecorate(this, null, _speedtestPhase_decorators, { kind: "accessor", name: "speedtestPhase", static: false, private: false, access: { has: obj => "speedtestPhase" in obj, get: obj => obj.speedtestPhase, set: (obj, value) => { obj.speedtestPhase = value; } }, metadata: _metadata }, _speedtestPhase_initializers, _speedtestPhase_extraInitializers);
__esDecorate(this, null, _speedtestProgress_decorators, { kind: "accessor", name: "speedtestProgress", static: false, private: false, access: { has: obj => "speedtestProgress" in obj, get: obj => obj.speedtestProgress, set: (obj, value) => { obj.speedtestProgress = value; } }, metadata: _metadata }, _speedtestProgress_initializers, _speedtestProgress_extraInitializers);
__esDecorate(this, null, _speedtestElapsed_decorators, { kind: "accessor", name: "speedtestElapsed", static: false, private: false, access: { has: obj => "speedtestElapsed" in obj, get: obj => obj.speedtestElapsed, set: (obj, value) => { obj.speedtestElapsed = value; } }, metadata: _metadata }, _speedtestElapsed_initializers, _speedtestElapsed_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
SwDashOverview = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
static styles = [
sharedStyles,
panelStyles,
gaugeStyles,
buttonStyles,
speedtestStyles,
css `
:host {
display: block;
}
.panel-content {
padding: var(--space-4);
}
.section-divider {
margin-top: var(--space-4);
padding-top: var(--space-4);
border-top: 1px solid var(--border-muted);
}
`
];
#metrics_accessor_storage = __runInitializers(this, _metrics_initializers, null);
get metrics() { return this.#metrics_accessor_storage; }
set metrics(value) { this.#metrics_accessor_storage = value; }
#eventCountLastHour_accessor_storage = (__runInitializers(this, _metrics_extraInitializers), __runInitializers(this, _eventCountLastHour_initializers, 0));
get eventCountLastHour() { return this.#eventCountLastHour_accessor_storage; }
set eventCountLastHour(value) { this.#eventCountLastHour_accessor_storage = value; }
#speedtestRunning_accessor_storage = (__runInitializers(this, _eventCountLastHour_extraInitializers), __runInitializers(this, _speedtestRunning_initializers, false));
get speedtestRunning() { return this.#speedtestRunning_accessor_storage; }
set speedtestRunning(value) { this.#speedtestRunning_accessor_storage = value; }
#speedtestPhase_accessor_storage = (__runInitializers(this, _speedtestRunning_extraInitializers), __runInitializers(this, _speedtestPhase_initializers, 'idle'));
get speedtestPhase() { return this.#speedtestPhase_accessor_storage; }
set speedtestPhase(value) { this.#speedtestPhase_accessor_storage = value; }
#speedtestProgress_accessor_storage = (__runInitializers(this, _speedtestPhase_extraInitializers), __runInitializers(this, _speedtestProgress_initializers, 0));
get speedtestProgress() { return this.#speedtestProgress_accessor_storage; }
set speedtestProgress(value) { this.#speedtestProgress_accessor_storage = value; }
#speedtestElapsed_accessor_storage = (__runInitializers(this, _speedtestProgress_extraInitializers), __runInitializers(this, _speedtestElapsed_initializers, 0));
get speedtestElapsed() { return this.#speedtestElapsed_accessor_storage; }
set speedtestElapsed(value) { this.#speedtestElapsed_accessor_storage = value; }
// Speedtest timing constants (must match service worker)
static TEST_DURATION_MS = 5000; // 5 seconds per test
progressInterval = (__runInitializers(this, _speedtestElapsed_extraInitializers), null);
async runSpeedtest() {
if (this.speedtestRunning)
return;
this.speedtestRunning = true;
this.speedtestPhase = 'latency';
this.speedtestProgress = 0;
this.speedtestElapsed = 0;
// Start progress animation (total ~10.5s: latency ~0.5s + 5s download + 5s upload)
const totalEstimatedMs = 10500;
const startTime = Date.now();
this.progressInterval = window.setInterval(() => {
this.speedtestElapsed = Date.now() - startTime;
this.speedtestProgress = Math.min(100, (this.speedtestElapsed / totalEstimatedMs) * 100);
// Estimate phase based on elapsed time
if (this.speedtestElapsed < 500) {
this.speedtestPhase = 'latency';
}
else if (this.speedtestElapsed < 5500) {
this.speedtestPhase = 'download';
}
else {
this.speedtestPhase = 'upload';
}
}, 100);
try {
const response = await fetch('/sw-dash/speedtest');
const result = await response.json();
this.speedtestPhase = 'complete';
this.speedtestProgress = 100;
// Dispatch event to parent to update metrics
this.dispatchEvent(new CustomEvent('speedtest-complete', {
detail: result,
bubbles: true,
composed: true
}));
}
catch (err) {
console.error('Speedtest failed:', err);
this.speedtestPhase = 'idle';
}
finally {
if (this.progressInterval) {
window.clearInterval(this.progressInterval);
this.progressInterval = null;
}
// Keep showing complete state briefly, then reset
setTimeout(() => {
this.speedtestRunning = false;
this.speedtestPhase = 'idle';
this.speedtestProgress = 0;
}, 1500);
}
}
getPhaseLabel() {
switch (this.speedtestPhase) {
case 'latency': return 'Testing latency';
case 'download': return 'Download test';
case 'upload': return 'Upload test';
case 'complete': return 'Complete';
default: return '';
}
}
formatElapsed() {
const seconds = Math.floor(this.speedtestElapsed / 1000);
return `${seconds}s`;
}
render() {
if (!this.metrics) {
return html `<div class="panel"><div class="panel-content">Loading metrics...</div></div>`;
}
const m = this.metrics;
const gaugeClass = SwDashTable.getGaugeClass;
return html `
<div class="grid">
<!-- Cache Panel -->
<div class="panel">
<div class="panel-title">Cache</div>
<div class="panel-content">
<div class="gauge">
<div class="gauge-header">
<span class="gauge-label">Hit Rate</span>
<span class="gauge-value">${m.cacheHitRate}%</span>
</div>
<div class="gauge-bar">
<div class="gauge-fill ${gaugeClass(m.cacheHitRate)}" style="width: ${m.cacheHitRate}%"></div>
</div>
</div>
<div class="row"><span class="label">Hits</span><span class="value success">${SwDashTable.formatNumber(m.cache.hits)}</span></div>
<div class="row"><span class="label">Misses</span><span class="value warning">${SwDashTable.formatNumber(m.cache.misses)}</span></div>
<div class="row"><span class="label">Errors</span><span class="value ${m.cache.errors > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.cache.errors)}</span></div>
<div class="row"><span class="label">From Cache</span><span class="value">${SwDashTable.formatBytes(m.cache.bytesServedFromCache)}</span></div>
<div class="row"><span class="label">Fetched</span><span class="value">${SwDashTable.formatBytes(m.cache.bytesFetched)}</span></div>
<div class="row"><span class="label">Resources</span><span class="value">${m.resourceCount}</span></div>
</div>
</div>
<!-- Network Panel -->
<div class="panel">
<div class="panel-title">Network</div>
<div class="panel-content">
<div class="gauge">
<div class="gauge-header">
<span class="gauge-label">Success Rate</span>
<span class="gauge-value">${m.networkSuccessRate}%</span>
</div>
<div class="gauge-bar">
<div class="gauge-fill ${gaugeClass(m.networkSuccessRate)}" style="width: ${m.networkSuccessRate}%"></div>
</div>
</div>
<div class="row"><span class="label">Total Requests</span><span class="value">${SwDashTable.formatNumber(m.network.totalRequests)}</span></div>
<div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.network.successfulRequests)}</span></div>
<div class="row"><span class="label">Failed</span><span class="value ${m.network.failedRequests > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.network.failedRequests)}</span></div>
<div class="row"><span class="label">Timeouts</span><span class="value ${m.network.timeouts > 0 ? 'warning' : ''}">${SwDashTable.formatNumber(m.network.timeouts)}</span></div>
<div class="row"><span class="label">Avg Latency</span><span class="value">${m.network.averageLatency}ms</span></div>
<div class="row"><span class="label">Transferred</span><span class="value">${SwDashTable.formatBytes(m.network.totalBytesTransferred)}</span></div>
</div>
</div>
<!-- Updates Panel -->
<div class="panel">
<div class="panel-title">Updates</div>
<div class="panel-content">
<div class="row"><span class="label">Total Checks</span><span class="value">${SwDashTable.formatNumber(m.update.totalChecks)}</span></div>
<div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.update.successfulChecks)}</span></div>
<div class="row"><span class="label">Failed</span><span class="value ${m.update.failedChecks > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.update.failedChecks)}</span></div>
<div class="row"><span class="label">Updates Found</span><span class="value">${SwDashTable.formatNumber(m.update.updatesFound)}</span></div>
<div class="row"><span class="label">Updates Applied</span><span class="value success">${SwDashTable.formatNumber(m.update.updatesApplied)}</span></div>
<div class="row"><span class="label">Last Check</span><span class="value">${SwDashTable.formatTimestamp(m.update.lastCheckTimestamp)}</span></div>
</div>
</div>
<!-- Connections Panel -->
<div class="panel">
<div class="panel-title">Connections</div>
<div class="panel-content">
<div class="row"><span class="label">Active Clients</span><span class="value success">${SwDashTable.formatNumber(m.connection.connectedClients)}</span></div>
<div class="row"><span class="label">Total Attempts</span><span class="value">${SwDashTable.formatNumber(m.connection.totalConnectionAttempts)}</span></div>
<div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.connection.successfulConnections)}</span></div>
<div class="row"><span class="label">Failed</span><span class="value ${m.connection.failedConnections > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.connection.failedConnections)}</span></div>
<div class="section-divider">
<div class="row"><span class="label">Events (1h)</span><span class="value">${this.eventCountLastHour}</span></div>
<div class="row"><span class="label">Started</span><span class="value">${SwDashTable.formatTimestamp(m.startTime)}</span></div>
</div>
</div>
</div>
<!-- Speedtest Panel -->
<div class="panel">
<div class="panel-title">Speedtest</div>
<div class="panel-content">
<div class="online-indicator ${m.speedtest.isOnline ? 'online' : 'offline'}">
<span class="online-dot"></span>
<span>${m.speedtest.isOnline ? 'Online' : 'Offline'}</span>
</div>
${this.speedtestRunning ? html `
<div class="speedtest-progress">
<div class="progress-header">
<span class="progress-phase">${this.getPhaseLabel()}</span>
<span class="progress-time">${this.formatElapsed()}</span>
</div>
<div class="progress-bar">
<div class="progress-fill ${this.speedtestPhase === 'complete' ? 'complete' : ''}" style="width: ${this.speedtestProgress}%"></div>
</div>
</div>
` : html `
<div class="speedtest-results">
<div class="speedtest-metric">
<div class="speedtest-value">${m.speedtest.lastDownloadSpeedMbps.toFixed(1)}</div>
<div class="speedtest-unit">Mbps</div>
<div class="speedtest-label">Download</div>
</div>
<div class="speedtest-metric">
<div class="speedtest-value">${m.speedtest.lastUploadSpeedMbps.toFixed(1)}</div>
<div class="speedtest-unit">Mbps</div>
<div class="speedtest-label">Upload</div>
</div>
<div class="speedtest-metric">
<div class="speedtest-value">${m.speedtest.lastLatencyMs.toFixed(0)}</div>
<div class="speedtest-unit">ms</div>
<div class="speedtest-label">Latency</div>
</div>
</div>
`}
<div class="btn-row">
<button class="btn btn-secondary" ?disabled="${this.speedtestRunning}" ="${this.runSpeedtest}">
${this.speedtestRunning ? 'Testing...' : 'Run Test'}
</button>
</div>
</div>
</div>
</div>
`;
}
static {
__runInitializers(_classThis, _classExtraInitializers);
}
};
return SwDashOverview = _classThis;
})();
export { SwDashOverview };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ctZGFzaC1vdmVydmlldy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3N3ZGFzaC9zdy1kYXNoLW92ZXJ2aWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFckYsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFpRGpEOztHQUVHO0lBRVUsY0FBYzs0QkFEMUIsYUFBYSxDQUFDLGtCQUFrQixDQUFDOzs7O3NCQUNFLFVBQVU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OEJBQWxCLFNBQVEsV0FBVTs7OzttQ0F3QjNDLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs4Q0FDMUIsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzRDQUMxQixLQUFLLEVBQUU7MENBQ1AsS0FBSyxFQUFFOzZDQUNQLEtBQUssRUFBRTs0Q0FDUCxLQUFLLEVBQUU7WUFMb0IsMEtBQVMsT0FBTyw2QkFBUCxPQUFPLHlGQUE2QjtZQUM3QywyTUFBUyxrQkFBa0IsNkJBQWxCLGtCQUFrQiwrR0FBSztZQUNuRCxxTUFBUyxnQkFBZ0IsNkJBQWhCLGdCQUFnQiwyR0FBUztZQUNsQywrTEFBUyxjQUFjLDZCQUFkLGNBQWMsdUdBQW1FO1lBQzFGLHdNQUFTLGlCQUFpQiw2QkFBakIsaUJBQWlCLDZHQUFLO1lBQy9CLHFNQUFTLGdCQUFnQiw2QkFBaEIsZ0JBQWdCLDJHQUFLO1lBN0J6Qyw2S0EwT0M7Ozs7UUF6T1EsTUFBTSxDQUFD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