diff --git a/packages/csv-stringify/lib/api/normalize_columns.js b/packages/csv-stringify/lib/api/normalize_columns.js index 53e4b2700..67722eae5 100644 --- a/packages/csv-stringify/lib/api/normalize_columns.js +++ b/packages/csv-stringify/lib/api/normalize_columns.js @@ -32,10 +32,11 @@ const normalize_columns = function (columns) { Error('Invalid column definition: property "key" is required'), ]; } - if (column.header === undefined) { - column.header = column.key; - } - newcolumns.push(column); + newcolumns.push({ + ...column, + key: column.key, + header: column.header === undefined ? column.key : column.header, + }); } else { return [ Error("Invalid column definition: expect a string or an object"), diff --git a/packages/csv-stringify/test/option.columns.js b/packages/csv-stringify/test/option.columns.js index a83bd1dd1..b6894c737 100644 --- a/packages/csv-stringify/test/option.columns.js +++ b/packages/csv-stringify/test/option.columns.js @@ -1,8 +1,51 @@ import "should"; import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `columns`", function () { describe("definition", function () { + it("accepts frozen column definitions without adding a header", function () { + const column = Object.freeze({ key: "a" }); + const columns = Object.freeze([column]); + stringifySync([{ a: "value" }], { columns, header: true }).should.eql( + "a\nvalue\n", + ); + Object.keys(column).should.eql(["key"]); + }); + + const structuralColumns = [ + ["inherited", Object.create({ key: "a" })], + ["non-enumerable", Object.defineProperty({}, "key", { value: "a" })], + [ + "getter", + Object.create({ + get key() { + return "a"; + }, + }), + ], + ]; + for (const [name, column] of structuralColumns) { + it(`preserves a ${name} column key`, function () { + stringifySync([{ a: "value" }], { + columns: [column], + header: true, + }).should.eql("a\nvalue\n"); + Object.keys(column).should.eql([]); + }); + } + + it("does not mutate reusable column definitions", function () { + const column = { key: "a" }; + stringifySync([{ a: "first" }], { columns: [column], header: true }); + column.key = "b"; + stringifySync([{ b: "second" }], { + columns: [column], + header: true, + }).should.eql("b\nsecond\n"); + Object.keys(column).should.eql(["key"]); + }); + it("validates option types", function () { (() => { stringify([], { columns: true }, () => {});