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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/serve.js +40 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bimba-cli",
3
- "version": "0.7.16",
3
+ "version": "0.7.17",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/HeapVoid/bimba.git"
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) _statusSaved = false
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 }])