Repository: typedorm/typedorm (ts)

Issue:
Entity index attributes not returned in findOne/ find  api responses
### Discussed in https://github.com/typedorm/typedorm/discussions/156

<div type='discussions-op-text'>

<sup>Originally posted by **Sachin-Radhakrishnan** July 29, 2021</sup>

Hi,

I tried to get an item from dynamodb using findOne() api , but the response returned is missing the the index attribute (email) and its value . Is it the expected behaviour? Is there any way to get it ?

This is the structure of my entity
```typescript
@Entity({
    name: 'sample-entity',
    primaryKey: {
        partitionKey: 'en#' + uuidv4(),
        sortKey: 'root',
    },
    indexes: {
        [process.env.EMAIL_INDEX!]: {
            type: INDEX_TYPE.GSI,
            partitionKey: '{{email}}',
            sortKey: ''
        }
    }
})
export default class EntityData  {

    @Attribute()
    name!: string;

    @Attribute()
    email!: string;

}
```
</div>

Pull request:
Bugfix/158 missing entity index attribute from response
closes #158 

Patch:
diff --git a/packages/core/src/classes/transformer/entity-transformer.ts b/packages/core/src/classes/transformer/entity-transformer.ts
index 3b8fa7d..6d20d30 100644
--- a/packages/core/src/classes/transformer/entity-transformer.ts
+++ b/packages/core/src/classes/transformer/entity-transformer.ts
@@ -32,30 +32,35 @@ export class EntityTransformer extends BaseTransformer {
       body: dynamoEntity,
     });
 
-    const entityPrimaryKeys = Object.keys(
+    const vanillaAttributesToInclude = entityMetadata.attributes
+      .filter(attr => !attr.hidden)
+      .map(attr => attr.name);
+
+    const primaryKeyAttributesToInclude = Object.keys(
       entityMetadata.schema.primaryKey.attributes
-    );
+    ).filter(attr => !vanillaAttributesToInclude.includes(attr));
+
     const entityInternalAttributeKeys = entityMetadata.internalAttributes.map(
       attr => attr.name
     );
-
     const entityHiddenAttributeKeys = entityMetadata.attributes
       .filter(attr => attr.hidden)
       .map(attr => attr.name);
 
     const entityMetadataSchemaIndexes = entityMetadata.schema.indexes ?? {};
-    const entityIndexes = Object.keys(entityMetadataSchemaIndexes)
+    const indexAttributesToInclude = Object.keys(entityMetadataSchemaIndexes)
       .map(key => {
         return Object.keys(entityMetadataSchemaIndexes[key].attributes ?? {});
       })
-      .flat();
+      .flat()
+      .filter(attr => !vanillaAttributesToInclude.includes(attr));
 
     const plainEntityAttributes = Object.keys(dynamoEntity).reduce(
       (acc, key) => {
         // if any of the below conditions are true, skip adding given attribute from returning response
         if (
-          entityPrimaryKeys.includes(key) ||
-          entityIndexes.includes(key) ||
+          primaryKeyAttributesToInclude.includes(key) ||
+          indexAttributesToInclude.includes(key) ||
           entityInternalAttributeKeys.includes(key) ||
           entityHiddenAttributeKeys.includes(key)
         ) {


Test patch:
diff --git a/__test__/github-issues/158/issue-158.spec.ts b/__test__/github-issues/158/issue-158.spec.ts
new file mode 100644
index 0000000..7ed608e
--- /dev/null
+++ b/__test__/github-issues/158/issue-158.spec.ts
@@ -0,0 +1,60 @@
+// assuming there is a EMAIL_INDEX loaded before anything else
+process.env.EMAIL_INDEX = 'email-index-v2';
+
+import {testTable} from './test-table';
+import {EntityManager} from '@typedorm/core';
+import {createTestConnection, resetTestConnection} from '@typedorm/testing';
+import EntityData from './test-entity';
+let entityManager: EntityManager;
+
+const dcMock = {
+  query: jest.fn(),
+};
+beforeEach(() => {
+  const connection = createTestConnection({
+    entities: [EntityData],
+    table: testTable,
+    documentClient: dcMock,
+  });
+  entityManager = new EntityManager(connection);
+});
+
+afterEach(() => {
+  resetTestConnection();
+});
+
+test('entityManager find returns attributes that has the same name as key', async () => {
+  dcMock.query.mockReturnValue({
+    promise: () => ({
+      Items: [
+        {
+          SK: 'root',
+          stringSet: ['test'],
+          email: 'test-entity@gmail.com',
+          PK: 'entity#12345678',
+          name: 'ABCD',
+        },
+      ],
+    }),
+  });
+
+  const response = await entityManager.find(
+    EntityData,
+    'test-entity@gmail.com',
+    {
+      queryIndex: process.env.EMAIL_INDEX!,
+      limit: 1,
+    }
+  );
+
+  expect(response.items[0]).toBeInstanceOf(EntityData);
+  expect(response).toEqual({
+    items: [
+      {
+        name: 'ABCD',
+        stringSet: ['test'],
+        email: 'test-entity@gmail.com',
+      },
+    ],
+  });
+});
diff --git a/__test__/github-issues/158/test-entity.ts b/__test__/github-issues/158/test-entity.ts
new file mode 100644
index 0000000..e0e1bcf
--- /dev/null
+++ b/__test__/github-issues/158/test-entity.ts
@@ -0,0 +1,24 @@
+import {Attribute, Entity, INDEX_TYPE} from '@typedorm/common';
+const uuid4 = () => '12345678';
+
+@Entity({
+  name: 'sample-entity',
+  primaryKey: {
+    partitionKey: 'en#' + uuid4(),
+    sortKey: 'root',
+  },
+  indexes: {
+    [process.env.EMAIL_INDEX!]: {
+      type: INDEX_TYPE.GSI,
+      partitionKey: '{{email}}',
+      sortKey: '',
+    },
+  },
+})
+export default class EntityData {
+  @Attribute()
+  name!: string;
+
+  @Attribute()
+  email!: string;
+}
diff --git a/__test__/github-issues/158/test-table.ts b/__test__/github-issues/158/test-table.ts
new file mode 100644
index 0000000..baac7ef
--- /dev/null
+++ b/__test__/github-issues/158/test-table.ts
@@ -0,0 +1,14 @@
+import {Table, INDEX_TYPE} from '@typedorm/common';
+
+export const testTable = new Table({
+  name: 'user-v2',
+  partitionKey: 'PK',
+  sortKey: 'SK',
+  indexes: {
+    [process.env.EMAIL_INDEX!]: {
+      type: INDEX_TYPE.GSI,
+      partitionKey: 'email',
+      sortKey: 'sk',
+    },
+  },
+});