bimba-cli 0.7.15 → 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/typecheck.js +17 -3
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 }])
|
package/typecheck.js
CHANGED
|
@@ -157,7 +157,7 @@ function send(server, seq, command, args) {
|
|
|
157
157
|
|
|
158
158
|
export async function checkImbaTypes(entrypoint, options = {}) {
|
|
159
159
|
const cwd = options.cwd || process.cwd();
|
|
160
|
-
const timeout = Number(options.timeout || process.env.BIMBA_TYPECHECK_TIMEOUT || process.env.IMBA_TS_CHECK_TIMEOUT ||
|
|
160
|
+
const timeout = Number(options.timeout || process.env.BIMBA_TYPECHECK_TIMEOUT || process.env.IMBA_TS_CHECK_TIMEOUT || 30000);
|
|
161
161
|
const scanRoot = getScanRoot(entrypoint, cwd);
|
|
162
162
|
const files = collectImbaFiles(scanRoot);
|
|
163
163
|
|
|
@@ -178,6 +178,7 @@ export async function checkImbaTypes(entrypoint, options = {}) {
|
|
|
178
178
|
let buffer = Buffer.alloc(0);
|
|
179
179
|
const seq = { value: 1 };
|
|
180
180
|
const diagnostics = [];
|
|
181
|
+
let geterrSeq = null;
|
|
181
182
|
|
|
182
183
|
const server = spawn(runner, [
|
|
183
184
|
tsserver,
|
|
@@ -195,7 +196,7 @@ export async function checkImbaTypes(entrypoint, options = {}) {
|
|
|
195
196
|
resolve(success);
|
|
196
197
|
}
|
|
197
198
|
|
|
198
|
-
|
|
199
|
+
function finishWithDiagnostics() {
|
|
199
200
|
const unique = uniqueDiagnostics(diagnostics);
|
|
200
201
|
|
|
201
202
|
if (!unique.length) {
|
|
@@ -207,6 +208,11 @@ export async function checkImbaTypes(entrypoint, options = {}) {
|
|
|
207
208
|
printDiagnostics(cwd, unique);
|
|
208
209
|
console.log(theme.failure(' Failure ') + ` TypeScript found ${theme.count(unique.length)} diagnostic${unique.length > 1 ? 's' : ''}`);
|
|
209
210
|
finish(false);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const timer = setTimeout(() => {
|
|
214
|
+
console.log(theme.failure(' Failure ') + ` Timed out waiting for TypeScript diagnostics after ${theme.time(timeout)} ms`);
|
|
215
|
+
finish(false);
|
|
210
216
|
}, timeout);
|
|
211
217
|
|
|
212
218
|
server.on('error', (error) => {
|
|
@@ -219,7 +225,14 @@ export async function checkImbaTypes(entrypoint, options = {}) {
|
|
|
219
225
|
server.stdout.on('data', chunk => {
|
|
220
226
|
buffer = Buffer.concat([buffer, chunk]);
|
|
221
227
|
buffer = parseMessages(buffer, msg => {
|
|
222
|
-
if (msg.type != 'event'
|
|
228
|
+
if (msg.type != 'event') return;
|
|
229
|
+
|
|
230
|
+
if (msg.event == 'requestCompleted' && msg.body?.request_seq == geterrSeq) {
|
|
231
|
+
finishWithDiagnostics();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!/Diag$/.test(msg.event)) return;
|
|
223
236
|
if (!msg.body?.diagnostics?.length) return;
|
|
224
237
|
|
|
225
238
|
for (const diagnostic of msg.body.diagnostics) {
|
|
@@ -246,6 +259,7 @@ export async function checkImbaTypes(entrypoint, options = {}) {
|
|
|
246
259
|
if (settled) return;
|
|
247
260
|
send(server, seq, 'configure', { preferences: {}, hostInfo: 'bimba-typecheck' });
|
|
248
261
|
for (const file of files) send(server, seq, 'open', { file, projectRootPath: cwd });
|
|
262
|
+
geterrSeq = seq.value;
|
|
249
263
|
send(server, seq, 'geterr', { files, delay: 0 });
|
|
250
264
|
}, 100);
|
|
251
265
|
});
|