From 5c7fd9827defb381acdfe701981e984b1d0aa928 Mon Sep 17 00:00:00 2001
From: j3tto <james@stackcrafters.com>
Date: Mon, 14 Dec 2020 18:31:49 +0000
Subject: [PATCH 1/2] Added option for defining `timeToLiveSpecification` as
 part of table definition

---
 README.md                |  3 +++
 src/serverless.js        |  8 +++++++-
 src/utils.js             | 15 +++++++++++++++
 test/integration.test.js |  8 +++++++-
 test/utils.js            | 23 +++++++++++++++++++++--
 5 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 7d07fe2..7746814 100644
--- a/README.md
+++ b/README.md
@@ -113,6 +113,9 @@ inputs:
           KeyType: HASH
       Projection:
         ProjectionType: 'ALL'
+  timeToLiveSpecification:       # (optional) 
+    AttributeName: attribute2
+    Enabled: false
   region: us-east-1
 ```
 
diff --git a/src/serverless.js b/src/serverless.js
index 8c34659..4c2891f 100644
--- a/src/serverless.js
+++ b/src/serverless.js
@@ -5,7 +5,7 @@ const { mergeDeepRight, pick } = require('ramda');
 const AWS = require('aws-sdk');
 // eslint-disable-next-line import/no-unresolved
 const { Component } = require('@serverless/core');
-const { log, createTable, deleteTable, describeTable, updateTable } = require('./utils');
+const { log, createTable, deleteTable, describeTable, updateTable, updateTimeToLive } = require('./utils');
 
 const outputsList = ['name', 'arn', 'region'];
 
@@ -27,6 +27,7 @@ const defaults = {
   name: null,
   region: 'us-east-1',
   deletionPolicy: 'delete',
+  timeToLiveSpecification: undefined
 };
 
 class AwsDynamoDb extends Component {
@@ -88,6 +89,11 @@ class AwsDynamoDb extends Component {
       await updateTable.call(this, { dynamodb, prevGlobalSecondaryIndexes, ...config });
     }
 
+    if (config.timeToLiveSpecification) {
+      await updateTimeToLive({dynamodb, ...config})
+
+    }
+
     log(`Table ${config.name} was successfully deployed to the ${config.region} region.`);
 
     this.state.arn = config.arn;
diff --git a/src/utils.js b/src/utils.js
index 7ae0545..d7e7abe 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -119,10 +119,25 @@ async function deleteTable({ dynamodb, name }) {
   return !!res;
 }
 
+async function updateTimeToLive({dynamodb, name, timeToLiveSpecification= {}}) {
+  return await dynamodb.waitFor('tableExists', { TableName: name}, async function(err, data) {
+    if (err) throw err;
+    return await dynamodb
+      .updateTimeToLive({
+        TableName: name,
+        TimeToLiveSpecification: {
+          AttributeName: timeToLiveSpecification.AttributeName,
+          Enabled: timeToLiveSpecification.Enabled,
+        }
+      }).promise();
+  }).promise();
+}
+
 module.exports = {
   log,
   createTable,
   describeTable,
   updateTable,
   deleteTable,
+  updateTimeToLive,
 };
diff --git a/test/integration.test.js b/test/integration.test.js
index 5e402b1..8775c79 100644
--- a/test/integration.test.js
+++ b/test/integration.test.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const { sleep, generateId, getCredentials, getServerlessSdk, getTable } = require('./utils');
+const { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive } = require('./utils');
 
 // set enough timeout for deployment to finish
 jest.setTimeout(30000);
@@ -16,6 +16,10 @@ const instanceYaml = {
   stage: 'dev',
   inputs: {
     deletionPolicy: 'delete',
+    timeToLiveSpecification: {
+      AttributeName : 'expires',
+      Enabled: true
+    },
     attributeDefinitions: [
       {
         AttributeName: 'attribute1',
@@ -75,6 +79,8 @@ it('should successfully deploy dynamodb table and local index', async () => {
 
   const res = await getTable(credentials, name);
 
+  //const resTTL = await getTableTimeToLive(credentials, name);
+
   expect(instance.outputs.name).toBeDefined();
   expect(instance.outputs.arn).toBeDefined();
   expect(res.Table.AttributeDefinitions.length).toEqual(2);
diff --git a/test/utils.js b/test/utils.js
index 183fae3..3849ef5 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -28,7 +28,7 @@ const getCredentials = () => {
   };
 
   if (!credentials.aws.accessKeyId || !credentials.aws.accessKeyId) {
-    throw new Error('Unable to run tests. AWS credentials not found in the envionrment');
+    throw new Error('Unable to run tests. AWS credentials not found in the environment');
   }
 
   return credentials;
@@ -67,4 +67,23 @@ const getTable = async (credentials, tableName) => {
     .promise();
 };
 
-module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable };
+/*
+ * Fetches a DynamoDB timeToLive for a table from aws for validation
+ * @param ${object} credentials - the cross provider credentials object
+ * @param ${string} tableName - the name of the dynamodb table
+ */
+const getTableTimeToLive = async (credentials, tableName) => {
+  const config = {
+    credentials: credentials.aws,
+    region: 'us-east-1',
+  };
+  const dynamodb = new AWS.DynamoDB(config);
+
+  return dynamodb
+    .describeTimeToLive({
+      TableName: tableName,
+    })
+    .promise();
+};
+
+module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive };

From 6deda45f6281bd54bc858785fdcda1bc9b4c20c9 Mon Sep 17 00:00:00 2001
From: j3tto <james@stackcrafters.com>
Date: Mon, 14 Dec 2020 18:43:24 +0000
Subject: [PATCH 2/2] Fix Lint Errors

---
 src/serverless.js                             | 14 +++++++---
 src/utils.js                                  | 27 ++++++++++---------
 .../serverless.template.yml                   |  2 +-
 test/integration.test.js                      |  8 +++---
 test/utils.js                                 |  9 ++++++-
 5 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/src/serverless.js b/src/serverless.js
index 4c2891f..484fe65 100644
--- a/src/serverless.js
+++ b/src/serverless.js
@@ -5,7 +5,14 @@ const { mergeDeepRight, pick } = require('ramda');
 const AWS = require('aws-sdk');
 // eslint-disable-next-line import/no-unresolved
 const { Component } = require('@serverless/core');
-const { log, createTable, deleteTable, describeTable, updateTable, updateTimeToLive } = require('./utils');
+const {
+  log,
+  createTable,
+  deleteTable,
+  describeTable,
+  updateTable,
+  updateTimeToLive,
+} = require('./utils');
 
 const outputsList = ['name', 'arn', 'region'];
 
@@ -27,7 +34,7 @@ const defaults = {
   name: null,
   region: 'us-east-1',
   deletionPolicy: 'delete',
-  timeToLiveSpecification: undefined
+  timeToLiveSpecification: undefined,
 };
 
 class AwsDynamoDb extends Component {
@@ -90,8 +97,7 @@ class AwsDynamoDb extends Component {
     }
 
     if (config.timeToLiveSpecification) {
-      await updateTimeToLive({dynamodb, ...config})
-
+      await updateTimeToLive({ dynamodb, ...config });
     }
 
     log(`Table ${config.name} was successfully deployed to the ${config.region} region.`);
diff --git a/src/utils.js b/src/utils.js
index d7e7abe..2023fc0 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -119,18 +119,21 @@ async function deleteTable({ dynamodb, name }) {
   return !!res;
 }
 
-async function updateTimeToLive({dynamodb, name, timeToLiveSpecification= {}}) {
-  return await dynamodb.waitFor('tableExists', { TableName: name}, async function(err, data) {
-    if (err) throw err;
-    return await dynamodb
-      .updateTimeToLive({
-        TableName: name,
-        TimeToLiveSpecification: {
-          AttributeName: timeToLiveSpecification.AttributeName,
-          Enabled: timeToLiveSpecification.Enabled,
-        }
-      }).promise();
-  }).promise();
+async function updateTimeToLive({ dynamodb, name, timeToLiveSpecification = {} }) {
+  return await dynamodb
+    .waitFor('tableExists', { TableName: name }, async (err) => {
+      if (err) throw err;
+      return await dynamodb
+        .updateTimeToLive({
+          TableName: name,
+          TimeToLiveSpecification: {
+            AttributeName: timeToLiveSpecification.AttributeName,
+            Enabled: timeToLiveSpecification.Enabled,
+          },
+        })
+        .promise();
+    })
+    .promise();
 }
 
 module.exports = {
diff --git a/templates/aws-dynamodb-starter/serverless.template.yml b/templates/aws-dynamodb-starter/serverless.template.yml
index 509d303..93488a4 100644
--- a/templates/aws-dynamodb-starter/serverless.template.yml
+++ b/templates/aws-dynamodb-starter/serverless.template.yml
@@ -3,4 +3,4 @@ org: serverlessinc
 description: Deploys a serverless NoSQL database powered by AWS DynamoDB
 keywords: aws, serverless, nosql, database
 repo: https://github.com/serverless-components/aws-dynamodb
-license: MIT
\ No newline at end of file
+license: MIT
diff --git a/test/integration.test.js b/test/integration.test.js
index 8775c79..2756d59 100644
--- a/test/integration.test.js
+++ b/test/integration.test.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive } = require('./utils');
+const { sleep, generateId, getCredentials, getServerlessSdk, getTable } = require('./utils');
 
 // set enough timeout for deployment to finish
 jest.setTimeout(30000);
@@ -17,8 +17,8 @@ const instanceYaml = {
   inputs: {
     deletionPolicy: 'delete',
     timeToLiveSpecification: {
-      AttributeName : 'expires',
-      Enabled: true
+      AttributeName: 'expires',
+      Enabled: true,
     },
     attributeDefinitions: [
       {
@@ -79,7 +79,7 @@ it('should successfully deploy dynamodb table and local index', async () => {
 
   const res = await getTable(credentials, name);
 
-  //const resTTL = await getTableTimeToLive(credentials, name);
+  // const resTTL = await getTableTimeToLive(credentials, name);
 
   expect(instance.outputs.name).toBeDefined();
   expect(instance.outputs.arn).toBeDefined();
diff --git a/test/utils.js b/test/utils.js
index 3849ef5..5e47786 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -86,4 +86,11 @@ const getTableTimeToLive = async (credentials, tableName) => {
     .promise();
 };
 
-module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive };
+module.exports = {
+  sleep,
+  generateId,
+  getCredentials,
+  getServerlessSdk,
+  getTable,
+  getTableTimeToLive,
+};