From cf036e1ea73e52caa7f455371d811d19226bfe18 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Tue, 9 Mar 2021 18:35:37 -0700 Subject: [PATCH 1/7] Returning saved object in Model.create and document.save --- lib/Document.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/Document.ts b/lib/Document.ts index dd00807fd..a9f8ae003 100644 --- a/lib/Document.ts +++ b/lib/Document.ts @@ -140,8 +140,11 @@ export class Document { settings = {}; } + let savedItem; + const localSettings: DocumentSaveSettings = settings; const paramsPromise = this.toDynamo({"defaults": true, "validate": true, "required": true, "enum": true, "forceDefault": true, "combine": true, "saveUnknown": true, "customTypesDynamo": true, "updateTimestamps": true, "modifiers": ["set"]}).then((item) => { + savedItem = item; let putItemObj: DynamoDB.PutItemInput = { "Item": item, "TableName": this.model.name @@ -182,13 +185,22 @@ export class Document { if (callback) { const localCallback: CallbackType = callback as CallbackType; promise.then(() => { - this[internalProperties].storedInDynamo = true; localCallback(null, this); + this[internalProperties].storedInDynamo = true; + + const returnDocument = new this.model.Document(savedItem as any); + returnDocument[internalProperties].storedInDynamo = true; + + localCallback(null, returnDocument); }).catch((error) => callback(error)); } else { return (async (): Promise => { await promise; this[internalProperties].storedInDynamo = true; - return this; + + const returnDocument = new this.model.Document(savedItem as any); + returnDocument[internalProperties].storedInDynamo = true; + + return returnDocument; })(); } } From a1857fe489f37da8462755a64e6e1a509ecb3ea3 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Tue, 9 Mar 2021 18:35:46 -0700 Subject: [PATCH 2/7] Adding tests for returning saved object in Model.create and document.save --- test/unit/Document.js | 10 ++++++++++ test/unit/Model.js | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/test/unit/Document.js b/test/unit/Document.js index c62078927..10e4cb09a 100644 --- a/test/unit/Document.js +++ b/test/unit/Document.js @@ -170,6 +170,16 @@ describe("Document", () => { expect(result).to.eql(user); }); + it("Should return correct result after saving with defaults", async () => { + putItemFunction = () => Promise.resolve(); + + User = dynamoose.model("User", {"id": Number, "name": String, "defaultValue": {"type": String, "default": "Hello World"}}); + user = new User({"id": 1, "name": "Charlie"}); + + const result = await callType.func(user).bind(user)(); + expect(result.toJSON()).to.eql({"id": 1, "name": "Charlie", "defaultValue": "Hello World"}); + }); + it("Should return request if return request is set as setting", async () => { const result = await callType.func(user).bind(user)({"return": "request"}); expect(putParams).to.eql([]); diff --git a/test/unit/Model.js b/test/unit/Model.js index a5304fb07..7b4cf6c51 100644 --- a/test/unit/Model.js +++ b/test/unit/Model.js @@ -1878,6 +1878,15 @@ describe("Model", () => { ]; functionCallTypes.forEach((callType) => { describe(callType.name, () => { + it("Should return correct result after saving with defaults", async () => { + createItemFunction = () => Promise.resolve(); + + User = dynamoose.model("User", {"id": Number, "name": String, "defaultValue": {"type": String, "default": "Hello World"}}); + + const result = await callType.func(User).bind(User)({"id": 1, "name": "Charlie"}); + expect(result.toJSON()).to.eql({"id": 1, "name": "Charlie", "defaultValue": "Hello World"}); + }); + it("Should send correct params to putItem", async () => { createItemFunction = () => Promise.resolve(); await callType.func(User).bind(User)({"id": 1, "name": "Charlie"}); From 3504d658e5ee45685d5bd18fe033199874e72e52 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Fri, 12 Mar 2021 19:48:19 -0700 Subject: [PATCH 3/7] Updating README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f281f5b04..31e97e424 100755 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Below you will find the current branch strategy for the project. Work taking pla | Branch | Version | NPM Tag | Links | | --- | --- | --- | --- | -| [`v3`](https://github.com/dynamoose/dynamoose/tree/v3) | 3.0.0 | | - [Documentation](https://dynamoose-git-v3-dynamoose.vercel.app/) | +| [`v3`](https://github.com/dynamoose/dynamoose/tree/v3) | 3.0.0 | alpha | - [Documentation](https://dynamoose-git-v3-dynamoose.vercel.app/) | | [`master`](https://github.com/dynamoose/dynamoose/tree/master) | 2.7.x | | - [Documentation](https://dynamoose.now.sh/) | | [`v2.7.1` (tag)](https://github.com/dynamoose/dynamoose/tree/v2.7.1) | 2.7.1 | latest | - [Documentation](https://dynamoosejs.com) From 5516497f1f5f388ba929b8cef22433de342534a4 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Sat, 13 Mar 2021 17:41:54 -0700 Subject: [PATCH 4/7] Refactoring type error message --- lib/Document.ts | 2 +- lib/utils/index.ts | 4 +++- lib/utils/type_name.ts | 6 ++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 lib/utils/type_name.ts diff --git a/lib/Document.ts b/lib/Document.ts index a9f8ae003..4311ca022 100644 --- a/lib/Document.ts +++ b/lib/Document.ts @@ -335,7 +335,7 @@ Document.objectFromSchema = async function (object: any, model: Model, if (existsInSchema) { const {isValidType, matchedTypeDetails, typeDetailsArray} = utils.dynamoose.getValueTypeCheckResult(schema, value, genericKey, settings, {"standardKey": true, typeIndexOptionMap}); if (!isValidType) { - throw new Error.TypeMismatch(`Expected ${key} to be of type ${typeDetailsArray.map((detail) => detail.dynamicName ? detail.dynamicName() : detail.name.toLowerCase()).join(", ")}, instead found type ${typeof value}${typeDetailsArray.some((val) => val.name === "Constant") ? ` (${value})` : ""}.`); + throw new Error.TypeMismatch(`Expected ${key} to be of type ${typeDetailsArray.map((detail) => detail.dynamicName ? detail.dynamicName() : detail.name.toLowerCase()).join(", ")}, instead found type ${utils.type_name(value, typeDetailsArray)}.`); } else if (matchedTypeDetails.isSet || matchedTypeDetails.name.toLowerCase() === "model") { validParents.push({key, "infinite": true}); } else if (/*typeDetails.dynamodbType === "M" || */matchedTypeDetails.dynamodbType === "L") { diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 7ccb1895c..21ac91439 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -9,6 +9,7 @@ import empty_function = require("./empty_function"); import object = require("./object"); import dynamoose = require("./dynamoose"); import all_elements_match from "./all_elements_match"; +import type_name from "./type_name"; export = { combine_objects, @@ -21,5 +22,6 @@ export = { array_flatten, empty_function, object, - dynamoose + dynamoose, + type_name }; diff --git a/lib/utils/type_name.ts b/lib/utils/type_name.ts new file mode 100644 index 000000000..50d0dba71 --- /dev/null +++ b/lib/utils/type_name.ts @@ -0,0 +1,6 @@ +import { DynamoDBSetTypeResult, DynamoDBTypeResult } from "../Schema"; + +// This function takes in a value and returns a user string for the type of that value. This function is mostly used to display type errors to users. +export default (value: any, typeDetailsArray: (DynamoDBTypeResult | DynamoDBSetTypeResult)[]): string => { + return `${typeof value}${typeDetailsArray.some((val) => val.name === "Constant") ? ` (${value})` : ""}`; +}; From 9cf6eaed2ab4466b409c23d2ff587931eb1188f3 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Sat, 13 Mar 2021 17:43:46 -0700 Subject: [PATCH 5/7] Using null name for type error instead of object --- lib/utils/type_name.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/utils/type_name.ts b/lib/utils/type_name.ts index 50d0dba71..fd1b69f40 100644 --- a/lib/utils/type_name.ts +++ b/lib/utils/type_name.ts @@ -2,5 +2,15 @@ import { DynamoDBSetTypeResult, DynamoDBTypeResult } from "../Schema"; // This function takes in a value and returns a user string for the type of that value. This function is mostly used to display type errors to users. export default (value: any, typeDetailsArray: (DynamoDBTypeResult | DynamoDBSetTypeResult)[]): string => { - return `${typeof value}${typeDetailsArray.some((val) => val.name === "Constant") ? ` (${value})` : ""}`; + let str: string = ""; + if (value === null) { + str += "null"; + } else { + str += typeof value; + } + + // Add constant value to type name + str += typeDetailsArray.some((val) => val.name === "Constant") ? ` (${value})` : ""; + + return str; }; From 7049d3964adbcf81eaa6d6b2b5fe2cee94a652aa Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Sat, 13 Mar 2021 17:43:53 -0700 Subject: [PATCH 6/7] Adding test for using null name for type error instead of object --- test/unit/Document.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/Document.js b/test/unit/Document.js index 10e4cb09a..bf34b9593 100644 --- a/test/unit/Document.js +++ b/test/unit/Document.js @@ -2750,6 +2750,11 @@ describe("Document", () => { return {"id": Number, "data": [{"type": Set, "schema": [Item]}, String]}; }, "error": new Error.ValidationError("Expected data to be of type Item Set, string, instead found type boolean.") + }, + { + "input": [{"id": 1, "data": null}, {"type": "toDynamo"}], + "schema": {"id": Number, "data": String}, + "error": new Error.ValidationError("Expected data to be of type string, instead found type null.") } ]; From 156bd4090c3280973170f06fab4725bf1858c291 Mon Sep 17 00:00:00 2001 From: Charlie Fish Date: Sat, 13 Mar 2021 17:45:26 -0700 Subject: [PATCH 7/7] Lint fixes --- lib/utils/type_name.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/type_name.ts b/lib/utils/type_name.ts index fd1b69f40..f9c247bfc 100644 --- a/lib/utils/type_name.ts +++ b/lib/utils/type_name.ts @@ -1,8 +1,8 @@ -import { DynamoDBSetTypeResult, DynamoDBTypeResult } from "../Schema"; +import {DynamoDBSetTypeResult, DynamoDBTypeResult} from "../Schema"; // This function takes in a value and returns a user string for the type of that value. This function is mostly used to display type errors to users. export default (value: any, typeDetailsArray: (DynamoDBTypeResult | DynamoDBSetTypeResult)[]): string => { - let str: string = ""; + let str = ""; if (value === null) { str += "null"; } else {