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.
@@ -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;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,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,IAAI,EAAE,WAAW,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAuC5F"}
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"}
@@ -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(data, null, 2));
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));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,kCAuCC;AAvDD,2CAA6B;AAC7B,uCAAyB;AACzB,2CAA6B;AAS7B,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CACpC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC,EAC5C,OAAO,CACR,CAAC;AAEF,SAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAiB;IACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;YAE3B,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAChB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;gBACnE,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;YAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;gBACxB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,mDAAmD,CAAC,CAAC,CAAC;YACrF,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;YACpC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -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
- init();
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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viberadar",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Live module map with test coverage for vibecoding projects",
5
5
  "main": "./dist/cli.js",
6
6
  "bin": {