bimba-cli 0.7.16 → 0.7.17
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/package.json +1 -1
- package/serve.js +40 -5
package/package.json
CHANGED
package/serve.js
CHANGED
|
@@ -208,7 +208,7 @@ const hmrClient = `
|
|
|
208
208
|
if (msg.type === 'update') _applyUpdate(msg.file, msg.slots);
|
|
209
209
|
else if (msg.type === 'reload') location.reload();
|
|
210
210
|
else if (msg.type === 'error') showError(msg.file, msg.errors);
|
|
211
|
-
else if (msg.type === 'clear-error') clearError();
|
|
211
|
+
else if (msg.type === 'clear-error') clearError(msg.file);
|
|
212
212
|
};
|
|
213
213
|
|
|
214
214
|
ws.onclose = () => setTimeout(connect, 1000);
|
|
@@ -225,6 +225,7 @@ const hmrClient = `
|
|
|
225
225
|
overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
|
|
226
226
|
document.body.appendChild(overlay);
|
|
227
227
|
}
|
|
228
|
+
overlay.dataset.file = file;
|
|
228
229
|
overlay.innerHTML = \`
|
|
229
230
|
<div style="background:#1a1a1a;border:1px solid #ff4444;border-radius:8px;max-width:860px;width:100%;max-height:90vh;overflow:auto;box-shadow:0 0 40px rgba(255,68,68,.3)">
|
|
230
231
|
<div style="background:#ff4444;color:#fff;padding:10px 16px;font-size:13px;font-weight:600;display:flex;justify-content:space-between;align-items:center">
|
|
@@ -241,9 +242,9 @@ const hmrClient = `
|
|
|
241
242
|
\`;
|
|
242
243
|
}
|
|
243
244
|
|
|
244
|
-
function clearError() {
|
|
245
|
+
function clearError(file) {
|
|
245
246
|
const overlay = document.getElementById('__bimba_error__');
|
|
246
|
-
if (overlay) overlay.remove();
|
|
247
|
+
if (overlay && (!file || overlay.dataset.file === file)) overlay.remove();
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
connect();
|
|
@@ -257,6 +258,13 @@ const _prevJs = new Map() // filepath → compiled js — for change detection
|
|
|
257
258
|
const _prevSlots = new Map() // filepath → previous symbol slot count
|
|
258
259
|
const _importScanner = new Bun.Transpiler({ loader: 'js' })
|
|
259
260
|
|
|
261
|
+
function dropFileState(filepath) {
|
|
262
|
+
const abs = path.resolve(filepath)
|
|
263
|
+
_compileCache.delete(abs)
|
|
264
|
+
_prevJs.delete(abs)
|
|
265
|
+
_prevSlots.delete(abs)
|
|
266
|
+
}
|
|
267
|
+
|
|
260
268
|
// Imba compiles tag render-cache slots as anonymous local Symbols at module top
|
|
261
269
|
// level: `var $4 = Symbol(), $11 = Symbol(), ...; let c$0 = Symbol();`. Each
|
|
262
270
|
// re-import of the file creates fresh Symbol objects, so old slot data on live
|
|
@@ -517,6 +525,7 @@ export function serve(entrypoint, flags) {
|
|
|
517
525
|
|
|
518
526
|
let _fadeTimers = []
|
|
519
527
|
let _fadeId = 0
|
|
528
|
+
let _statusFile = null
|
|
520
529
|
let _statusSaved = false
|
|
521
530
|
const _isTTY = process.stdout.isTTY
|
|
522
531
|
|
|
@@ -525,6 +534,16 @@ export function serve(entrypoint, flags) {
|
|
|
525
534
|
_fadeTimers = []
|
|
526
535
|
}
|
|
527
536
|
|
|
537
|
+
function clearStatus(file) {
|
|
538
|
+
if (file && _statusFile && _statusFile !== file) return
|
|
539
|
+
cancelFade()
|
|
540
|
+
if (_statusSaved) {
|
|
541
|
+
process.stdout.write('\x1b[u\x1b[J')
|
|
542
|
+
_statusSaved = false
|
|
543
|
+
}
|
|
544
|
+
_statusFile = null
|
|
545
|
+
}
|
|
546
|
+
|
|
528
547
|
function printStatus(file, state, errors) {
|
|
529
548
|
// non-TTY (pipes, Claude Code bash, CI): plain newline-terminated output,
|
|
530
549
|
// no ANSI cursor tricks, no fade-out — so logs stay readable.
|
|
@@ -552,6 +571,7 @@ export function serve(entrypoint, flags) {
|
|
|
552
571
|
|
|
553
572
|
process.stdout.write('\x1b[s')
|
|
554
573
|
_statusSaved = true
|
|
574
|
+
_statusFile = file
|
|
555
575
|
|
|
556
576
|
if (errors?.length) {
|
|
557
577
|
process.stdout.write(` ${theme.folder(now)} ${theme.filename(file)} ${status}\n`)
|
|
@@ -567,7 +587,10 @@ export function serve(entrypoint, flags) {
|
|
|
567
587
|
_fadeTimers.push(setTimeout(() => {
|
|
568
588
|
if (_fadeId !== myId) return
|
|
569
589
|
process.stdout.write('\x1b[1D \x1b[1D')
|
|
570
|
-
if (i === total)
|
|
590
|
+
if (i === total) {
|
|
591
|
+
_statusSaved = false
|
|
592
|
+
_statusFile = null
|
|
593
|
+
}
|
|
571
594
|
}, 5000 + i * 22))
|
|
572
595
|
}
|
|
573
596
|
}
|
|
@@ -580,6 +603,11 @@ export function serve(entrypoint, flags) {
|
|
|
580
603
|
for (const socket of sockets) socket.send(msg)
|
|
581
604
|
}
|
|
582
605
|
|
|
606
|
+
function clearError(file) {
|
|
607
|
+
clearStatus(file)
|
|
608
|
+
broadcast({ type: 'clear-error', file })
|
|
609
|
+
}
|
|
610
|
+
|
|
583
611
|
const _debounce = new Map()
|
|
584
612
|
|
|
585
613
|
watch(srcDir, { recursive: true }, async (_event, filename) => {
|
|
@@ -591,6 +619,12 @@ export function serve(entrypoint, flags) {
|
|
|
591
619
|
const rel = path.join(path.relative('.', srcDir), filename).replaceAll('\\', '/')
|
|
592
620
|
|
|
593
621
|
try {
|
|
622
|
+
if (!existsSync(filepath)) {
|
|
623
|
+
dropFileState(filepath)
|
|
624
|
+
clearError(rel)
|
|
625
|
+
return
|
|
626
|
+
}
|
|
627
|
+
|
|
594
628
|
const out = await compileFile(filepath)
|
|
595
629
|
|
|
596
630
|
|
|
@@ -604,11 +638,12 @@ export function serve(entrypoint, flags) {
|
|
|
604
638
|
return
|
|
605
639
|
}
|
|
606
640
|
|
|
641
|
+
clearError()
|
|
642
|
+
|
|
607
643
|
// No change at all — skip
|
|
608
644
|
if (out.changeType === 'none' || out.changeType === 'cached') return
|
|
609
645
|
|
|
610
646
|
printStatus(rel, 'ok')
|
|
611
|
-
broadcast({ type: 'clear-error' })
|
|
612
647
|
broadcast({ type: 'update', file: rel, slots: out.slots || 'shifted' })
|
|
613
648
|
} catch(e) {
|
|
614
649
|
printStatus(rel, 'fail', [{ message: e.message }])
|