diff --git a/src/output.ts b/src/output.ts index 0df8fbe..cee1ff2 100644 --- a/src/output.ts +++ b/src/output.ts @@ -35,7 +35,11 @@ export function formatOutput(data: unknown, format: OutputFormat): string { function formatTable(data: unknown): string { if (Array.isArray(data)) { if (data.length === 0) return "(empty)" - const keys = Object.keys(data[0] as Record) + const keys = [ + ...new Set( + data.flatMap(row => Object.keys(row as Record)), + ), + ] const widths = keys.map(key => Math.max( key.length, diff --git a/test/output.test.ts b/test/output.test.ts index 4a4af80..b414d5c 100644 --- a/test/output.test.ts +++ b/test/output.test.ts @@ -38,6 +38,22 @@ describe("formatOutput", () => { expect(formatOutput([], "table")).toBe("(empty)") }) + it("includes fields that first appear on later array rows", () => { + const data = [ + { name: "CryptoPunk #1", price: "10 ETH" }, + { name: "Bored Ape #2", price: "5 ETH", rarity: "Rare" }, + ] + const result = formatOutput(data, "table") + const lines = result.split("\n") + + expect(lines[0]).toContain("name") + expect(lines[0]).toContain("price") + expect(lines[0]).toContain("rarity") + expect(lines[2]).toContain("CryptoPunk #1") + expect(lines[3]).toContain("Bored Ape #2") + expect(lines[3]).toContain("Rare") + }) + it("returns (empty) for empty object", () => { expect(formatOutput({}, "table")).toBe("(empty)") })