Repository: typedorm/typedorm (ts)

Issue:
entitiy manager create operation is missing attributes in returned objec 
When item is created using `entityManager.create()`, this should return all properties of entity.

- auto generated attributes are not included in returned response

Pull request:
11 missing attributes on entity manager create operation
Include all autogenerated attributes when returning created item

closes #11 

Patch:
diff --git a/.eslintrc.json b/.eslintrc.json
index 03723ee..4b65852 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,11 +1,13 @@
 {
   "extends": "./node_modules/gts/",
   "rules": {
+    "jest/no-focused-tests": "error",
     "@typescript-eslint/no-explicit-any": [
       0,
       {
         "fixToUnknown": true
       }
     ]
-  }
+  },
+  "plugins": ["jest"]
 }
diff --git a/package-lock.json b/package-lock.json
index 300ea4b..bc02e85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -992,18 +992,6 @@
       "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
       "dev": true
     },
-    "@semantic-release/changelog": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-5.0.1.tgz",
-      "integrity": "sha512-unvqHo5jk4dvAf2nZ3aw4imrlwQ2I50eVVvq9D47Qc3R+keNqepx1vDYwkjF8guFXnOYaYcR28yrZWno1hFbiw==",
-      "dev": true,
-      "requires": {
-        "@semantic-release/error": "^2.1.0",
-        "aggregate-error": "^3.0.0",
-        "fs-extra": "^9.0.0",
-        "lodash": "^4.17.4"
-      }
-    },
     "@semantic-release/commit-analyzer": {
       "version": "8.0.1",
       "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-8.0.1.tgz",
@@ -1025,22 +1013,6 @@
       "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==",
       "dev": true
     },
-    "@semantic-release/git": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-9.0.0.tgz",
-      "integrity": "sha512-AZ4Zha5NAPAciIJH3ipzw/WU9qLAn8ENaoVAhD6srRPxTpTzuV3NhNh14rcAo8Paj9dO+5u4rTKcpetOBluYVw==",
-      "dev": true,
-      "requires": {
-        "@semantic-release/error": "^2.1.0",
-        "aggregate-error": "^3.0.0",
-        "debug": "^4.0.0",
-        "dir-glob": "^3.0.0",
-        "execa": "^4.0.0",
-        "lodash": "^4.17.4",
-        "micromatch": "^4.0.0",
-        "p-reduce": "^2.0.0"
-      }
-    },
     "@semantic-release/github": {
       "version": "7.1.2",
       "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-7.1.2.tgz",
@@ -2980,6 +2952,15 @@
         "regexpp": "^3.0.0"
       }
     },
+    "eslint-plugin-jest": {
+      "version": "24.1.3",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz",
+      "integrity": "sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/experimental-utils": "^4.0.1"
+      }
+    },
     "eslint-plugin-node": {
       "version": "11.1.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
diff --git a/package.json b/package.json
index 86fcdfb..95e1f00 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
     "@types/node": "^14.11.2",
     "@types/uuid": "^8.3.0",
     "babel": "^6.23.0",
+    "eslint-plugin-jest": "^24.1.3",
     "gts": "^3.0.2",
     "jest": "^26.6.3",
     "semantic-release": "^17.2.2",
diff --git a/packages/core/classes/manager/entity-manager.ts b/packages/core/classes/manager/entity-manager.ts
index 98e4b82..57a68c1 100644
--- a/packages/core/classes/manager/entity-manager.ts
+++ b/packages/core/classes/manager/entity-manager.ts
@@ -17,6 +17,7 @@ import {
 } from '../transformer/document-client-request-transformer';
 import {EntityTransformer} from '../transformer/entity-transformer';
 import {BaseManager} from './base-manager';
+import {getConstructorForInstance} from '../../helpers/get-constructor-for-instance';
 
 export interface EntityManagerUpdateOptions {
   /**
@@ -49,21 +50,18 @@ export class EntityManager extends BaseManager {
    * Creates new record in table with given entity
    * @param entity Entity to add to table as a new record
    */
-  async create<Entity>(
-    entity: Entity,
-    options?: {returnIdentifier: string}
-  ): Promise<Entity> {
-    const identifier = options?.returnIdentifier ?? 'id';
+  async create<Entity>(entity: Entity): Promise<Entity> {
     const dynamoPutItemInput = this._dcReqTransformer.toDynamoPutItem(entity);
-    let itemToReturn = {...entity};
+    const entityClass = getConstructorForInstance(entity);
 
     if (!Array.isArray(dynamoPutItemInput)) {
       await this._dc.put(dynamoPutItemInput).promise();
+      const itemToReturn = this._entityTransformer.fromDynamoEntity<Entity>(
+        entityClass,
+        dynamoPutItemInput.Item
+      );
 
-      if (dynamoPutItemInput.Item[identifier]) {
-        itemToReturn = {...itemToReturn, id: dynamoPutItemInput.Item.id};
-      }
-      return {...entity};
+      return itemToReturn;
     }
 
     // when put item is set to array, one or more attributes are marked as unique
@@ -74,11 +72,11 @@ export class EntityManager extends BaseManager {
     );
     await this.connection.transactionManger.write(transaction);
 
-    // if there are any unique attributes they will be appended after first item,
-    // in that case we get id from
-    if (dynamoPutItemInput[0].Item[identifier]) {
-      itemToReturn = {...itemToReturn, id: dynamoPutItemInput[0].Item.id};
-    }
+    const itemToReturn = this._entityTransformer.fromDynamoEntity<Entity>(
+      entityClass,
+      // if create operation contains multiple items, first one will the original requested item
+      dynamoPutItemInput[0].Item
+    );
 
     return itemToReturn;
   }


Test patch:
diff --git a/packages/core/classes/manager/__test__/entity-manager.spec.ts b/packages/core/classes/manager/__test__/entity-manager.spec.ts
index 799ac13..d6c78ae 100644
--- a/packages/core/classes/manager/__test__/entity-manager.spec.ts
+++ b/packages/core/classes/manager/__test__/entity-manager.spec.ts
@@ -13,6 +13,7 @@ jest.mock('aws-sdk', () => ({
     DocumentClient: dcMock,
   },
 }));
+jest.useFakeTimers('modern').setSystemTime(new Date(1606896235000));
 
 import {createTestConnection, resetTestConnection} from '@typedorm/testing';
 import {EntityManager} from '../entity-manager';
@@ -76,6 +77,40 @@ test('creates entity', async () => {
   });
 });
 
+/**
+ * Issue: #11
+ */
+test('creates entity and returns all attributes, including auto generated ones', async () => {
+  dcMock().put.mockReturnValue({
+    promise: () => ({}),
+  });
+
+  const user = new UserAutoGenerateAttributes();
+  user.id = '1';
+
+  const userEntity = await manager.create(user);
+  expect(dcMock().put).toHaveBeenCalledTimes(1);
+  expect(dcMock().put).toHaveBeenCalledWith({
+    Item: {
+      GSI1PK: 'USER#UPDATED_AT#1606896235',
+      GSI1SK: 'USER#1',
+      PK: 'USER#1',
+      SK: 'USER#1',
+      id: '1',
+      updatedAt: 1606896235,
+    },
+    TableName: 'test-table',
+    ConditionExpression: 'attribute_not_exists(#CE_PK)',
+    ExpressionAttributeNames: {
+      '#CE_PK': 'PK',
+    },
+  });
+  expect(userEntity).toEqual({
+    id: '1',
+    updatedAt: 1606896235,
+  });
+});
+
 /**
  * @group findOne
  */