Skip to content

Commit 99cca82

Browse files
committed
Fix truncated stdout when piping more than 64kb
1 parent 21c3d4b commit 99cca82

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

packages/cli/src/index.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { major, minor } from "semver";
1717
import { getExitCode } from "./getExitCode.js";
1818
import { applyProfile, profiles } from "./profiles.js";
1919
import { write } from "./write.js";
20+
import { Writable } from "stream";
2021

2122
const packageJson = createRequire(import.meta.url)("../package.json");
2223
const version = packageJson.version;
@@ -99,8 +100,13 @@ particularly ESM-related module resolution issues.`,
99100
applyProfile(opts.profile, opts);
100101
}
101102

103+
let out: Writable = process.stdout;
102104
if (opts.quiet) {
103-
console.log = () => {};
105+
out = new (class extends Writable {
106+
_write(_chunk: any, _encoding: BufferEncoding, callback: (error?: Error | null) => void) {
107+
callback();
108+
}
109+
})();
104110
}
105111

106112
if (!opts.color) {
@@ -224,7 +230,7 @@ particularly ESM-related module resolution issues.`,
224230
result.problems = groupProblemsByKind(analysis.problems);
225231
}
226232

227-
await write(JSON.stringify(result, undefined, 2) + "\n");
233+
await write(JSON.stringify(result, undefined, 2), out);
228234

229235
if (deleteTgz) {
230236
await unlink(deleteTgz);
@@ -238,12 +244,12 @@ particularly ESM-related module resolution issues.`,
238244
return;
239245
}
240246

241-
console.log();
247+
await write("", out);
242248
if (analysis.types) {
243-
console.log(await render.typed(analysis, opts));
249+
await write(await render.typed(analysis, opts), out);
244250
process.exitCode = getExitCode(analysis, opts);
245251
} else {
246-
console.log(render.untyped(analysis as core.UntypedResult));
252+
await write(render.untyped(analysis as core.UntypedResult), out);
247253
}
248254

249255
if (deleteTgz) {

packages/cli/src/write.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
import { Readable, Writable } from "node:stream";
2-
import { pipeline } from "node:stream/promises";
32

43
// JSON output is often longer than 64 kb, so we need to use streams to write it to stdout
54
// in order to avoid truncation when piping to other commands.
6-
export function write(data: string, out: Writable = process.stdout): Promise<void> {
7-
const stream = new Readable();
8-
stream.push(data);
9-
stream.push(null);
10-
return pipeline(stream, out);
5+
export async function write(data: string, out: Writable): Promise<void> {
6+
return new Promise((resolve, reject) => {
7+
const stream = new Readable({
8+
read() {
9+
this.push(data);
10+
this.push("\n");
11+
this.push(null);
12+
},
13+
});
14+
15+
stream.on("data", (chunk) => {
16+
out.write(chunk);
17+
});
18+
19+
stream.on("end", () => {
20+
resolve();
21+
});
22+
23+
out.on("error", (err) => {
24+
reject(err);
25+
});
26+
});
1127
}

packages/cli/test/snapshots.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { execFileSync, type SpawnSyncReturns } from "child_process";
12
import { access, readFile, writeFile } from "fs/promises";
2-
import { execSync, type SpawnSyncReturns } from "child_process";
33
import assert from "node:assert";
44
import path from "node:path";
55
import { after, describe, test } from "node:test";
@@ -10,7 +10,7 @@ function resolveFileRelativePath(relPath: string) {
1010
return path.resolve(directoryPath, relPath);
1111
}
1212

13-
const attw = `node ${resolveFileRelativePath("../../dist/index.js")}`;
13+
const attw = resolveFileRelativePath("../../dist/index.js");
1414
const updateSnapshots = process.env.UPDATE_SNAPSHOTS || process.env.U;
1515
const testFilter = (process.env.TEST_FILTER || process.env.T)?.toLowerCase();
1616

@@ -91,7 +91,8 @@ describe("snapshots", async () => {
9191
let stderr = "";
9292
let exitCode = 0;
9393
try {
94-
stdout = execSync(`${attw} ${tarballPath} ${options ?? defaultOpts}`, {
94+
stdout = execFileSync(process.execPath, [attw, tarballPath, ...(options ?? defaultOpts).split(" ")], {
95+
maxBuffer: 1024 * 1024 * 1024,
9596
encoding: "utf8",
9697
env: { ...process.env, FORCE_COLOR: "0" },
9798
});

0 commit comments

Comments
 (0)