startall 0.0.25 → 0.0.26

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/index.js +28 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -7,6 +7,7 @@ import { join } from 'path';
7
7
  import kill from 'tree-kill';
8
8
  import stripAnsi from 'strip-ansi';
9
9
  import { Database } from 'bun:sqlite';
10
+ import { StringDecoder } from 'string_decoder';
10
11
 
11
12
  // SQLite-backed output line storage
12
13
  class OutputDatabase {
@@ -1358,9 +1359,19 @@ class ProcessManager {
1358
1359
  shell: true,
1359
1360
  });
1360
1361
 
1362
+ // Use StringDecoder to properly handle multi-byte UTF-8 characters
1363
+ // that may be split across data chunks
1364
+ const stdoutDecoder = new StringDecoder('utf8');
1365
+ const stderrDecoder = new StringDecoder('utf8');
1366
+ let stdoutBuffer = '';
1367
+ let stderrBuffer = '';
1368
+
1361
1369
  proc.stdout.on('data', (data) => {
1362
- const text = data.toString();
1363
- const lines = text.split('\n');
1370
+ // Decode properly handles partial multi-byte characters
1371
+ stdoutBuffer += stdoutDecoder.write(data);
1372
+ const lines = stdoutBuffer.split('\n');
1373
+ // Keep the last incomplete line in the buffer
1374
+ stdoutBuffer = lines.pop();
1364
1375
  lines.forEach(line => {
1365
1376
  if (line.trim()) {
1366
1377
  this.addOutputLine(scriptName, line);
@@ -1369,8 +1380,11 @@ class ProcessManager {
1369
1380
  });
1370
1381
 
1371
1382
  proc.stderr.on('data', (data) => {
1372
- const text = data.toString();
1373
- const lines = text.split('\n');
1383
+ // Decode properly handles partial multi-byte characters
1384
+ stderrBuffer += stderrDecoder.write(data);
1385
+ const lines = stderrBuffer.split('\n');
1386
+ // Keep the last incomplete line in the buffer
1387
+ stderrBuffer = lines.pop();
1374
1388
  lines.forEach(line => {
1375
1389
  if (line.trim()) {
1376
1390
  this.addOutputLine(scriptName, line);
@@ -1379,6 +1393,16 @@ class ProcessManager {
1379
1393
  });
1380
1394
 
1381
1395
  proc.on('exit', (code) => {
1396
+ // Flush any remaining buffered content from the decoders
1397
+ const remainingStdout = stdoutBuffer + stdoutDecoder.end();
1398
+ const remainingStderr = stderrBuffer + stderrDecoder.end();
1399
+ if (remainingStdout.trim()) {
1400
+ this.addOutputLine(scriptName, remainingStdout);
1401
+ }
1402
+ if (remainingStderr.trim()) {
1403
+ this.addOutputLine(scriptName, remainingStderr);
1404
+ }
1405
+
1382
1406
  const status = code === 0 ? 'exited' : 'crashed';
1383
1407
  this.processes.set(scriptName, { status, exitCode: code });
1384
1408
  this.addOutputLine(scriptName, `Process exited with code ${code}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "startall",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {