UNPKG

@api.global/typedserver

Version:

A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.

673 lines (654 loc) 50.4 kB
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, state, customElement, deesComms } from './plugins.js'; import { sharedStyles, terminalStyles, navStyles } from './sw-dash-styles.js'; // Import components to register them import './sw-dash-overview.js'; import './sw-dash-urls.js'; import './sw-dash-domains.js'; import './sw-dash-types.js'; import './sw-dash-events.js'; import './sw-dash-requests.js'; import './sw-dash-table.js'; /** * Main SW Dashboard application shell * * Architecture: * - ONE initial HTTP seed request to /sw-dash/metrics (provides ALL data) * - HTTP heartbeat every 30s for SW health check * - Everything else via DeesComms (push from SW, requests to SW) */ let SwDashApp = (() => { let _classDecorators = [customElement('sw-dash-app')]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = LitElement; let _currentView_decorators; let _currentView_initializers = []; let _currentView_extraInitializers = []; let _metrics_decorators; let _metrics_initializers = []; let _metrics_extraInitializers = []; let _lastRefresh_decorators; let _lastRefresh_initializers = []; let _lastRefresh_extraInitializers = []; let _isConnected_decorators; let _isConnected_initializers = []; let _isConnected_extraInitializers = []; let _resourceData_decorators; let _resourceData_initializers = []; let _resourceData_extraInitializers = []; let _events_decorators; let _events_initializers = []; let _events_extraInitializers = []; let _eventTotalCount_decorators; let _eventTotalCount_initializers = []; let _eventTotalCount_extraInitializers = []; let _eventCountLastHour_decorators; let _eventCountLastHour_initializers = []; let _eventCountLastHour_extraInitializers = []; let _requestLogs_decorators; let _requestLogs_initializers = []; let _requestLogs_extraInitializers = []; let _requestTotalCount_decorators; let _requestTotalCount_initializers = []; let _requestTotalCount_extraInitializers = []; let _requestStats_decorators; let _requestStats_initializers = []; let _requestStats_extraInitializers = []; let _requestMethods_decorators; let _requestMethods_initializers = []; let _requestMethods_extraInitializers = []; var SwDashApp = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _currentView_decorators = [state()]; _metrics_decorators = [state()]; _lastRefresh_decorators = [state()]; _isConnected_decorators = [state()]; _resourceData_decorators = [state()]; _events_decorators = [state()]; _eventTotalCount_decorators = [state()]; _eventCountLastHour_decorators = [state()]; _requestLogs_decorators = [state()]; _requestTotalCount_decorators = [state()]; _requestStats_decorators = [state()]; _requestMethods_decorators = [state()]; __esDecorate(this, null, _currentView_decorators, { kind: "accessor", name: "currentView", static: false, private: false, access: { has: obj => "currentView" in obj, get: obj => obj.currentView, set: (obj, value) => { obj.currentView = value; } }, metadata: _metadata }, _currentView_initializers, _currentView_extraInitializers); __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, _lastRefresh_decorators, { kind: "accessor", name: "lastRefresh", static: false, private: false, access: { has: obj => "lastRefresh" in obj, get: obj => obj.lastRefresh, set: (obj, value) => { obj.lastRefresh = value; } }, metadata: _metadata }, _lastRefresh_initializers, _lastRefresh_extraInitializers); __esDecorate(this, null, _isConnected_decorators, { kind: "accessor", name: "isConnected", static: false, private: false, access: { has: obj => "isConnected" in obj, get: obj => obj.isConnected, set: (obj, value) => { obj.isConnected = value; } }, metadata: _metadata }, _isConnected_initializers, _isConnected_extraInitializers); __esDecorate(this, null, _resourceData_decorators, { kind: "accessor", name: "resourceData", static: false, private: false, access: { has: obj => "resourceData" in obj, get: obj => obj.resourceData, set: (obj, value) => { obj.resourceData = value; } }, metadata: _metadata }, _resourceData_initializers, _resourceData_extraInitializers); __esDecorate(this, null, _events_decorators, { kind: "accessor", name: "events", static: false, private: false, access: { has: obj => "events" in obj, get: obj => obj.events, set: (obj, value) => { obj.events = value; } }, metadata: _metadata }, _events_initializers, _events_extraInitializers); __esDecorate(this, null, _eventTotalCount_decorators, { kind: "accessor", name: "eventTotalCount", static: false, private: false, access: { has: obj => "eventTotalCount" in obj, get: obj => obj.eventTotalCount, set: (obj, value) => { obj.eventTotalCount = value; } }, metadata: _metadata }, _eventTotalCount_initializers, _eventTotalCount_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, _requestLogs_decorators, { kind: "accessor", name: "requestLogs", static: false, private: false, access: { has: obj => "requestLogs" in obj, get: obj => obj.requestLogs, set: (obj, value) => { obj.requestLogs = value; } }, metadata: _metadata }, _requestLogs_initializers, _requestLogs_extraInitializers); __esDecorate(this, null, _requestTotalCount_decorators, { kind: "accessor", name: "requestTotalCount", static: false, private: false, access: { has: obj => "requestTotalCount" in obj, get: obj => obj.requestTotalCount, set: (obj, value) => { obj.requestTotalCount = value; } }, metadata: _metadata }, _requestTotalCount_initializers, _requestTotalCount_extraInitializers); __esDecorate(this, null, _requestStats_decorators, { kind: "accessor", name: "requestStats", static: false, private: false, access: { has: obj => "requestStats" in obj, get: obj => obj.requestStats, set: (obj, value) => { obj.requestStats = value; } }, metadata: _metadata }, _requestStats_initializers, _requestStats_extraInitializers); __esDecorate(this, null, _requestMethods_decorators, { kind: "accessor", name: "requestMethods", static: false, private: false, access: { has: obj => "requestMethods" in obj, get: obj => obj.requestMethods, set: (obj, value) => { obj.requestMethods = value; } }, metadata: _metadata }, _requestMethods_initializers, _requestMethods_extraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); SwDashApp = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static styles = [ sharedStyles, terminalStyles, navStyles, css ` :host { display: block; background: var(--bg-primary); min-height: 100vh; padding: var(--space-5); } .view { display: none; } .view.active { display: block; } .header-left { display: flex; align-items: center; gap: var(--space-3); } .logo { width: 24px; height: 24px; background: var(--accent-primary); border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; color: white; } .uptime-badge { display: inline-flex; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-2); background: var(--bg-tertiary); border-radius: var(--radius-sm); font-size: 11px; color: var(--text-tertiary); } .uptime-badge .value { color: var(--text-primary); font-weight: 500; font-variant-numeric: tabular-nums; } .footer-left { display: flex; align-items: center; gap: var(--space-2); color: var(--text-tertiary); font-size: 11px; } .footer-right { display: flex; align-items: center; gap: var(--space-2); } .auto-refresh { display: inline-flex; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-2); background: rgba(34, 197, 94, 0.1); color: var(--accent-success); border-radius: var(--radius-sm); font-size: 11px; font-weight: 500; } .auto-refresh .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } ` ]; #currentView_accessor_storage = __runInitializers(this, _currentView_initializers, 'overview'); // Core metrics get currentView() { return this.#currentView_accessor_storage; } set currentView(value) { this.#currentView_accessor_storage = value; } #metrics_accessor_storage = (__runInitializers(this, _currentView_extraInitializers), __runInitializers(this, _metrics_initializers, null)); get metrics() { return this.#metrics_accessor_storage; } set metrics(value) { this.#metrics_accessor_storage = value; } #lastRefresh_accessor_storage = (__runInitializers(this, _metrics_extraInitializers), __runInitializers(this, _lastRefresh_initializers, new Date().toLocaleTimeString())); get lastRefresh() { return this.#lastRefresh_accessor_storage; } set lastRefresh(value) { this.#lastRefresh_accessor_storage = value; } #isConnected_accessor_storage = (__runInitializers(this, _lastRefresh_extraInitializers), __runInitializers(this, _isConnected_initializers, false)); get isConnected() { return this.#isConnected_accessor_storage; } set isConnected(value) { this.#isConnected_accessor_storage = value; } #resourceData_accessor_storage = (__runInitializers(this, _isConnected_extraInitializers), __runInitializers(this, _resourceData_initializers, { resources: [], domains: [], contentTypes: [], resourceCount: 0 })); // Resource data (from initial seed) get resourceData() { return this.#resourceData_accessor_storage; } set resourceData(value) { this.#resourceData_accessor_storage = value; } #events_accessor_storage = (__runInitializers(this, _resourceData_extraInitializers), __runInitializers(this, _events_initializers, [])); // Events data (from initial seed + push updates) get events() { return this.#events_accessor_storage; } set events(value) { this.#events_accessor_storage = value; } #eventTotalCount_accessor_storage = (__runInitializers(this, _events_extraInitializers), __runInitializers(this, _eventTotalCount_initializers, 0)); get eventTotalCount() { return this.#eventTotalCount_accessor_storage; } set eventTotalCount(value) { this.#eventTotalCount_accessor_storage = value; } #eventCountLastHour_accessor_storage = (__runInitializers(this, _eventTotalCount_extraInitializers), __runInitializers(this, _eventCountLastHour_initializers, 0)); get eventCountLastHour() { return this.#eventCountLastHour_accessor_storage; } set eventCountLastHour(value) { this.#eventCountLastHour_accessor_storage = value; } #requestLogs_accessor_storage = (__runInitializers(this, _eventCountLastHour_extraInitializers), __runInitializers(this, _requestLogs_initializers, [])); // Request logs data (from initial seed + push updates) get requestLogs() { return this.#requestLogs_accessor_storage; } set requestLogs(value) { this.#requestLogs_accessor_storage = value; } #requestTotalCount_accessor_storage = (__runInitializers(this, _requestLogs_extraInitializers), __runInitializers(this, _requestTotalCount_initializers, 0)); get requestTotalCount() { return this.#requestTotalCount_accessor_storage; } set requestTotalCount(value) { this.#requestTotalCount_accessor_storage = value; } #requestStats_accessor_storage = (__runInitializers(this, _requestTotalCount_extraInitializers), __runInitializers(this, _requestStats_initializers, null)); get requestStats() { return this.#requestStats_accessor_storage; } set requestStats(value) { this.#requestStats_accessor_storage = value; } #requestMethods_accessor_storage = (__runInitializers(this, _requestStats_extraInitializers), __runInitializers(this, _requestMethods_initializers, [])); get requestMethods() { return this.#requestMethods_accessor_storage; } set requestMethods(value) { this.#requestMethods_accessor_storage = value; } // DeesComms for communication with service worker comms = (__runInitializers(this, _requestMethods_extraInitializers), null); // Heartbeat interval (30 seconds) for SW health check heartbeatInterval = null; HEARTBEAT_INTERVAL_MS = 30000; connectedCallback() { super.connectedCallback(); // Initial HTTP seed request to wake up SW and get ALL initial data this.loadInitialData(); // Setup push listeners via DeesComms this.setupPushListeners(); // Start heartbeat for SW health check this.startHeartbeat(); } disconnectedCallback() { super.disconnectedCallback(); if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); } } /** * Initial HTTP request to seed ALL data and wake up service worker * This is the ONE HTTP request that provides everything: * - Core metrics * - Resources, domains, content types * - Events (initial 50) * - Request logs (initial 50), stats, methods */ async loadInitialData() { try { const response = await fetch('/sw-dash/metrics'); const data = await response.json(); // Core metrics this.metrics = data; // Resource data this.resourceData = { resources: data.resources || [], domains: data.domains || [], contentTypes: data.contentTypes || [], resourceCount: data.resourceCount || 0, }; // Events data this.events = data.events || []; this.eventTotalCount = data.eventTotalCount || 0; this.eventCountLastHour = data.eventCountLastHour || 0; // Request logs data this.requestLogs = data.requestLogs || []; this.requestTotalCount = data.requestTotalCount || 0; this.requestStats = data.requestStats || null; this.requestMethods = data.requestMethods || []; this.lastRefresh = new Date().toLocaleTimeString(); this.isConnected = true; } catch (err) { console.error('Failed to load initial data:', err); this.isConnected = false; } } /** * Setup DeesComms handlers for receiving push updates from SW * All real-time updates come through here */ setupPushListeners() { this.comms = new deesComms.DeesComms(); // Handle metrics push updates this.comms.createTypedHandler('serviceworker_metricsUpdate', async (snapshot) => { // Update metrics from push if (this.metrics) { this.metrics = { ...this.metrics, cache: { ...this.metrics.cache, hits: snapshot.cache.hits, misses: snapshot.cache.misses, errors: snapshot.cache.errors, bytesServedFromCache: snapshot.cache.bytesServedFromCache, bytesFetched: snapshot.cache.bytesFetched, }, network: { ...this.metrics.network, totalRequests: snapshot.network.totalRequests, successfulRequests: snapshot.network.successfulRequests, failedRequests: snapshot.network.failedRequests, }, cacheHitRate: snapshot.cacheHitRate, networkSuccessRate: snapshot.networkSuccessRate, resourceCount: snapshot.resourceCount, uptime: snapshot.uptime, }; } this.lastRefresh = new Date().toLocaleTimeString(); this.isConnected = true; return {}; }); // Handle new event logged - add to our events array this.comms.createTypedHandler('serviceworker_eventLogged', async (entry) => { // Prepend new event to array this.events = [entry, ...this.events]; this.eventTotalCount++; // Check if event is within last hour const oneHourAgo = Date.now() - 3600000; if (entry.timestamp >= oneHourAgo) { this.eventCountLastHour++; } return {}; }); // Handle resource cached push updates this.comms.createTypedHandler('serviceworker_resourceCached', async (resource) => { // Update resource count optimistically if (resource.cached && this.metrics) { this.metrics = { ...this.metrics, resourceCount: this.metrics.resourceCount + 1, }; } return {}; }); // Handle new TypedRequest logged - add to our logs array this.comms.createTypedHandler('serviceworker_typedRequestLogged', async (entry) => { // Prepend new log to array this.requestLogs = [entry, ...this.requestLogs]; this.requestTotalCount++; // Update stats optimistically if (this.requestStats) { const newStats = { ...this.requestStats }; if (entry.phase === 'request') { newStats.totalRequests++; } else { newStats.totalResponses++; } if (entry.error) { newStats.errorCount++; } // Update method counts if (!newStats.methodCounts[entry.method]) { newStats.methodCounts[entry.method] = { requests: 0, responses: 0, errors: 0, avgDurationMs: 0 }; // Add to methods list if new if (!this.requestMethods.includes(entry.method)) { this.requestMethods = [...this.requestMethods, entry.method]; } } if (entry.phase === 'request') { newStats.methodCounts[entry.method].requests++; } else { newStats.methodCounts[entry.method].responses++; } if (entry.error) { newStats.methodCounts[entry.method].errors++; } this.requestStats = newStats; } return {}; }); } /** * Heartbeat to check SW health periodically (HTTP) * This is the ONLY periodic HTTP request */ startHeartbeat() { this.heartbeatInterval = setInterval(async () => { try { const response = await fetch('/sw-dash/metrics'); if (response.ok) { this.isConnected = true; // Refresh all data from heartbeat response const data = await response.json(); this.metrics = data; this.resourceData = { resources: data.resources || [], domains: data.domains || [], contentTypes: data.contentTypes || [], resourceCount: data.resourceCount || 0, }; this.events = data.events || []; this.eventTotalCount = data.eventTotalCount || 0; this.eventCountLastHour = data.eventCountLastHour || 0; this.requestLogs = data.requestLogs || []; this.requestTotalCount = data.requestTotalCount || 0; this.requestStats = data.requestStats || null; this.requestMethods = data.requestMethods || []; this.lastRefresh = new Date().toLocaleTimeString(); } else { this.isConnected = false; } } catch { this.isConnected = false; } }, this.HEARTBEAT_INTERVAL_MS); } /** * Handle "load more events" request from sw-dash-events component * Uses DeesComms to request older events from SW */ async handleLoadMoreEvents(e) { if (!this.comms) return; try { const tr = this.comms.createTypedRequest('serviceworker_getEventLog'); const result = await tr.fire({ limit: 50, before: e.detail.before, }); // Append older events to existing array this.events = [...this.events, ...result.events]; this.eventTotalCount = result.totalCount; } catch (err) { console.error('Failed to load more events:', err); } } /** * Handle "clear events" request from sw-dash-events component * Uses DeesComms to clear event log in SW */ async handleClearEvents() { if (!this.comms) return; try { const tr = this.comms.createTypedRequest('serviceworker_clearEventLog'); await tr.fire({}); // Clear local state this.events = []; this.eventTotalCount = 0; this.eventCountLastHour = 0; } catch (err) { console.error('Failed to clear events:', err); } } /** * Handle "load more requests" from sw-dash-requests component * Uses DeesComms to request older request logs from SW */ async handleLoadMoreRequests(e) { if (!this.comms) return; try { const tr = this.comms.createTypedRequest('serviceworker_getTypedRequestLogs'); const result = await tr.fire({ limit: 50, before: e.detail.before, method: e.detail.method, }); // Append older logs to existing array this.requestLogs = [...this.requestLogs, ...result.logs]; this.requestTotalCount = result.totalCount; } catch (err) { console.error('Failed to load more requests:', err); } } /** * Handle "clear requests" from sw-dash-requests component * Uses DeesComms to clear request logs in SW */ async handleClearRequests() { if (!this.comms) return; try { const tr = this.comms.createTypedRequest('serviceworker_clearTypedRequestLogs'); await tr.fire({}); // Clear local state this.requestLogs = []; this.requestTotalCount = 0; this.requestStats = { totalRequests: 0, totalResponses: 0, methodCounts: {}, errorCount: 0, avgDurationMs: 0, }; this.requestMethods = []; } catch (err) { console.error('Failed to clear requests:', err); } } setView(view) { this.currentView = view; // No HTTP fetch on view change - data is already loaded from initial seed } handleSpeedtestComplete(_e) { // Refresh metrics after speedtest via HTTP this.loadInitialData(); } formatUptime(ms) { const s = Math.floor(ms / 1000); const m = Math.floor(s / 60); const h = Math.floor(m / 60); const d = Math.floor(h / 24); if (d > 0) return `${d}d ${h % 24}h`; if (h > 0) return `${h}h ${m % 60}m`; if (m > 0) return `${m}m ${s % 60}s`; return `${s}s`; } render() { return html ` <div class="terminal"> <div class="header"> <div class="header-left"> <div class="logo">SW</div> <span class="title">Service Worker Dashboard</span> </div> <div class="uptime-badge"> Uptime: <span class="value">${this.metrics ? this.formatUptime(this.metrics.uptime) : '--'}</span> </div> </div> <nav class="nav"> <button class="nav-tab ${this.currentView === 'overview' ? 'active' : ''}" @click="${() => this.setView('overview')}" >Overview</button> <button class="nav-tab ${this.currentView === 'urls' ? 'active' : ''}" @click="${() => this.setView('urls')}" >URLs <span class="count">${this.resourceData.resourceCount}</span></button> <button class="nav-tab ${this.currentView === 'domains' ? 'active' : ''}" @click="${() => this.setView('domains')}" >Domains</button> <button class="nav-tab ${this.currentView === 'types' ? 'active' : ''}" @click="${() => this.setView('types')}" >Types</button> <button class="nav-tab ${this.currentView === 'events' ? 'active' : ''}" @click="${() => this.setView('events')}" >Events</button> <button class="nav-tab ${this.currentView === 'requests' ? 'active' : ''}" @click="${() => this.setView('requests')}" >Requests</button> </nav> <div class="content"> <div class="view ${this.currentView === 'overview' ? 'active' : ''}"> <sw-dash-overview .metrics="${this.metrics}" .eventCountLastHour="${this.eventCountLastHour}" @speedtest-complete="${this.handleSpeedtestComplete}" ></sw-dash-overview> </div> <div class="view ${this.currentView === 'urls' ? 'active' : ''}"> <sw-dash-urls .resources="${this.resourceData.resources}"></sw-dash-urls> </div> <div class="view ${this.currentView === 'domains' ? 'active' : ''}"> <sw-dash-domains .domains="${this.resourceData.domains}"></sw-dash-domains> </div> <div class="view ${this.currentView === 'types' ? 'active' : ''}"> <sw-dash-types .contentTypes="${this.resourceData.contentTypes}"></sw-dash-types> </div> <div class="view ${this.currentView === 'events' ? 'active' : ''}"> <sw-dash-events .events="${this.events}" .totalCount="${this.eventTotalCount}" @load-more-events="${this.handleLoadMoreEvents}" @clear-events="${this.handleClearEvents}" ></sw-dash-events> </div> <div class="view ${this.currentView === 'requests' ? 'active' : ''}"> <sw-dash-requests .logs="${this.requestLogs}" .totalCount="${this.requestTotalCount}" .stats="${this.requestStats}" .methods="${this.requestMethods}" @load-more-requests="${this.handleLoadMoreRequests}" @clear-requests="${this.handleClearRequests}" ></sw-dash-requests> </div> </div> <div class="footer"> <div class="footer-left"> Last updated: ${this.lastRefresh} </div> <div class="footer-right"> <div class="auto-refresh"> <span class="dot"></span> Live </div> </div> </div> </div> `; } static { __runInitializers(_classThis, _classExtraInitializers); } }; return SwDashApp = _classThis; })(); export { SwDashApp }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ctZGFzaC1hcHAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zd2Rhc2gvc3ctZGFzaC1hcHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0RixPQUFPLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQU85RSxxQ0FBcUM7QUFDckMsT0FBTyx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxvQkFBb0IsQ0FBQztBQVc1Qjs7Ozs7OztHQU9HO0lBRVUsU0FBUzs0QkFEckIsYUFBYSxDQUFDLGFBQWEsQ0FBQzs7OztzQkFDRSxVQUFVOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3lCQUFsQixTQUFRLFdBQVU7Ozs7dUNBbUd0QyxLQUFLLEVBQUU7bUNBQ1AsS0FBSyxFQUFFO3VDQUNQLEtBQUssRUFBRTt1Q0FDUCxLQUFLLEVBQUU7d0NBR1AsS0FBSyxFQUFFO2tDQVFQLEtBQUssRUFBRTsyQ0FDUCxLQUFLLEVBQUU7OENBQ1AsS0FBSyxFQUFFO3VDQUdQLEtBQUssRUFBRTs2Q0FDUCxLQUFLLEVBQUU7d0NBQ1AsS0FBSyxFQUFFOzBDQUNQLEtBQUssRUFBRTtZQXRCQyxzTEFBUyxXQUFXLDZCQUFYLFdBQVcsaUdBQXdCO1lBQzVDLDBLQUFTLE9BQU8sNkJBQVAsT0FBTyx5RkFBNkI7WUFDN0Msc0xBQVMsV0FBVyw2QkFBWCxXQUFXLGlHQUFt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