From 59aeaaee7d1182ddf3fd61a876cfacefb6652694 Mon Sep 17 00:00:00 2001 From: Jason Staten Date: Sun, 10 Sep 2023 23:32:03 -0600 Subject: [PATCH] stream --- ngron.mjs | 2 +- ngronstream.mjs | 39 +++++++++++++++++++ ngronstream.test.mjs | 91 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 ngronstream.mjs create mode 100644 ngronstream.test.mjs diff --git a/ngron.mjs b/ngron.mjs index 91dd302..6d838d0 100644 --- a/ngron.mjs +++ b/ngron.mjs @@ -28,7 +28,7 @@ const iter = (obj, key, lines) => { export const gronify = (obj) => { const lines = [] - iter(obj, ["json"], lines) + iter(obj, "json", lines) return lines.join('\n'); diff --git a/ngronstream.mjs b/ngronstream.mjs new file mode 100644 index 0000000..9ce1623 --- /dev/null +++ b/ngronstream.mjs @@ -0,0 +1,39 @@ +import { Readable } from "node:stream"; + +const objType = (obj) => { + if (obj === null) { + return 'null' + } + if (Array.isArray(obj)) { + return 'array' + } + + return typeof obj +} + +function* gronGenerator(obj, root = `json`) { + switch (objType(obj)) { + case 'object': + yield `${root}={};\n`; + for (const key in obj) { + yield* gronGenerator(obj[key], `${root}.${key}`); + } + break; + case 'array': + yield `${root}=[];\n`; + for (let i = 0; i < obj.length; i++) { + yield* gronGenerator(obj[i], `${root}[${i}]`); + } + break; + + default: + yield `${root}=${JSON.stringify(obj)};\n`; + + } +} + +export const gronReadStream = (obj) => { + + return Readable.from(gronGenerator(obj)); + +} diff --git a/ngronstream.test.mjs b/ngronstream.test.mjs new file mode 100644 index 0000000..665d3e3 --- /dev/null +++ b/ngronstream.test.mjs @@ -0,0 +1,91 @@ +import test from "node:test" +import assert from "node:assert" +import { gronReadStream } from "./ngronstream.mjs"; + +const asString = async (stream) => { + const chunks = []; + for await (const chunk of stream) { + chunks.push(Buffer.from(chunk)) + } + return Buffer.concat(chunks).toString('utf8'); +} + +test("number", async () => { + const rs = gronReadStream(3); + const result = await asString(rs); + + assert.strictEqual(result, `json=3;\n`) +}); + +test("string", async () => { + const rs = gronReadStream("hello") + const result = await asString(rs); + + assert.strictEqual(result, `json="hello";\n`) +}); + +test("null", async () => { + const rs = gronReadStream(null) + const result = await asString(rs); + + assert.strictEqual(result, `json=null;\n`) +}); + +test("empty obj", async () => { + const rs = gronReadStream({}) + const result = await asString(rs); + + assert.strictEqual(result, `json={};\n`) +}); + +test("empty array", async () => { + const rs = gronReadStream([]) + const result = await asString(rs); + + assert.strictEqual(result, `json=[];\n`) +}); + +test("nested obj", async () => { + const rs = gronReadStream({ one: 1 }) + const result = await asString(rs); + + assert.strictEqual(result, ` +json={}; +json.one=1; +`.trimStart()) +}); + +test("nested array", async () => { + const rs = gronReadStream(["hello", "world"]) + const result = await asString(rs); + + assert.strictEqual(result, ` +json=[]; +json[0]="hello"; +json[1]="world"; +`.trimStart()) +}); + +test("complex", async () => { + const rs = gronReadStream([ + { name: "Alice", startYear: 2001 }, + { name: "Ralph", startYear: 2010 }, + { name: "Jesse", startYear: 2007, tired: true }, + ]); + const result = await asString(rs); + + assert.strictEqual(result, ` +json=[]; +json[0]={}; +json[0].name="Alice"; +json[0].startYear=2001; +json[1]={}; +json[1].name="Ralph"; +json[1].startYear=2010; +json[2]={}; +json[2].name="Jesse"; +json[2].startYear=2007; +json[2].tired=true; +`.trimStart()); + +});