Skip to content

Commit

Permalink
Merge pull request #105 from shelfio/aws-sdk-js-v3
Browse files Browse the repository at this point in the history
  • Loading branch information
vladgolubev committed Aug 18, 2021
2 parents 7b3fa6e + 68cc8de commit 4ee04ea
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 31 deletions.
29 changes: 20 additions & 9 deletions index-another-concurrent-test.test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
const {DocumentClient} = require('aws-sdk/clients/dynamodb');
const {DynamoDB} = require('@aws-sdk/client-dynamodb');
const {DynamoDBDocument} = require('@aws-sdk/lib-dynamodb');

const ddb = new DocumentClient({
convertEmptyValues: true,
endpoint: 'localhost:8000',
sslEnabled: false,
region: 'local-env'
});
const ddb = DynamoDBDocument.from(
new DynamoDB({
endpoint: 'http://localhost:8000',
tls: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey'
}
}),
{
marshallOptions: {
convertEmptyValues: true
}
}
);

it('should insert item into another table concurrently', async () => {
await ddb.put({TableName: 'users', Item: {id: '1', hello: 'world'}}).promise();
await ddb.put({TableName: 'users', Item: {id: '1', hello: 'world'}});

const {Item} = await ddb.get({TableName: 'users', Key: {id: '1'}}).promise();
const {Item} = await ddb.get({TableName: 'users', Key: {id: '1'}});

expect(Item).toEqual({
id: '1',
Expand Down
29 changes: 20 additions & 9 deletions index.test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
const {DocumentClient} = require('aws-sdk/clients/dynamodb');
const {DynamoDB} = require('@aws-sdk/client-dynamodb');
const {DynamoDBDocument} = require('@aws-sdk/lib-dynamodb');

const ddb = new DocumentClient({
convertEmptyValues: true,
endpoint: 'localhost:8000',
sslEnabled: false,
region: 'local-env'
});
const ddb = DynamoDBDocument.from(
new DynamoDB({
endpoint: 'http://localhost:8000',
tls: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey'
}
}),
{
marshallOptions: {
convertEmptyValues: true
}
}
);

it('should insert item into table', async () => {
await ddb.put({TableName: 'files', Item: {id: '1', hello: 'world'}}).promise();
await ddb.put({TableName: 'files', Item: {id: '1', hello: 'world'}});

const {Item} = await ddb.get({TableName: 'files', Key: {id: '1'}}).promise();
const {Item} = await ddb.get({TableName: 'files', Key: {id: '1'}});

expect(Item).toEqual({
id: '1',
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,24 @@
"dynamodb-local": "0.0.31"
},
"devDependencies": {
"@aws-sdk/client-dynamodb": "^3.26.0",
"@aws-sdk/lib-dynamodb": "^3.26.0",
"@aws-sdk/util-dynamodb": "^3.26.0",
"@shelf/eslint-config": "0.19.0",
"@shelf/prettier-config": "0.0.7",
"aws-sdk": "2.631.0",
"eslint": "7.6.0",
"husky": "4.2.5",
"jest": "26.2.2",
"lint-staged": "10.2.11",
"prettier": "2.0.5"
},
"peerDependencies": {
"aws-sdk": "2.x.x"
"@aws-sdk/client-dynamodb": "3.x.x",
"@aws-sdk/lib-dynamodb": "3.x.x",
"@aws-sdk/util-dynamodb": "3.x.x"
},
"engines": {
"node": ">=8"
"node": ">=12"
},
"publishConfig": {
"access": "public"
Expand Down
30 changes: 29 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ module.exports = async () => {
};
```

### 3. Configure DynamoDB client
### 3.1 Configure DynamoDB client (from aws-sdk v2)

```js
const {DocumentClient} = require('aws-sdk/clients/dynamodb');
Expand All @@ -160,6 +160,34 @@ const config = {
const ddb = new DocumentClient(config);
```

### 3.2 Configure DynamoDB client (from aws-sdk v3)

```js
const {DynamoDB} = require('@aws-sdk/client-dynamodb');
const {DynamoDBDocument} = require('@aws-sdk/lib-dynamodb');

const isTest = process.env.JEST_WORKER_ID;

const ddb = DynamoDBDocument.from(
new DynamoDB({
...(isTest && {
endpoint: 'localhost:8000',
sslEnabled: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey'
}
})
}),
{
marshallOptions: {
convertEmptyValues: true
}
}
);
```

### 4. PROFIT! Write tests

```js
Expand Down
19 changes: 14 additions & 5 deletions setup.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const {resolve} = require('path');
const cwd = require('cwd');
const DynamoDB = require('aws-sdk/clients/dynamodb');
const {DynamoDB} = require('@aws-sdk/client-dynamodb');
const DynamoDbLocal = require('dynamodb-local');
const debug = require('debug')('jest-dynamodb');
const waitForLocalhost = require('./wait-for-localhost');

// aws-sdk requires access and secret key to be able to call DDB
process.env.AWS_ACCESS_KEY_ID = 'access-key';
Expand All @@ -22,17 +23,21 @@ module.exports = async function () {
} = typeof config === 'function' ? await config() : config;

const dynamoDB = new DynamoDB({
endpoint: `localhost:${port}`,
sslEnabled: false,
endpoint: `http://localhost:${port}`,
tls: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey'
},
...clientConfig
});

global.__DYNAMODB_CLIENT__ = dynamoDB;

try {
const {TableNames: tableNames} = await Promise.race([
dynamoDB.listTables().promise(),
dynamoDB.listTables({}),
new Promise(resolve => setTimeout(resolve, 1000))
]);
await deleteTables(dynamoDB, tableNames); // cleanup leftovers
Expand All @@ -45,15 +50,19 @@ module.exports = async function () {
}

if (!global.__DYNAMODB__) {
debug('spinning up a local ddb instance');

global.__DYNAMODB__ = await DynamoDbLocal.launch(port, null, options);

await waitForLocalhost({port: DEFAULT_PORT, useGet: true, path: '/'});
}
}

await createTables(dynamoDB, newTables);
};

async function createTables(dynamoDB, tables) {
return Promise.all(tables.map(table => dynamoDB.createTable(table).promise()));
return Promise.all(tables.map(table => dynamoDB.createTable(table)));
}

async function deleteTables(dynamoDB, tableNames) {
Expand Down
7 changes: 3 additions & 4 deletions teardown.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ module.exports = async function (jestArgs) {

if (global.__DYNAMODB__) {
const watching = jestArgs.watch || jestArgs.watchAll;

if (!watching) {
await DynamoDbLocal.stopChild(global.__DYNAMODB__);
}
} else {
const dynamoDB = global.__DYNAMODB_CLIENT__;
const {TableNames: tableNames} = await dynamoDB.listTables().promise();
await Promise.all(
tableNames.map(tableName => dynamoDB.deleteTable({TableName: tableName}).promise())
);
const {TableNames: tableNames} = await dynamoDB.listTables({});
await Promise.all(tableNames.map(tableName => dynamoDB.deleteTable({TableName: tableName})));
}
};
34 changes: 34 additions & 0 deletions wait-for-localhost.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
This is copied from https://github.com/sindresorhus/wait-for-localhost/blob/v3.3.0/index.js
With 1 change
We rely on status code 400 instead of 200 to ensure local DDB is up and running
*/

const http = require('http');

const waitForLocalhost = options => {
options = {...options};

return new Promise(resolve => {
const retry = () => setTimeout(main, 200);

const method = options.useGet ? 'GET' : 'HEAD';

const main = () => {
const request = http.request({method, port: options.port, path: options.path}, response => {
if (response.statusCode === 400) {
return resolve();
}

retry();
});

request.on('error', retry);
request.end();
};

main();
});
};

module.exports = waitForLocalhost;

0 comments on commit 4ee04ea

Please sign in to comment.