]> git.ardis.lu - csvio/commitdiff
Implement `.delete()` and `.clear()`
authorArdis Lu <ardisglu@gmail.com>
Sun, 19 Oct 2025 04:30:41 +0000 (21:30 -0700)
committerArdis Lu <ardisglu@gmail.com>
Sun, 19 Oct 2025 04:30:41 +0000 (21:30 -0700)
Useful when a user wants to mostly duplicate an input row but make some minor tweaks. Not having the capability to remove rows leads to unwieldy workarounds.

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

index 32a57f9c45e42eae8e52fa93d8b5481991db3276..7c1efee13edc345017145a8a8cf771cafb3377f2 100644 (file)
@@ -346,15 +346,22 @@ export class CSVNormalizer extends TransformStream {
    * values by *reference* to the underlying `CSVNormalizerField`. This interception makes the `Map` stay in sync with the
    * `row` array.
    * 
-   * Only the methods `.get()`, `.set()`, `.has()` and the property `.size` are supported. All other methods are unsupported.
-   * For more advanced usage, use the underlying `row` object directly.
+   * Only these methods and properties are supported:
+   * - `.get()`
+   * - `.set()`
+   * - `.has()`
+   * - `.delete()`
+   * - `.clear()`
+   * - `.size`
+   * 
+   * All other methods are unsupported. For more advanced usage, use the underlying `row` object directly.
    * 
    * The `displayName` and `emptyField` values of a field cannot be accessed from the `Map`.
    * 
    * Calling `.set()` with a `name` that is not in the row will push a new field to the row.
    * @param {Array<CSVNormalizerField>} row A normalized CSV row.
-   * @returns {Pick<Map<string,any>,'get'|'set'|'has'|'size'>} A `Proxy` over a `Map` object with keys set to the `name` of
-   * each field in the row.
+   * @returns {Pick<Map<string,any>,'get'|'set'|'has'|'delete'|'clear'|'size'>} A `Proxy` over a `Map` object with keys
+   * set to the `name` of each field in the row.
    */
   static toFieldMap(row) {
     const map = new Map();
@@ -383,6 +390,23 @@ export class CSVNormalizer extends TransformStream {
           const targetProp = Reflect.get(target, prop);
           return typeof targetProp === 'function' ? targetProp.bind(target) : targetProp;
         }
+        if (prop === 'delete') {
+          return name => {
+            if (target.has(name)) {
+              const i = row.findIndex(f => f.name === name);
+              row.splice(i, 1);
+              target.delete(name);
+              return true;
+            }
+            return false;
+          }
+        }
+        if (prop === 'clear') {
+          return () => {
+            row.length = 0;
+            target.clear();
+          }
+        }
       }
     });
   }
index d96e04b564ca18a7589731b362c008789befe2f1..97bbc0fc754c1f88f7b6235df525a115f42d9df4 100644 (file)
@@ -238,6 +238,24 @@ suite('CSVNormalizer.toFieldMap', { concurrency: true }, () => {
     map.set('b', 2).set('c', 3).set('d', 4);
     deepStrictEqual(row.length, 4);
   });
+  test('can delete fields', { concurrency: true }, async () => {
+    const row = [{ name: 'a', value: 1 }, { name: 'b', value: 1 }];
+    const map = CSVNormalizer.toFieldMap(row);
+    deepStrictEqual(row.length, 2);
+    ok(map.delete('a'));
+    ok(!map.delete('a'));
+    deepStrictEqual(row.length, 1);
+    ok(map.delete('b'));
+    ok(!map.delete('b'));
+    deepStrictEqual(row.length, 0);
+  });
+  test('can clear fields', { concurrency: true }, async () => {
+    const row = [{ name: 'a', value: 1 }, { name: 'b', value: 1 }];
+    const map = CSVNormalizer.toFieldMap(row);
+    deepStrictEqual(row.length, 2);
+    map.clear();
+    deepStrictEqual(row.length, 0);
+  });
   test('passes through .has() method', { concurrency: true }, async () => {
     const row = [{ name: 'a', value: 1 }];
     const map = CSVNormalizer.toFieldMap(row);
This page took 0.050193 seconds and 4 git commands to generate.