viberadar 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server/index.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ interface ServerOptions {
|
|
|
5
5
|
port: number;
|
|
6
6
|
projectRoot: string;
|
|
7
7
|
}
|
|
8
|
-
export declare function startServer({ data, port, projectRoot }: ServerOptions): Promise<http.Server>;
|
|
8
|
+
export declare function startServer({ data: initialData, port, projectRoot }: ServerOptions): Promise<http.Server>;
|
|
9
9
|
export {};
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AAErD,UAAU,aAAa;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAwGzG"}
|
package/dist/server/index.js
CHANGED
|
@@ -32,14 +32,72 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.startServer = startServer;
|
|
37
40
|
const http = __importStar(require("http"));
|
|
38
41
|
const fs = __importStar(require("fs"));
|
|
39
42
|
const path = __importStar(require("path"));
|
|
43
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
44
|
+
const scanner_1 = require("../scanner");
|
|
40
45
|
const DASHBOARD_HTML = fs.readFileSync(path.join(__dirname, '../ui/dashboard.html'), 'utf-8');
|
|
41
|
-
function startServer({ data, port, projectRoot }) {
|
|
46
|
+
function startServer({ data: initialData, port, projectRoot }) {
|
|
42
47
|
return new Promise((resolve, reject) => {
|
|
48
|
+
// ── Mutable data reference ──────────────────────────────────────────────────
|
|
49
|
+
let currentData = initialData;
|
|
50
|
+
// ── SSE clients ─────────────────────────────────────────────────────────────
|
|
51
|
+
const sseClients = new Set();
|
|
52
|
+
function broadcast(event) {
|
|
53
|
+
const msg = `event: ${event}\ndata: {}\n\n`;
|
|
54
|
+
for (const client of sseClients) {
|
|
55
|
+
try {
|
|
56
|
+
client.write(msg);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
sseClients.delete(client);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ── File watcher + re-scan ──────────────────────────────────────────────────
|
|
64
|
+
let scanDebounce = null;
|
|
65
|
+
async function scheduleRescan(changedFile) {
|
|
66
|
+
if (scanDebounce)
|
|
67
|
+
clearTimeout(scanDebounce);
|
|
68
|
+
scanDebounce = setTimeout(async () => {
|
|
69
|
+
try {
|
|
70
|
+
const label = changedFile
|
|
71
|
+
? path.relative(projectRoot, changedFile).replace(/\\/g, '/')
|
|
72
|
+
: '…';
|
|
73
|
+
process.stdout.write(`\r 🔄 ${label} changed, rescanning... `);
|
|
74
|
+
currentData = await (0, scanner_1.scanProject)(projectRoot);
|
|
75
|
+
process.stdout.write(`\r ✅ ${currentData.modules.length} modules` +
|
|
76
|
+
(currentData.features ? `, ${currentData.features.length} features` : '') +
|
|
77
|
+
' \n');
|
|
78
|
+
broadcast('data-updated');
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error('\nRescan error:', err.message);
|
|
82
|
+
}
|
|
83
|
+
}, 600);
|
|
84
|
+
}
|
|
85
|
+
chokidar_1.default.watch([
|
|
86
|
+
'**/*.{ts,tsx,js,jsx,vue,svelte}',
|
|
87
|
+
'viberadar.config.json',
|
|
88
|
+
], {
|
|
89
|
+
cwd: projectRoot,
|
|
90
|
+
ignored: [
|
|
91
|
+
'**/node_modules/**', '**/dist/**', '**/.git/**',
|
|
92
|
+
'**/coverage/**', '**/.next/**', '**/.turbo/**',
|
|
93
|
+
],
|
|
94
|
+
ignoreInitial: true,
|
|
95
|
+
persistent: true,
|
|
96
|
+
})
|
|
97
|
+
.on('add', f => scheduleRescan(path.join(projectRoot, f)))
|
|
98
|
+
.on('change', f => scheduleRescan(path.join(projectRoot, f)))
|
|
99
|
+
.on('unlink', f => scheduleRescan(path.join(projectRoot, f)));
|
|
100
|
+
// ── HTTP server ─────────────────────────────────────────────────────────────
|
|
43
101
|
const server = http.createServer((req, res) => {
|
|
44
102
|
const url = req.url ?? '/';
|
|
45
103
|
if (url === '/') {
|
|
@@ -49,7 +107,19 @@ function startServer({ data, port, projectRoot }) {
|
|
|
49
107
|
}
|
|
50
108
|
if (url === '/api/data') {
|
|
51
109
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
52
|
-
res.end(JSON.stringify(
|
|
110
|
+
res.end(JSON.stringify(currentData));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Server-Sent Events endpoint
|
|
114
|
+
if (url === '/api/events') {
|
|
115
|
+
res.writeHead(200, {
|
|
116
|
+
'Content-Type': 'text/event-stream',
|
|
117
|
+
'Cache-Control': 'no-cache',
|
|
118
|
+
'Connection': 'keep-alive',
|
|
119
|
+
});
|
|
120
|
+
res.write('data: connected\n\n'); // initial ping
|
|
121
|
+
sseClients.add(res);
|
|
122
|
+
req.on('close', () => sseClients.delete(res));
|
|
53
123
|
return;
|
|
54
124
|
}
|
|
55
125
|
res.writeHead(404);
|
|
@@ -63,10 +133,7 @@ function startServer({ data, port, projectRoot }) {
|
|
|
63
133
|
reject(err);
|
|
64
134
|
}
|
|
65
135
|
});
|
|
66
|
-
server.listen(port, '127.0.0.1', () =>
|
|
67
|
-
resolve(server);
|
|
68
|
-
});
|
|
69
|
-
// Graceful shutdown
|
|
136
|
+
server.listen(port, '127.0.0.1', () => resolve(server));
|
|
70
137
|
process.on('SIGINT', () => {
|
|
71
138
|
console.log('\n👋 VibeRadar stopped.');
|
|
72
139
|
server.close(() => process.exit(0));
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/dashboard.html
CHANGED
|
@@ -351,6 +351,12 @@
|
|
|
351
351
|
<h1>VibeRadar</h1>
|
|
352
352
|
<span class="header-project" id="projectName">—</span>
|
|
353
353
|
<span class="header-time" id="scannedAt"></span>
|
|
354
|
+
<span id="liveDot" title="Connecting…" style="
|
|
355
|
+
width:8px; height:8px; border-radius:50%;
|
|
356
|
+
background:var(--dim); display:inline-block;
|
|
357
|
+
margin-left:8px; transition:background 0.3s;
|
|
358
|
+
flex-shrink:0;
|
|
359
|
+
"></span>
|
|
354
360
|
</header>
|
|
355
361
|
|
|
356
362
|
<div class="stats-bar" id="statsBar"></div>
|
|
@@ -749,7 +755,64 @@ document.getElementById('searchInput').oninput = e => {
|
|
|
749
755
|
document.getElementById('panelClose').onclick = closePanel;
|
|
750
756
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') closePanel(); });
|
|
751
757
|
|
|
752
|
-
|
|
758
|
+
// ─── Live reload ──────────────────────────────────────────────────────────────
|
|
759
|
+
function setLiveDot(color, title) {
|
|
760
|
+
const dot = document.getElementById('liveDot');
|
|
761
|
+
dot.style.background = color;
|
|
762
|
+
dot.title = title;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
async function refreshData() {
|
|
766
|
+
try {
|
|
767
|
+
const res = await fetch('/api/data');
|
|
768
|
+
D = await res.json();
|
|
769
|
+
|
|
770
|
+
// Update header timestamp
|
|
771
|
+
document.getElementById('scannedAt').textContent =
|
|
772
|
+
new Date(D.scannedAt).toLocaleTimeString();
|
|
773
|
+
|
|
774
|
+
renderStats();
|
|
775
|
+
renderSidebar();
|
|
776
|
+
renderContent();
|
|
777
|
+
|
|
778
|
+
// Re-open panel if it was open
|
|
779
|
+
const panelOpen = document.getElementById('panel').classList.contains('open');
|
|
780
|
+
if (panelOpen && activePanelKey) {
|
|
781
|
+
if (view === 'features' && D.features) {
|
|
782
|
+
openFeaturePanel(activePanelKey);
|
|
783
|
+
} else {
|
|
784
|
+
const m = D.modules.find(m => m.id === activePanelKey);
|
|
785
|
+
if (m) openModulePanel(m);
|
|
786
|
+
else closePanel();
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// Brief green flash on the dot to signal fresh data
|
|
791
|
+
setLiveDot('#3fb950', 'Live — обновлено только что');
|
|
792
|
+
setTimeout(() => setLiveDot('#3fb950', 'Live — автообновление включено'), 1500);
|
|
793
|
+
} catch (err) {
|
|
794
|
+
console.error('Refresh failed:', err);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
function connectSSE() {
|
|
799
|
+
const es = new EventSource('/api/events');
|
|
800
|
+
|
|
801
|
+
es.onopen = () => setLiveDot('#3fb950', 'Live — автообновление включено');
|
|
802
|
+
|
|
803
|
+
es.addEventListener('data-updated', () => {
|
|
804
|
+
setLiveDot('#e3b341', 'Обновляю данные…');
|
|
805
|
+
refreshData();
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
es.onerror = () => {
|
|
809
|
+
setLiveDot('var(--dim)', 'Нет соединения — переподключаюсь…');
|
|
810
|
+
es.close();
|
|
811
|
+
setTimeout(connectSSE, 3000);
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
init().then(() => connectSSE());
|
|
753
816
|
</script>
|
|
754
817
|
</body>
|
|
755
818
|
</html>
|