]> git.ardis.lu - csvio/commitdiff
Add `.from` static method
authorArdis Lu <ardisglu@gmail.com>
Thu, 30 Oct 2025 06:46:01 +0000 (23:46 -0700)
committerArdis Lu <ardisglu@gmail.com>
Thu, 30 Oct 2025 06:46:01 +0000 (23:46 -0700)
This method is intended to be the inverse of the `.toObject` method. It is useful to have such a method as a functional (i.e., non-mutating) alternative to `.toFieldMap` to transform rows in a transformation function.

src/normalization.js
test/normalization.test.js

index 7c1efee13edc345017145a8a8cf771cafb3377f2..04cff95cd0b483e34f5e9abfc9f2e1be9ad68b06 100644 (file)
@@ -410,6 +410,19 @@ export class CSVNormalizer extends TransformStream {
       }
     });
   }
+
+  /**
+   * Create a new array of `CSVNormalizerField` from an object.
+   * @param {Object} obj An object to convert.
+   * @returns {Array<CSVNormalizerField>} An array of `CSVNormalizerField`.
+   */
+  static from(obj) {
+    const arr = [];
+    for (const [name, value] of Object.entries(obj)) {
+      arr.push({ name, value });
+    }
+    return arr;
+  }
 }
 
 /**
index e6a92f4dbacc3dd407c61b61b72cf9c616ccd2b9..846eeea4c9bb758a390a830de1ad0a7fb9a360b8 100644 (file)
@@ -207,6 +207,14 @@ suite('CSVNormalizer.toObject', { concurrency: true }, () => {
     const obj = CSVNormalizer.toObject(row);
     deepStrictEqual(obj.a.b[0], 1n);
   });
+  test('is the inverse of .from', { concurrency: true }, async () => {
+    const obj = {
+      'a': '1',
+      'b': '2',
+      'c': '3'
+    };
+    deepStrictEqual(CSVNormalizer.toObject(CSVNormalizer.from(obj)), obj);
+  });
 });
 
 suite('CSVNormalizer.toFieldMap', { concurrency: true }, () => {
@@ -269,6 +277,40 @@ suite('CSVNormalizer.toFieldMap', { concurrency: true }, () => {
   });
 });
 
+suite('CSVNormalizer.from', { concurrency: true }, () => {
+  test('converts a simple object', { concurrency: true }, async () => {
+    deepStrictEqual(CSVNormalizer.from({
+      'columnA': 'valueA',
+      'columnB': 'valueB'
+    }), [
+      { name: 'columnA', value: 'valueA' },
+      { name: 'columnB', value: 'valueB' },
+    ]);
+  });
+  test('converts an empty object', { concurrency: true }, async () => {
+    deepStrictEqual(CSVNormalizer.from({}), []);
+  });
+  test('preserves complex value types', { concurrency: true }, async () => {
+    deepStrictEqual(CSVNormalizer.from({
+      'a': 123n,
+      'b': { 'b-1': 'b-2' },
+      'c': ['c', 2, 3n]
+    }), [
+      { name: 'a', value: 123n },
+      { name: 'b', value: { 'b-1': 'b-2' } },
+      { name: 'c', value: ['c', 2, 3n] },
+    ]);
+  });
+  test('is the inverse of .toObject', { concurrency: true }, async () => {
+    const row = [
+      { name: 'a', value: '1' },
+      { name: 'b', value: '2' },
+      { name: 'c', value: '3' },
+    ];
+    deepStrictEqual(CSVNormalizer.from(CSVNormalizer.toObject(row)), row);
+  });
+});
+
 suite('CSVNormalizer', { concurrency: true }, () => {
   test('accepts string shorthand to set headers', { concurrency: true }, async () => {
     await createCSVMockStream([
This page took 0.036596 seconds and 4 git commands to generate.