From 1a84622f11ad4bbe3759bb1e9f09bbec8c00da3a Mon Sep 17 00:00:00 2001 From: Sri Charan Date: Mon, 12 Oct 2026 13:52:15 +0000 Subject: [PATCH 1/2] fix(csv-stringify): preserve caller cast configuration --- .../lib/api/normalize_options.js | 17 ++++++- packages/csv-stringify/test/option.cast.js | 44 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/packages/csv-stringify/lib/api/normalize_options.js b/packages/csv-stringify/lib/api/normalize_options.js index 32e63033c..339387c23 100644 --- a/packages/csv-stringify/lib/api/normalize_options.js +++ b/packages/csv-stringify/lib/api/normalize_options.js @@ -199,8 +199,21 @@ const normalize_options = function (opts) { // Normalize option `cast` if (options.cast === undefined || options.cast === null) { options.cast = {}; - } else { - // todo + } else if ( + typeof options.cast === "object" || + typeof options.cast === "function" + ) { + options.cast = { + ...options.cast, + bigint: options.cast.bigint, + boolean: options.cast.boolean, + date: options.cast.date, + number: options.cast.number, + object: options.cast.object, + string: options.cast.string, + null: options.cast.null, + undefined: options.cast.undefined, + }; } // Normalize option cast.bigint if (options.cast.bigint === undefined || options.cast.bigint === null) { diff --git a/packages/csv-stringify/test/option.cast.js b/packages/csv-stringify/test/option.cast.js index 83fcef78a..ec4cd77fe 100644 --- a/packages/csv-stringify/test/option.cast.js +++ b/packages/csv-stringify/test/option.cast.js @@ -1,8 +1,52 @@ import "should"; +import assert from "node:assert/strict"; import { stringify } from "../lib/index.js"; import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `cast`", function () { + describe("configuration", function () { + for (const frozen of [false, true]) { + it(`preserves ${frozen ? "frozen" : "mutable"} options in the sync API`, function () { + const string = (value) => value.toUpperCase(); + const cast = { string, number: null }; + if (frozen) Object.freeze(cast); + for (let i = 0; i < 2; i++) { + assert.equal(stringifySync([["value", 42]], { cast }), "VALUE,42\n"); + } + assert.deepEqual(cast, { string, number: null }); + }); + + it(`preserves ${frozen ? "frozen" : "mutable"} options in the callback API`, function (next) { + const string = (value) => value.toUpperCase(); + const cast = { string }; + if (frozen) Object.freeze(cast); + stringify([["value", 42]], { cast }, (err, output) => { + if (err) return next(err); + assert.equal(output, "VALUE,42\n"); + assert.deepEqual(cast, { string }); + next(); + }); + }); + } + + it("preserves inherited and non-enumerable custom casters", function () { + const cast = Object.create({ string: (value) => value.toUpperCase() }); + Object.defineProperty(cast, "number", { value: () => "number" }); + assert.equal(stringifySync([["value", 42]], { cast }), "VALUE,number\n"); + }); + + it("preserves custom null and undefined casters", function () { + const cast = { + null: () => "null", + undefined: () => "missing", + }; + assert.equal( + stringifySync([[null, undefined]], { cast }), + "null,missing\n", + ); + }); + }); + describe("udf", function () { it("boolean must return a string", function (next) { stringify( From 2e1cc93e5696ee1d725ddffd67ce3167b28afeac Mon Sep 17 00:00:00 2001 From: sricharanreddycheruku Date: Tue, 13 Oct 2026 12:01:07 +0000 Subject: [PATCH 2/2] fix(csv-stringify): simplify cast configuration handling --- .../lib/api/normalize_options.js | 17 +------ packages/csv-stringify/test/option.cast.js | 44 ------------------- packages/csv-stringify/test/option.cast.ts | 11 +++++ 3 files changed, 13 insertions(+), 59 deletions(-) diff --git a/packages/csv-stringify/lib/api/normalize_options.js b/packages/csv-stringify/lib/api/normalize_options.js index 339387c23..a1b58d70c 100644 --- a/packages/csv-stringify/lib/api/normalize_options.js +++ b/packages/csv-stringify/lib/api/normalize_options.js @@ -199,21 +199,8 @@ const normalize_options = function (opts) { // Normalize option `cast` if (options.cast === undefined || options.cast === null) { options.cast = {}; - } else if ( - typeof options.cast === "object" || - typeof options.cast === "function" - ) { - options.cast = { - ...options.cast, - bigint: options.cast.bigint, - boolean: options.cast.boolean, - date: options.cast.date, - number: options.cast.number, - object: options.cast.object, - string: options.cast.string, - null: options.cast.null, - undefined: options.cast.undefined, - }; + } else { + options.cast = { ...options.cast }; } // Normalize option cast.bigint if (options.cast.bigint === undefined || options.cast.bigint === null) { diff --git a/packages/csv-stringify/test/option.cast.js b/packages/csv-stringify/test/option.cast.js index ec4cd77fe..83fcef78a 100644 --- a/packages/csv-stringify/test/option.cast.js +++ b/packages/csv-stringify/test/option.cast.js @@ -1,52 +1,8 @@ import "should"; -import assert from "node:assert/strict"; import { stringify } from "../lib/index.js"; import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `cast`", function () { - describe("configuration", function () { - for (const frozen of [false, true]) { - it(`preserves ${frozen ? "frozen" : "mutable"} options in the sync API`, function () { - const string = (value) => value.toUpperCase(); - const cast = { string, number: null }; - if (frozen) Object.freeze(cast); - for (let i = 0; i < 2; i++) { - assert.equal(stringifySync([["value", 42]], { cast }), "VALUE,42\n"); - } - assert.deepEqual(cast, { string, number: null }); - }); - - it(`preserves ${frozen ? "frozen" : "mutable"} options in the callback API`, function (next) { - const string = (value) => value.toUpperCase(); - const cast = { string }; - if (frozen) Object.freeze(cast); - stringify([["value", 42]], { cast }, (err, output) => { - if (err) return next(err); - assert.equal(output, "VALUE,42\n"); - assert.deepEqual(cast, { string }); - next(); - }); - }); - } - - it("preserves inherited and non-enumerable custom casters", function () { - const cast = Object.create({ string: (value) => value.toUpperCase() }); - Object.defineProperty(cast, "number", { value: () => "number" }); - assert.equal(stringifySync([["value", 42]], { cast }), "VALUE,number\n"); - }); - - it("preserves custom null and undefined casters", function () { - const cast = { - null: () => "null", - undefined: () => "missing", - }; - assert.equal( - stringifySync([[null, undefined]], { cast }), - "null,missing\n", - ); - }); - }); - describe("udf", function () { it("boolean must return a string", function (next) { stringify( diff --git a/packages/csv-stringify/test/option.cast.ts b/packages/csv-stringify/test/option.cast.ts index 5d27be58a..158f99c8f 100644 --- a/packages/csv-stringify/test/option.cast.ts +++ b/packages/csv-stringify/test/option.cast.ts @@ -1,8 +1,19 @@ import "should"; import dedent from "dedent"; import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `cast`", function () { + it("preserves frozen options in the sync API", function () { + const string = (value: string) => value.toUpperCase(); + const cast = { string }; + Object.freeze(cast); + for (let i = 0; i < 2; i++) { + stringifySync([["value", 42]], { cast }).should.equal("VALUE,42\n"); + } + cast.should.eql({ string }); + }); + describe("default", function () { it("default BigInt formatter", function (next) { stringify(