Repository: dynamoosejs/dynamoose (js)

Issue:
Schema attribute `set` should be executed on `Model.update()`, too
Currently having a `set` function on a schema's attribute it gets executed only on `Model.create()` but not on `Model.updated()`. IMO it should get executed on both functions.

Pull request description:
Set with Model.update
This PR fixes an issue where `set` wouldn't be called with `Model.update`.

Closes #819

Patch:
diff --git a/lib/Model.js b/lib/Model.js
index 7dba4046..caf20147 100644
--- a/lib/Model.js
+++ b/lib/Model.js
@@ -425,7 +425,7 @@ Model.prototype.update = function (keyObj, updateObj, settings = {}, callback) {
 	let index = 0;
 	const getUpdateExpressionObject = async () => {
 		const updateTypes = [
-			{"name": "$SET", "operator": " = ", "objectFromSchemaSettings": {"validate": true, "enum": true, "forceDefault": true, "required": "nested"}},
+			{"name": "$SET", "operator": " = ", "objectFromSchemaSettings": {"validate": true, "enum": true, "forceDefault": true, "required": "nested", "modifiers": ["set"]}},
 			{"name": "$ADD", "objectFromSchemaSettings": {"forceDefault": true}},
 			{"name": "$REMOVE", "attributeOnly": true, "objectFromSchemaSettings": {"required": true, "defaults": true}}
 		].reverse();


Test patch:
diff --git a/test/Model.js b/test/Model.js
index 27e59f60..cb455bc3 100644
--- a/test/Model.js
+++ b/test/Model.js
@@ -2689,6 +2689,81 @@ describe("Model", () => {
 					});
 				});
 
+				it("Should call set modifier if setting property", async () => {
+					updateItemFunction = () => Promise.resolve({});
+					User = new dynamoose.Model("User", {"id": Number, "name": {"type": String, "set": (val) => `${val}-set`}});
+					await callType.func(User).bind(User)({"id": 1}, {"name": "Bob"});
+					expect(updateItemParams).to.be.an("object");
+					expect(updateItemParams).to.eql({
+						"ExpressionAttributeNames": {
+							"#a0": "name"
+						},
+						"ExpressionAttributeValues": {
+							":v0": {
+								"S": "Bob-set"
+							}
+						},
+						"UpdateExpression": "SET #a0 = :v0",
+						"Key": {
+							"id": {
+								"N": "1"
+							}
+						},
+						"TableName": "User",
+						"ReturnValues": "ALL_NEW"
+					});
+				});
+
+				it("Should call set modifier if setting property using $SET", async () => {
+					updateItemFunction = () => Promise.resolve({});
+					User = new dynamoose.Model("User", {"id": Number, "name": {"type": String, "set": (val) => `${val}-set`}});
+					await callType.func(User).bind(User)({"id": 1}, {"$SET": {"name": "Bob"}});
+					expect(updateItemParams).to.be.an("object");
+					expect(updateItemParams).to.eql({
+						"ExpressionAttributeNames": {
+							"#a0": "name"
+						},
+						"ExpressionAttributeValues": {
+							":v0": {
+								"S": "Bob-set"
+							}
+						},
+						"UpdateExpression": "SET #a0 = :v0",
+						"Key": {
+							"id": {
+								"N": "1"
+							}
+						},
+						"TableName": "User",
+						"ReturnValues": "ALL_NEW"
+					});
+				});
+
+				it("Should not call set modifier if adding to property", async () => {
+					updateItemFunction = () => Promise.resolve({});
+					User = new dynamoose.Model("User", {"id": Number, "age": {"type": Number, "set": (val) => val * 10}});
+					await callType.func(User).bind(User)({"id": 1}, {"$ADD": {"age": 5}});
+					expect(updateItemParams).to.be.an("object");
+					expect(updateItemParams).to.eql({
+						"ExpressionAttributeNames": {
+							"#a0": "age"
+						},
+						"ExpressionAttributeValues": {
+							":v0": {
+								"N": "5"
+							}
+						},
+						"UpdateExpression": "ADD #a0 :v0",
+						"Key": {
+							"id": {
+								"N": "1"
+							}
+						},
+						"TableName": "User",
+						"ReturnValues": "ALL_NEW"
+					});
+				});
+
 				it("Should throw error if AWS throws error", () => {
 					updateItemFunction = () => Promise.reject({"error": "ERROR"});