koguma 2.3.2 → 2.3.4

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/cli/log.ts CHANGED
@@ -27,23 +27,30 @@ export const ANSI = {
27
27
  } as const;
28
28
 
29
29
  // ── Logging functions ──────────────────────────────────────────────
30
+ // On TTY, prepend \r\x1b[K (carriage return + clear line) so any
31
+ // in-place status line (spinner, reload counter) is cleared before
32
+ // the permanent message, preventing interleaved output.
33
+
34
+ const CR = process.stdout.isTTY ? '\r\x1b[K' : '';
30
35
 
31
36
  export function log(msg: string): void {
32
- console.log(` ${msg}`);
37
+ process.stdout.write(`${CR} ${msg}\n`);
33
38
  }
34
39
 
35
40
  export function ok(msg: string): void {
36
- console.log(` ${ANSI.BRAND_TEAL}✓${ANSI.RESET} ${msg}`);
41
+ process.stdout.write(`${CR} ${ANSI.BRAND_TEAL}✓${ANSI.RESET} ${msg}\n`);
37
42
  }
38
43
 
39
44
  export function warn(msg: string): void {
40
- console.log(` ${ANSI.YELLOW}⚠${ANSI.RESET} ${msg}`);
45
+ process.stdout.write(`${CR} ${ANSI.YELLOW}⚠${ANSI.RESET} ${msg}\n`);
41
46
  }
42
47
 
43
48
  export function fail(msg: string): void {
44
- console.error(` ${ANSI.BRAND_RED}✗${ANSI.RESET} ${msg}`);
49
+ process.stderr.write(`${CR} ${ANSI.BRAND_RED}✗${ANSI.RESET} ${msg}\n`);
45
50
  }
46
51
 
47
52
  export function header(msg: string): void {
48
- console.log(`\n${ANSI.BOLD}${ANSI.BRAND_TEAL}🐻 ${msg}${ANSI.RESET}\n`);
53
+ process.stdout.write(
54
+ `\n${ANSI.BOLD}${ANSI.BRAND_TEAL}🐻 ${msg}${ANSI.RESET}\n\n`
55
+ );
49
56
  }
package/cli/wrangler.ts CHANGED
@@ -337,97 +337,32 @@ export function wranglerDev(
337
337
  /^▲\s+/, // npm dep install warning lines
338
338
  /^>\s+/, // npm progress lines
339
339
  /^\s*$/, // blank lines
340
- /Reloading local server/, // wrangler dev reload spam
341
- /Local server updated/, // wrangler dev reload (handled as status line)
340
+ /Reloading local server/, // wrangler dev reload — suppress
341
+ /Local server updated/, // wrangler dev reload suppress
342
342
  /Unable to find and open the program executable/ // benign diagnostic
343
343
  ];
344
344
 
345
345
  const shouldSuppress = (line: string): boolean =>
346
346
  suppressPatterns.some(p => p.test(line));
347
347
 
348
- // ── Animated spinner for reload status ──
349
- const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
350
- let reloadCount = 0;
351
- let hasStatusLine = false;
352
- let spinnerFrame = 0;
353
- let spinnerTimer: ReturnType<typeof setInterval> | null = null;
354
- const isTTY = process.stdout.isTTY;
355
-
356
- const drawStatus = (suffix = '') => {
357
- if (!isTTY) return;
358
- const frame = SPINNER_FRAMES[spinnerFrame % SPINNER_FRAMES.length]!;
359
- process.stdout.write(`\r\x1b[K ${frame} reloading${suffix}`);
360
- hasStatusLine = true;
361
- };
362
-
363
- const startSpinner = () => {
364
- if (!isTTY) return;
365
- if (spinnerTimer) return; // already running
366
- drawStatus();
367
- spinnerTimer = setInterval(() => {
368
- spinnerFrame++;
369
- drawStatus();
370
- }, 80);
371
- };
372
-
373
- const stopSpinner = (finalMsg?: string) => {
374
- if (spinnerTimer) {
375
- clearInterval(spinnerTimer);
376
- spinnerTimer = null;
377
- }
378
- if (!isTTY) return;
379
- if (finalMsg) {
380
- process.stdout.write(`\r\x1b[K ✓ ${finalMsg}\n`);
381
- hasStatusLine = false;
382
- }
383
- };
384
-
385
- /** Clear the status line before printing a permanent line */
386
- const clearStatus = () => {
387
- if (spinnerTimer) {
388
- clearInterval(spinnerTimer);
389
- spinnerTimer = null;
390
- }
391
- if (hasStatusLine && isTTY) {
392
- process.stdout.write('\r\x1b[K');
393
- hasStatusLine = false;
394
- }
395
- };
396
-
397
348
  const handleOutput = (data: Buffer, isErr: boolean) => {
398
349
  const text = data.toString();
399
350
  for (const line of text.split('\n')) {
400
351
  const trimmed = line.trim();
401
352
  if (!trimmed) continue;
402
353
 
403
- // Rebrand the "Ready" message before suppress check
354
+ // Rebrand the "Ready" message
404
355
  if (trimmed.includes('Ready on http')) {
405
356
  const urlMatch = trimmed.match(/(https?:\/\/[^\s]+)/);
406
357
  const url = urlMatch?.[1] ?? 'http://localhost:8787';
407
- stopSpinner();
408
- clearStatus();
409
358
  ok(`Server ready → ${url}`);
410
359
  continue;
411
360
  }
412
361
 
413
- // Reload events → animated spinner (overwrites in place)
414
- if (/Reloading local server/.test(trimmed)) {
415
- reloadCount++;
416
- startSpinner();
417
- continue;
418
- }
419
- if (/Local server updated/.test(trimmed)) {
420
- stopSpinner(`reload #${reloadCount}`);
421
- continue;
422
- }
423
-
424
362
  if (shouldSuppress(line)) continue;
425
-
426
363
  if (trimmed.includes('Starting local server')) continue;
427
364
  if (trimmed.includes('Shutting down')) continue;
428
365
 
429
- // Permanent line — clear status first
430
- clearStatus();
431
366
  if (isErr) {
432
367
  warn(trimmed);
433
368
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koguma",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "🐻 A little CMS with big heart — schema-driven, runs on Cloudflare's free tier",
5
5
  "type": "module",
6
6
  "license": "MIT",