From f1f696f2af70de404b2b73cfae7127536c42e7a4 Mon Sep 17 00:00:00 2001 From: lux-liang <249971141+lux-liang@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:28:54 +0800 Subject: [PATCH] fix(csv-generate): emit object records independently of column values --- packages/csv-generate/lib/api/read.js | 10 +++---- packages/csv-generate/test/api.sync.js | 13 +++++++++ .../csv-generate/test/options.object_mode.js | 29 +++++++++++++++++++ packages/csv-generate/test/options.sleep.js | 17 +++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/packages/csv-generate/lib/api/read.js b/packages/csv-generate/lib/api/read.js index 8d7b63b85..b072b98c0 100644 --- a/packages/csv-generate/lib/api/read.js +++ b/packages/csv-generate/lib/api/read.js @@ -55,12 +55,10 @@ const read = (options, state, size, push, close) => { } // Obtain record length if (options.objectMode) { - recordLength = 0; - // recordLength is currently equal to the number of columns - // This is wrong and shall equal to 1 record only - for (const column of record) { - recordLength += column.length; - } + // Let the stream request each record independently of its column values. + state.count_created++; + push(record); + return; } else { // Stringify the record record = diff --git a/packages/csv-generate/test/api.sync.js b/packages/csv-generate/test/api.sync.js index cd4443faa..1dbef660e 100644 --- a/packages/csv-generate/test/api.sync.js +++ b/packages/csv-generate/test/api.sync.js @@ -31,4 +31,17 @@ describe("api sync", function () { const data = generate({ length: 1000, objectMode: true }); data.length.should.eql(1000); }); + + it("preserves supported column values in objectMode", function () { + const data = generate({ + length: 3, + objectMode: true, + columns: [() => "value", () => null, () => 42, () => ""], + }); + data.should.eql([ + ["value", null, 42, ""], + ["value", null, 42, ""], + ["value", null, 42, ""], + ]); + }); }); diff --git a/packages/csv-generate/test/options.object_mode.js b/packages/csv-generate/test/options.object_mode.js index 267f8dc18..c7e54ebde 100644 --- a/packages/csv-generate/test/options.object_mode.js +++ b/packages/csv-generate/test/options.object_mode.js @@ -2,6 +2,35 @@ import "should"; import { generate } from "../lib/index.js"; describe("Option `objectMode`", function () { + for (const value of [42, "", "value"]) { + it(`streams ${JSON.stringify(value)} without generating all records first`, function (next) { + let generated = 0; + let generatedAtFirstRecord; + const records = []; + const generator = generate({ + objectMode: true, + highWaterMark: 1, + length: 100, + columns: [ + () => { + generated++; + return value; + }, + ], + }); + generator.on("data", (record) => { + generatedAtFirstRecord ??= generated; + records.push(record); + }); + generator.on("error", next); + generator.on("end", () => { + generatedAtFirstRecord.should.be.within(1, 2); + records.should.eql(Array.from({ length: 100 }, () => [value])); + next(); + }); + }); + } + it("return an array of array", function (next) { this.timeout(1000000); generate({ seed: 1, objectMode: true, length: 4 }, (err, data) => { diff --git a/packages/csv-generate/test/options.sleep.js b/packages/csv-generate/test/options.sleep.js index 17d1a5f0b..3615d3c2d 100644 --- a/packages/csv-generate/test/options.sleep.js +++ b/packages/csv-generate/test/options.sleep.js @@ -2,6 +2,23 @@ import "should"; import { generate } from "../lib/index.js"; describe("Option `sleep`", function () { + for (const value of [42, "", null, "value"]) { + it(`preserves all object records containing ${JSON.stringify(value)}`, async function () { + const data = await new Promise((resolve, reject) => { + generate( + { + objectMode: true, + length: 5, + sleep: 5, + columns: [() => value], + }, + (err, data) => (err ? reject(err) : resolve(data)), + ); + }); + data.should.eql(Array.from({ length: 5 }, () => [value])); + }); + } + it("as integer above 0", function (next) { this.timeout(10000); generate({ duration: 1000, sleep: 100, objectMode: true }, (err, data) => {