bimba-cli 0.7.17 → 0.7.19
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/index.js +17 -2
- package/package.json +1 -1
- package/serve.js +42 -7
package/index.js
CHANGED
|
@@ -90,6 +90,8 @@ if(flags.help) {
|
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
let bundling = false;
|
|
93
|
+
let rebuildQueued = false;
|
|
94
|
+
let watchTimer = null;
|
|
93
95
|
|
|
94
96
|
// typecheck mode
|
|
95
97
|
if (flags.typecheck || flags.tscheck) {
|
|
@@ -131,7 +133,13 @@ else {
|
|
|
131
133
|
|
|
132
134
|
function watch(callback) {
|
|
133
135
|
if (flags.watch) {
|
|
134
|
-
const watcher = fs.watch(path.dirname(entrypoint), {recursive: true},
|
|
136
|
+
const watcher = fs.watch(path.dirname(entrypoint), {recursive: true}, () => {
|
|
137
|
+
if (watchTimer) clearTimeout(watchTimer);
|
|
138
|
+
watchTimer = setTimeout(() => {
|
|
139
|
+
watchTimer = null;
|
|
140
|
+
callback();
|
|
141
|
+
}, 150);
|
|
142
|
+
});
|
|
135
143
|
|
|
136
144
|
process.on("SIGINT", () => {
|
|
137
145
|
if(flags.clearcache) rmSync(cache, { recursive: true, force: true });
|
|
@@ -146,7 +154,10 @@ function watch(callback) {
|
|
|
146
154
|
|
|
147
155
|
|
|
148
156
|
async function bundle() {
|
|
149
|
-
if (bundling)
|
|
157
|
+
if (bundling) {
|
|
158
|
+
rebuildQueued = true;
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
150
161
|
bundling = true;
|
|
151
162
|
|
|
152
163
|
if (!fs.existsSync(entrypoint)) {
|
|
@@ -220,5 +231,9 @@ async function bundle() {
|
|
|
220
231
|
}
|
|
221
232
|
finally {
|
|
222
233
|
bundling = false;
|
|
234
|
+
if (rebuildQueued) {
|
|
235
|
+
rebuildQueued = false;
|
|
236
|
+
queueMicrotask(bundle);
|
|
237
|
+
}
|
|
223
238
|
};
|
|
224
239
|
}
|
package/package.json
CHANGED
package/serve.js
CHANGED
|
@@ -216,7 +216,15 @@ const hmrClient = `
|
|
|
216
216
|
|
|
217
217
|
// ── Error overlay ──────────────────────────────────────────────────────────
|
|
218
218
|
|
|
219
|
+
function normalizeFile(file) {
|
|
220
|
+
let value = String(file || '').split(String.fromCharCode(92)).join('/');
|
|
221
|
+
while (value.startsWith('./')) value = value.slice(2);
|
|
222
|
+
while (value.startsWith('/')) value = value.slice(1);
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
225
|
+
|
|
219
226
|
function showError(file, errors) {
|
|
227
|
+
const displayFile = normalizeFile(file);
|
|
220
228
|
let overlay = document.getElementById('__bimba_error__');
|
|
221
229
|
if (!overlay) {
|
|
222
230
|
overlay = document.createElement('div');
|
|
@@ -225,11 +233,11 @@ const hmrClient = `
|
|
|
225
233
|
overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
|
|
226
234
|
document.body.appendChild(overlay);
|
|
227
235
|
}
|
|
228
|
-
overlay.dataset.file =
|
|
236
|
+
overlay.dataset.file = displayFile;
|
|
229
237
|
overlay.innerHTML = \`
|
|
230
238
|
<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)">
|
|
231
239
|
<div style="background:#ff4444;color:#fff;padding:10px 16px;font-size:13px;font-weight:600;display:flex;justify-content:space-between;align-items:center">
|
|
232
|
-
<span>Compile error — \${
|
|
240
|
+
<span>Compile error — \${displayFile}</span>
|
|
233
241
|
<span onclick="document.getElementById('__bimba_error__').remove()" style="cursor:pointer;opacity:.7;font-size:16px">✕</span>
|
|
234
242
|
</div>
|
|
235
243
|
\${errors.map(err => \`
|
|
@@ -244,7 +252,10 @@ const hmrClient = `
|
|
|
244
252
|
|
|
245
253
|
function clearError(file) {
|
|
246
254
|
const overlay = document.getElementById('__bimba_error__');
|
|
247
|
-
if (
|
|
255
|
+
if (!overlay) return;
|
|
256
|
+
|
|
257
|
+
const activeFile = overlay.dataset.file;
|
|
258
|
+
if (!file || !activeFile || activeFile === normalizeFile(file)) overlay.remove();
|
|
248
259
|
}
|
|
249
260
|
|
|
250
261
|
connect();
|
|
@@ -609,17 +620,35 @@ export function serve(entrypoint, flags) {
|
|
|
609
620
|
}
|
|
610
621
|
|
|
611
622
|
const _debounce = new Map()
|
|
623
|
+
const _watchVersion = new Map()
|
|
612
624
|
|
|
613
|
-
|
|
625
|
+
function scheduleCompile(filename) {
|
|
626
|
+
filename = filename && String(filename)
|
|
614
627
|
if (!filename || !filename.endsWith('.imba')) return
|
|
615
|
-
if (_debounce.has(filename)) return
|
|
616
|
-
_debounce.set(filename, setTimeout(() => _debounce.delete(filename), 150))
|
|
617
628
|
|
|
629
|
+
const version = (_watchVersion.get(filename) || 0) + 1
|
|
630
|
+
_watchVersion.set(filename, version)
|
|
631
|
+
|
|
632
|
+
const pending = _debounce.get(filename)
|
|
633
|
+
if (pending) clearTimeout(pending)
|
|
634
|
+
|
|
635
|
+
_debounce.set(filename, setTimeout(() => {
|
|
636
|
+
_debounce.delete(filename)
|
|
637
|
+
compileChangedFile(filename, version)
|
|
638
|
+
}, 150))
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function isCurrentChange(filename, version) {
|
|
642
|
+
return _watchVersion.get(filename) === version
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function compileChangedFile(filename, version) {
|
|
618
646
|
const filepath = path.join(srcDir, filename)
|
|
619
647
|
const rel = path.join(path.relative('.', srcDir), filename).replaceAll('\\', '/')
|
|
620
648
|
|
|
621
649
|
try {
|
|
622
650
|
if (!existsSync(filepath)) {
|
|
651
|
+
if (!isCurrentChange(filename, version)) return
|
|
623
652
|
dropFileState(filepath)
|
|
624
653
|
clearError(rel)
|
|
625
654
|
return
|
|
@@ -627,6 +656,7 @@ export function serve(entrypoint, flags) {
|
|
|
627
656
|
|
|
628
657
|
const out = await compileFile(filepath)
|
|
629
658
|
|
|
659
|
+
if (!isCurrentChange(filename, version)) return
|
|
630
660
|
|
|
631
661
|
if (out.errors?.length) {
|
|
632
662
|
printStatus(rel, 'fail', out.errors)
|
|
@@ -638,7 +668,7 @@ export function serve(entrypoint, flags) {
|
|
|
638
668
|
return
|
|
639
669
|
}
|
|
640
670
|
|
|
641
|
-
clearError()
|
|
671
|
+
clearError(rel)
|
|
642
672
|
|
|
643
673
|
// No change at all — skip
|
|
644
674
|
if (out.changeType === 'none' || out.changeType === 'cached') return
|
|
@@ -646,9 +676,14 @@ export function serve(entrypoint, flags) {
|
|
|
646
676
|
printStatus(rel, 'ok')
|
|
647
677
|
broadcast({ type: 'update', file: rel, slots: out.slots || 'shifted' })
|
|
648
678
|
} catch(e) {
|
|
679
|
+
if (!isCurrentChange(filename, version)) return
|
|
649
680
|
printStatus(rel, 'fail', [{ message: e.message }])
|
|
650
681
|
broadcast({ type: 'error', file: rel, errors: [{ message: e.message, snippet: e.stack || e.message }] })
|
|
651
682
|
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
686
|
+
scheduleCompile(filename)
|
|
652
687
|
})
|
|
653
688
|
|
|
654
689
|
// ── HTTP + WebSocket server ────────────────────────────────────────────────
|