Repository: jeremydaly/dynamodb-toolbox (ts)

Issue:
expressionBuilder mutates expressions
Right now `expressionBuilder` will mutate input expressions.
This can be a problem when we reuse prebuilt expressions across multiple queries/entities.
I myself spent couple of hours figuring this out.

Such test
```TypeScript
it("doesn't mutate input expression", () => {
    let exp = { attr: 'a', eq: 'b' }
    expressionBuilder(exp,TestTable,'TestEntity')
    expect(exp).toEqual({ attr: 'a', eq: 'b' })
  }))
```
Will fail with:
```Jest
expect(received).toEqual(expected) // deep equality

    - Expected  - 0
    + Received  + 1

      Object {
        "attr": "a",
    +   "entity": "TestEntity",
        "eq": "b",
      }

      361 |     let exp = { attr: 'a', eq: 'b' }
      362 |     expressionBuilder(exp ,TestTable,'TestEntity')
    > 363 |     expect(exp).toEqual({ attr: 'a', eq: 'b' })
          |                 ^
      364 |   })
      365 | })
      366 |
```
I've submitted a PR with a fix linked below

Pull request description:
[expressionBuilder] Don't mutate input expressions
Copy expressions before processing to avoid mutations.

closes #228 

Patch:
diff --git a/src/lib/expressionBuilder.ts b/src/lib/expressionBuilder.ts
index d2966533..5d693687 100644
--- a/src/lib/expressionBuilder.ts
+++ b/src/lib/expressionBuilder.ts
@@ -76,9 +76,9 @@ const buildExpression = <
 
       // Else process the clause
     } else {
-      // Make sure TS knows this is a FilterExpression
-      const exp = clauses[id] as FilterExpression
-
+     // Make sure TS knows this is a FilterExpression; copy to avoid mutation
+      const exp = {...clauses[id]} as FilterExpression
+      
       // Increment group counter for each clause
       group++ // guarantees uniqueness
 


Test patch:
diff --git a/src/__tests__/expressionBuilder.unit.test.ts b/src/__tests__/expressionBuilder.unit.test.ts
index 4c77ff85..f3bce1b5 100644
--- a/src/__tests__/expressionBuilder.unit.test.ts
+++ b/src/__tests__/expressionBuilder.unit.test.ts
@@ -375,4 +375,13 @@ describe('expressionBuilder', () => {
       `A condition is required`
     )
   })
+
+  it("doesn't mutate input expression", () => {
+    let expObj = { attr: 'a', eq: 'b' }
+    let expArr = [{ attr: 'a', eq: 'b' }]
+    expressionBuilder(expObj,TestTable,'TestEntity')
+    expressionBuilder(expArr,TestTable,'TestEntity')
+    expect(expObj).toEqual({ attr: 'a', eq: 'b' })
+    expect(expArr).toEqual([{ attr: 'a', eq: 'b' }])
+  })
 })