diff --git a/src/converters/dasel.ts b/src/converters/dasel.ts index 741d325..c895d3e 100644 --- a/src/converters/dasel.ts +++ b/src/converters/dasel.ts @@ -11,6 +11,10 @@ export const properties = { }, }; +export function buildDaselArgs(filePath: string, fileType: string, convertTo: string): string[] { + return ["--var", `data=${fileType}:file:${filePath}`, "--out", convertTo, "$data"]; +} + export async function convert( filePath: string, fileType: string, @@ -19,14 +23,10 @@ export async function convert( options?: unknown, execFile: ExecFileFn = execFileOriginal, // to make it mockable ): Promise { - const args: string[] = []; - - args.push("--file", filePath); - args.push("--read", fileType); - args.push("--write", convertTo); + const args = buildDaselArgs(filePath, fileType, convertTo); return new Promise((resolve, reject) => { - execFile("dasel", args, (error, stdout, stderr) => { + const childProcess = execFile("dasel", args, (error, stdout, stderr) => { if (error) { reject(`error: ${error}`); return; @@ -44,5 +44,7 @@ export async function convert( } }); }); + + childProcess?.stdin?.end(); }); } diff --git a/src/converters/types.ts b/src/converters/types.ts index 1bfe36c..9e5b048 100644 --- a/src/converters/types.ts +++ b/src/converters/types.ts @@ -1,11 +1,11 @@ -import { ExecFileOptions } from "child_process"; +import type { ChildProcess, ExecFileOptions } from "child_process"; export type ExecFileFn = ( cmd: string, args: string[], callback: (err: Error | null, stdout: string, stderr: string) => void, options?: ExecFileOptions, -) => void; +) => ChildProcess | void; export type ConvertFnWithExecFile = ( filePath: string, diff --git a/tests/converters/dasel.test.ts b/tests/converters/dasel.test.ts index b08bed9..9e5a86a 100644 --- a/tests/converters/dasel.test.ts +++ b/tests/converters/dasel.test.ts @@ -1,6 +1,6 @@ import fs from "fs"; import { beforeEach, afterEach, expect, test, describe } from "bun:test"; -import { convert } from "../../src/converters/dasel"; +import { buildDaselArgs, convert } from "../../src/converters/dasel"; import type { ExecFileFn } from "../../src/converters/types"; const originalWriteFile = fs.writeFile; @@ -21,6 +21,16 @@ describe("convert", () => { fs.writeFile = originalWriteFile; }); + test("should build dasel v3 arguments", () => { + expect(buildDaselArgs("input.yaml", "yaml", "json")).toEqual([ + "--var", + "data=yaml:file:input.yaml", + "--out", + "json", + "$data", + ]); + }); + test("should call dasel with correct arguments and write output", async () => { let calledArgs: Parameters = ["", [], () => {}]; mockExecFile = (cmd, args, callback) => { @@ -48,11 +58,23 @@ describe("convert", () => { ); expect(calledArgs[0]).toBe("dasel"); - expect(calledArgs[1]).toEqual(["--file", "input.yaml", "--read", "yaml", "--write", "json"]); + expect(calledArgs[1]).toEqual(["--var", "data=yaml:file:input.yaml", "--out", "json", "$data"]); expect(writeFileCalled).toBe(true); expect(result).toBe("Done"); }); + test("should close dasel stdin so v3 does not wait for input", async () => { + let stdinEnded = false; + mockExecFile = (cmd, args, callback) => { + callback(null, "output-data", ""); + return { stdin: { end: () => (stdinEnded = true) } } as ReturnType; + }; + + await convert("input.yaml", "yaml", "json", "output.json", undefined, mockExecFile); + + expect(stdinEnded).toBe(true); + }); + test("should reject if execFile returns an error", async () => { mockExecFile = (cmd, args, callback) => callback(new Error("fail"), "", ""); await expect(