diff --git a/js/spec/binary-client.spec.ts b/js/spec/binary-client.spec.ts index d7c0444..88a85f5 100644 --- a/js/spec/binary-client.spec.ts +++ b/js/spec/binary-client.spec.ts @@ -1,7 +1,7 @@ import * as fs from "fs"; import { Client } from "pg"; import { encodeContent } from "../src"; -import { binaryClient, grpcClient, tmpdir } from "./util"; +import { binaryClient, binaryClientWithLogger, grpcClient, tmpdir } from "./util"; beforeEach(async () => { const client = new Client({ @@ -190,3 +190,22 @@ describe("Gadget file match tests", () => { expect(result).toBe(false); }); }); + +describe.only("The client handles and formats errors coming out of the subprocess call", () => { + it("stderr from the subprocess properly handles non-JSON output streams", async () => { + const project = 1337n; + await grpcClient.newProject(project, []); + + //spy on this output to confirm the tests + + // const spy = jest.spyOn(console, "log"); + try { + const bClientWithLogger = binaryClientWithLogger; + await bClientWithLogger.gcProject(1337, 0); + } catch (err) {} + + // console.log(spy.mock.calls, "calls to spy"); + + // expect(spy.mock.calls).not.toContain("line"); + }); +}); diff --git a/js/spec/util.ts b/js/spec/util.ts index 922fe24..d34098b 100644 --- a/js/spec/util.ts +++ b/js/spec/util.ts @@ -18,6 +18,18 @@ export const binaryClient = new DateiLagerBinaryClient({ command: path.join(__dirname, "..", "..", "bin", "client"), }); +export const binaryClientWithLogger = new DateiLagerBinaryClient({ + server: { + host: "localhost", + }, + token: devAdminToken, + command: path.join(__dirname, "..", "..", "bin", "client"), + logger: { + level: "info", + log: (level, msg, fields) => console.log(msg, fields), + }, +}); + export function tmpdir(): string { const name = Date.now(); const dir = path.resolve(__dirname, "..", "..", "tmp", "tests", "js", name.toString()); diff --git a/js/src/binary-client.ts b/js/src/binary-client.ts index d58c946..5d7ba1d 100644 --- a/js/src/binary-client.ts +++ b/js/src/binary-client.ts @@ -380,23 +380,55 @@ export class DateiLagerBinaryClient { if (this._options.logger && subprocess.stderr) { readline.createInterface(subprocess.stderr).on("line", (line) => { - try { - // we purposefully extract and ignore the `ts` field - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { level, msg, ts, ...fields } = JSON.parse(line) as { - [key: string]: unknown; - level: "debug" | "info" | "warn" | "error"; - msg: string; - ts: string | number; - }; - - this._options.logger?.log(level, msg, fields); - } catch (error) { - this._options.logger?.log("warn", "failed to log line", { error, line }); - } + this.mikesStdErrHandler(line) + // try { + // // we purposefully extract and ignore the `ts` field + // // eslint-disable-next-line @typescript-eslint/no-unused-vars + // const { level, msg, ts, ...fields } = JSON.parse(line) as { + // [key: string]: unknown; + // level: "debug" | "info" | "warn" | "error"; + // msg: string; + // ts: string | number; + // }; + + // this._options.logger?.log(level, msg, fields); + // } catch (error) { + // this._options.logger?.log("warn", "failed to log line", { error, line }); + // } }); } return subprocess; } + + mikesStdErrHandler(line: string) { + try { + // we purposefully extract and ignore the `ts` field + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { level, msg, ts, ...fields } = JSON.parse(line) as { + [key: string]: unknown; + level: "debug" | "info" | "warn" | "error"; + msg: string; + ts: string | number; + }; + + this._options.logger?.log(level, msg, fields); + } catch (error) { + const stdOutChopped = line.split(":"); + if (stdOutChopped.length > 3) { + const errorName = stdOutChopped.slice(1, 2).join().trim(); + const stack = stdOutChopped.slice(2).join().trim(); + + this._options.logger?.log("warn", "failed to log line", { + error: { + name: errorName, + stack: stack, + }, + line, + }); + } else { + this._options.logger?.log("warn", "failed to log line", { error, line }); + } + } + } }