Skip to content

Commit

Permalink
Merge branch 'master' into queryImprovements
Browse files Browse the repository at this point in the history
  • Loading branch information
fishcharlie committed Apr 18, 2020
2 parents 3a25cf8 + 780dc72 commit b6913a0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 11 deletions.
26 changes: 15 additions & 11 deletions lib/Document.js
Expand Up @@ -10,6 +10,9 @@ const staticMethods = {
"isDynamoObject": function (object, recurrsive = false) {
// This function will check to see if a nested object is valid by calling Document.isDynamoObject recursively
const isValid = (value) => {
if (typeof value === "undefined" || value === null) {
return false;
}
const keys = Object.keys(value);
const key = keys[0];
const nestedResult = (typeof value[key] === "object" && !(value[key] instanceof Buffer) ? (Array.isArray(value[key]) ? value[key].every((value) => this.isDynamoObject(value, true)) : this.isDynamoObject(value[key])) : true);
Expand Down Expand Up @@ -224,6 +227,18 @@ function DocumentCarrier(model) {
utils.object.set(returnObject, key, typeDetails[settings.type](value));
}
});
if (settings.modifiers) {
await Promise.all(settings.modifiers.map((modifier) => {
return Promise.all(Document.attributesWithSchema(returnObject).map(async (key) => {
const value = utils.object.get(returnObject, key);
const modifierFunction = await model.schema.getAttributeSettingValue(modifier, key, {"returnFunction": true});
const isValueUndefined = typeof value === "undefined" || value === null;
if (modifierFunction && !isValueUndefined) {
utils.object.set(returnObject, key, await modifierFunction(value));
}
}));
}));
}
if (settings.validate) {
await Promise.all(Document.attributesWithSchema(returnObject).map(async (key) => {
const value = utils.object.get(returnObject, key);
Expand Down Expand Up @@ -281,17 +296,6 @@ function DocumentCarrier(model) {
}
}));
}
if (settings.modifiers) {
await Promise.all(settings.modifiers.map((modifier) => {
return Promise.all(Document.attributesWithSchema(returnObject).map(async (key) => {
const value = utils.object.get(returnObject, key);
const modifierFunction = await model.schema.getAttributeSettingValue(modifier, key, {"returnFunction": true});
if (modifierFunction && value) {
utils.object.set(returnObject, key, await modifierFunction(value));
}
}));
}));
}

return returnObject;
};
Expand Down
40 changes: 40 additions & 0 deletions test/Document.js
Expand Up @@ -182,6 +182,28 @@ describe("Document", () => {
});
});

it("Should save with correct object with undefined as value without required or default as first property", async () => {
putItemFunction = () => Promise.resolve();
User = new Model("User", new Schema({"id": Number, "name": String}));
user = new User({"name": undefined, "id": 1});
await callType.func(user).bind(user)();
expect(putParams).to.eql([{
"Item": {"id": {"N": "1"}},
"TableName": "User"
}]);
});

it("Should save with correct object with undefined as value without required or default as second property", async () => {
putItemFunction = () => Promise.resolve();
User = new Model("User", new Schema({"id": Number, "name": String}));
user = new User({"id": 1, "name": undefined});
await callType.func(user).bind(user)();
expect(putParams).to.eql([{
"Item": {"id": {"N": "1"}},
"TableName": "User"
}]);
});

it("Should save with correct object with string set", async () => {
putItemFunction = () => Promise.resolve();
User = new Model("User", {"id": Number, "friends": [String]});
Expand Down Expand Up @@ -1283,6 +1305,14 @@ describe("Document", () => {
{
"input": {"data": {"L": []}},
"output": true
},
{
"input": {"prop": undefined},
"output": false
},
{
"input": {"prop": null},
"output": false
}
];

Expand Down Expand Up @@ -1684,6 +1714,16 @@ describe("Document", () => {
"input": [{"id": 1, "items": [{"birthday": 1}, {"birthday": 10000}, {"birthday": "test"}]}, {"type": "fromDynamo", "customTypesDynamo": true}],
"schema": new Schema({"id": Number, "items": {"type": Array, "schema": [{"type": Object, "schema": {"birthday": Date}}]}}),
"error": new Error.ValidationError("Expected items.2.birthday to be of type date, instead found type string.")
},
{
"schema": {"id": Number, "name": {"type": String, "set": (val) => val === "" ? undefined : val}},
"input": [{"id": 1, "name": ""}, {"type": "toDynamo", "modifiers": ["set"]}],
"output": {"id": 1, "name": undefined}
},
{
"schema": {"id": Number, "name": {"type": String, "required": true, "set": (val) => val === "" ? undefined : val}},
"input": [{"id": 1, "name": ""}, {"type": "toDynamo", "modifiers": ["set"], "required": true}],
"error": new Error.ValidationError("name is a required property but has no value when trying to save document")
}
];

Expand Down
36 changes: 36 additions & 0 deletions test/Model.js
Expand Up @@ -1349,6 +1349,42 @@ describe("Model", () => {
});
});

it("Should send correct params to putItem with value as undefined as first property", async () => {
createItemFunction = () => Promise.resolve();
await callType.func(User).bind(User)({"name": undefined, "id": 1});
expect(createItemParams).to.be.an("object");
expect(createItemParams).to.eql({
"ConditionExpression": "attribute_not_exists(#__hash_key)",
"ExpressionAttributeNames": {
"#__hash_key": "id"
},
"Item": {
"id": {
"N": "1"
}
},
"TableName": "User"
});
});

it("Should send correct params to putItem with value as undefined as second property", async () => {
createItemFunction = () => Promise.resolve();
await callType.func(User).bind(User)({"id": 1, "name": undefined});
expect(createItemParams).to.be.an("object");
expect(createItemParams).to.eql({
"ConditionExpression": "attribute_not_exists(#__hash_key)",
"ExpressionAttributeNames": {
"#__hash_key": "id"
},
"Item": {
"id": {
"N": "1"
}
},
"TableName": "User"
});
});

it("Should not include attributes that do not exist in schema", async () => {
createItemFunction = () => Promise.resolve();
await callType.func(User).bind(User)({"id": 1, "name": "Charlie", "hello": "world"});
Expand Down

0 comments on commit b6913a0

Please sign in to comment.