Skip to content

Commit 1ee2c77

Browse files
committed
V2.0.0, Refactored to add config options and better support single table apps
1 parent 1b742f6 commit 1ee2c77

File tree

5 files changed

+360
-117
lines changed

5 files changed

+360
-117
lines changed

README.md

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Javascript DynamoDB Context Store
1+
# Javascript DynamoDB Context Store
22

33
Used by the [SmartApp SDK](https://github.com/SmartThingsCommunity/smartapp-sdk-nodejs) to store IDs and access tokens for an installed instance of a SmartApp
44
and retrieves that information for use in asynchronous API calls. The use of a context store
@@ -14,31 +14,114 @@ The context stored by this module consists of the following data elements:
1414
* **refreshToken**: the refresh token used in generating a new access token when one expires
1515
* **clientId**: the SmartApp's client ID, used in generating a new access token
1616
* **clientSecret**: the SmartApp's client secret, used in generating a new access token
17-
* **config**: the current installed app instance configuration, i.e. selected devices, options, etc.v
17+
* **config**: the current installed app instance configuration, i.e. selected devices, options, etc.
18+
19+
_Note: Version 2.X.X is a breaking change to version 1.X.X as far as configuring the context store is
20+
concerned, but either one can be used with any version of the SmartThings SDK._
1821

1922
## Installation:
2023
```
21-
npm install @smartthings/dynamodb-context-store --save
24+
npm install @smartthings/dynamodb-context-store
2225
```
2326

2427
## Usage
2528

26-
To use this module to add DynamoDB context storage to your SmartApp you should:
27-
1. Create a DynamoDB table with `installedAppId` as its primary key
29+
Create a `DynamoDBContextStore` object and pass it to the SmartApp connector to store the context in a table
30+
named `"smartapp"` in the `us-east-1` AWS region. If the table does not exist it will be created.
31+
```javascript
32+
smartapp.contextStore(new DynamoDBContextStore())
33+
```
34+
35+
The more extensive set of options are shown in this example:
36+
```javascript
37+
smartapp.contextStore(new DynamoDBContextStore(
38+
{
39+
table: {
40+
name: 'custom-table', // defaults to 'smartapp'
41+
hashKey: 'key1', // defaults to 'id'
42+
prefix: 'context', // defaults to 'ctx'
43+
readCapacityUnits: 10, // defaults to 5, applies to automatic creation only
44+
writeCapacityUnits: 10 // defaults to 5, applies to automatic creation only
45+
},
46+
AWSRegion: 'us-east-2', // defaults to 'us-east-1'
47+
autoCreate: true // defaults to true
48+
}
49+
))
50+
```
51+
52+
The **table** configuration options are:
53+
* **name** -- The name of the DynamoDB table storing the context
54+
* **hashKey** -- The name of the partition key of the table
55+
* **prefix** -- A string pre-pended to the installed app ID and used as the partition key for the entry
56+
* **readCapacityUnits** -- Number of consistent reads per second. Used only when table is created
57+
* **writeCapacityUnits** -- Number of writes per second. Used only when table is created
58+
* **sortKey** -- Optional sort key definition (see below for more details)
2859

29-
1. Give your Lambda permission to access that table
60+
Other configuration options are:
61+
* **AWSRegion** -- The AWS region containing the table
62+
* **AWSConfigPath** -- The location of the AWS configuration JSON file
63+
* **AWSConfigJSON** -- The AWS credentials and region
64+
* **autoCreate** -- Controls whether table is created if it doesn't already exist
3065

31-
1. Create a context store instance with the table name and AWS region and pass it to the
32-
smartapp SDK object. For example, the following code:
66+
Note that only one of the AWS options should be specified or behavior will be inconsistent
3367

68+
### AWS Configuration Options
69+
70+
By default, the AWS credentials are picked up from the environment. If you prefer you can read the credentials
71+
from a file with this configuration:
72+
```javascript
73+
smartapp.contextStore(new DynamoDBContextStore(
74+
{
75+
AWSConfigPath: './path/to/file.json'
76+
}
77+
))
3478
```
35-
const smartapp = require('@smartthings/dynamodb-context-store');
36-
const DynamoDBContextStore = require('@smartthings/dynamodb-context-store');
3779

38-
smartapp.contextStore(new DynamoDBContextStore('us-east-2', 'app-table-name'))
39-
.configureI18n()
40-
.page('mainPage', (page) => {
41-
...
80+
81+
You can also explicitly set the credentials in this way:
82+
```javascript
83+
smartapp.contextStore(new DynamoDBContextStore(
84+
{
85+
AWSConfigJSON: {
86+
accessKeyId: '<YOUR_ACCESS_KEY_ID>',
87+
secretAccessKey: '<YOUR_SECRET_ACCESS_KEY>',
88+
region: 'us-east-2'
89+
}
90+
}
91+
))
92+
````
93+
94+
### Sort Key Configuration
95+
In order to support single table schemas, the context store can be configured to use a table with a sort key.
96+
The simplest way to do that is by specifying the sort key name:
97+
```javascript
98+
smartapp.contextStore(new DynamoDBContextStore(
99+
{
100+
table: {
101+
name: 'my-application',
102+
hashKey: 'pk',
103+
sortKey: 'sk'
104+
}
105+
}
106+
))
107+
42108
```
109+
More control over the sort key can be exercised using this form, which is configured with the default values
110+
used when just the sort key name is specified:
111+
```javascript
112+
smartapp.contextStore(new DynamoDBContextStore(
113+
{
114+
table: {
115+
name: 'my-application',
116+
hashKey: 'pk',
117+
sortKey: {
118+
AttributeName: 'sk',
119+
AttributeType: 'S',
120+
AttributeValue: 'context',
121+
KeyType: 'RANGE'
122+
}
123+
}
124+
}
125+
))
43126
44-
will use a table named `app-table-name` in the `us-east-2` region.
127+
```

index.js

Lines changed: 1 addition & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,3 @@
11
'use strict';
2-
const AWS = require('aws-sdk');
32

4-
module.exports = class DynamoDBContextStore {
5-
constructor(region, tableName) {
6-
this.region = region;
7-
this.tableName = tableName;
8-
AWS.config.update({region: region});
9-
this.docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
10-
}
11-
12-
get(installedAppId) {
13-
let params = {
14-
TableName: this.tableName,
15-
Key: {
16-
installedAppId: installedAppId
17-
},
18-
ConsistentRead: true
19-
};
20-
return new Promise((resolve, reject) => {
21-
this.docClient.get(params, function(err, data) {
22-
if (err) {
23-
reject(err);
24-
} else {
25-
if (data.Item) {
26-
let result = data.Item;
27-
28-
// For backward compatibility with version 1.0.1
29-
if (typeof result.config === 'string') {
30-
result.config = JSON.parse(result.config);
31-
}
32-
resolve(result);
33-
}
34-
else {
35-
resolve({});
36-
}
37-
}
38-
});
39-
});
40-
}
41-
42-
put(params) {
43-
const data = {
44-
TableName: this.tableName,
45-
Item: {
46-
installedAppId: params.installedAppId,
47-
locationId: params.locationId,
48-
authToken: params.authToken,
49-
refreshToken: params.refreshToken,
50-
config: params.config
51-
}
52-
};
53-
return new Promise((resolve, reject) => {
54-
this.docClient.put(data, function(err, data) {
55-
if (err) {
56-
reject(err);
57-
} else {
58-
resolve(data);
59-
}
60-
});
61-
});
62-
}
63-
64-
update(installedAppId, params) {
65-
const data = {
66-
TableName: this.tableName,
67-
Key: {'installedAppId': installedAppId},
68-
UpdateExpression: 'SET authToken = :x, refreshToken = :y',
69-
ExpressionAttributeValues: {
70-
':x': params.authToken,
71-
':y': params.refreshToken
72-
}
73-
};
74-
return new Promise((resolve, reject) => {
75-
this.docClient.update(data, function(err, data) {
76-
if (err) {
77-
reject(err);
78-
} else {
79-
resolve(data);
80-
}
81-
});
82-
});
83-
}
84-
85-
delete(installedAppId) {
86-
let params = {
87-
TableName: this.tableName,
88-
Key: {
89-
installedAppId: installedAppId
90-
}
91-
};
92-
return new Promise((resolve, reject) => {
93-
this.docClient.delete(params, function(err, data) {
94-
if (err) {
95-
reject(err);
96-
} else {
97-
resolve(data);
98-
}
99-
});
100-
});
101-
}
102-
};
3+
module.exports = require('./lib/DynamoDBContextStore')

0 commit comments

Comments
 (0)