Skip to content

Commit 93be847

Browse files
committed
chore(deps): Updated client libraries to AWS SDK v3
1 parent 3905dc2 commit 93be847

File tree

9 files changed

+1402
-136
lines changed

9 files changed

+1402
-136
lines changed

.projen/deps.json

+37-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.projenrc.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@ const { TaimosTypescriptLibrary } = require('@taimos/projen');
33
const project = new TaimosTypescriptLibrary({
44
name: '@taimos/lambda-toolbox',
55
deps: [
6-
'aws-sdk',
76
'jsonwebtoken',
87
'jwk-to-pem',
98
'axios',
109
'uuid',
1110
'lambda-log',
11+
'@aws-crypto/sha256-js',
12+
'@aws-sdk/client-appsync',
13+
'@aws-sdk/client-dynamodb',
14+
'@aws-sdk/credential-providers',
15+
'@aws-sdk/lib-dynamodb',
16+
'@aws-sdk/node-http-handler',
17+
'@aws-sdk/protocol-http',
18+
'@aws-sdk/signature-v4',
1219
],
1320
docgen: false,
1421
defaultReleaseBranch: 'main',
@@ -21,6 +28,8 @@ const project = new TaimosTypescriptLibrary({
2128
'@types/uuid',
2229
'@taimos/projen',
2330
'@hapi/boom',
31+
'aws-sdk-client-mock',
32+
'aws-sdk-client-mock-jest',
2433
],
2534
keywords: [
2635
'aws',

package.json

+10-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client/appsync.ts

+25-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { parse, UrlWithStringQuery } from 'url';
2-
import * as AWS from 'aws-sdk';
1+
import { URL } from 'url';
2+
import { Sha256 } from '@aws-crypto/sha256-js';
3+
import * as credentials from '@aws-sdk/credential-providers';
4+
import { HttpRequest } from '@aws-sdk/protocol-http';
5+
import { SignatureV4 } from '@aws-sdk/signature-v4';
36
import * as axios from 'axios';
47

58
export class AppSyncClient {
69

7-
protected readonly graphQlServerUri: UrlWithStringQuery;
10+
protected readonly graphQlServerUri: URL;
811

912
constructor(protected readonly graphQlServerUrl: string, protected readonly awsRegion: string) {
10-
this.graphQlServerUri = parse(this.graphQlServerUrl);
13+
this.graphQlServerUri = new URL(this.graphQlServerUrl);
1114
if (!this.graphQlServerUri.href) {
1215
throw new Error('Invalid GraphQL server URL');
1316
}
@@ -20,22 +23,32 @@ export class AppSyncClient {
2023
variables,
2124
};
2225

23-
const httpRequest = new AWS.HttpRequest(new AWS.Endpoint(this.graphQlServerUri.href!), this.awsRegion);
26+
const httpRequest = new HttpRequest({
27+
headers: {
28+
'host': this.graphQlServerUri.host!,
29+
'Content-Type': 'application/json',
30+
},
31+
method: 'POST',
32+
body: JSON.stringify(post_body),
33+
});
2434
httpRequest.headers.host = this.graphQlServerUri.host!;
2535
httpRequest.headers['Content-Type'] = 'application/json';
2636
httpRequest.method = 'POST';
2737
httpRequest.body = JSON.stringify(post_body);
2838

29-
await ((AWS.config.credentials as AWS.Credentials)?.getPromise());
39+
// There's now an official signature library - yay!
40+
const signer = new SignatureV4({
41+
credentials: credentials.fromEnv(),
42+
service: 'appsync',
43+
region: this.awsRegion,
44+
sha256: Sha256,
45+
});
3046

31-
// Signers is an internal API
32-
const signer = new (AWS as any).Signers.V4(httpRequest, 'appsync', true);
33-
signer.addAuthorization(AWS.config.credentials, (AWS as any).util.date.getDate());
47+
const signedRequest = await signer.sign(httpRequest, { signingDate: new Date() });
3448

35-
const res = await axios.default.post(this.graphQlServerUri.href!, httpRequest.body, {
36-
headers: httpRequest.headers,
49+
return axios.default.post(this.graphQlServerUri.href!, signedRequest.body, {
50+
headers: signedRequest.headers,
3751
});
38-
return res;
3952
}
4053

4154
}

src/dynamodb/client.ts

+26-21
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,41 @@
11
import * as https from 'https';
22
import { env } from 'process';
3-
import { DynamoDB } from 'aws-sdk';
3+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
4+
import * as dynamodb from '@aws-sdk/lib-dynamodb';
5+
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
6+
import { NodeHttpHandler } from '@aws-sdk/node-http-handler';
47
import { PrimaryEntity } from './model';
58

69
const agent = new https.Agent({
710
keepAlive: true,
811
});
9-
export const dynamoClient: DynamoDB.DocumentClient = new DynamoDB.DocumentClient({ httpOptions: { agent } });
12+
export const dynamoClient: DynamoDBDocumentClient = DynamoDBDocumentClient.from(new DynamoDBClient({
13+
requestHandler: new NodeHttpHandler({ httpsAgent: agent }),
14+
}));
1015

1116
export const TABLE_NAME: string = env.TABLE!;
1217

13-
export async function getItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], options?: Omit<DynamoDB.DocumentClient.GetItemInput, 'TableName' | 'Key'>): Promise<E | undefined> {
14-
const res = await dynamoClient.get({
18+
export async function getItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], options?: Omit<dynamodb.GetCommandInput, 'TableName' | 'Key'>): Promise<E | undefined> {
19+
const res = await dynamoClient.send(new dynamodb.GetCommand({
1520
TableName: TABLE_NAME,
1621
Key: {
1722
PK: pk,
1823
SK: sk,
1924
},
2025
...options,
21-
}).promise();
26+
}));
2227
return res.Item ? res.Item as E : undefined;
2328
}
2429

25-
export async function deleteItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], options?: Omit<DynamoDB.DocumentClient.DeleteItemInput, 'TableName' | 'Key'>): Promise<void> {
26-
await dynamoClient.delete({
30+
export async function deleteItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], options?: Omit<dynamodb.DeleteCommandInput, 'TableName' | 'Key'>): Promise<void> {
31+
await dynamoClient.send(new dynamodb.DeleteCommand({
2732
TableName: TABLE_NAME,
2833
Key: {
2934
PK: pk,
3035
SK: sk,
3136
},
3237
...options,
33-
}).promise();
38+
}));
3439
}
3540

3641
export async function putNewItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], item: Omit<E, 'PK' | 'SK'>): Promise<E> {
@@ -39,35 +44,35 @@ export async function putNewItem<E extends PrimaryEntity<any, any>>(pk: E['PK'],
3944
SK: sk,
4045
...item,
4146
};
42-
await dynamoClient.put({
47+
await dynamoClient.send(new dynamodb.PutCommand({
4348
TableName: TABLE_NAME,
4449
Item,
4550
ConditionExpression: 'attribute_not_exists(PK) and attribute_not_exists(SK)',
46-
}).promise();
51+
}));
4752
return Item as E;
4853
}
4954

5055
export async function updateExistingItem<E extends PrimaryEntity<any, any>>(pk: E['PK'], sk: E['SK'], item: Partial<E>): Promise<E | undefined> {
51-
const res = await dynamoClient.update(createUpdate<E>({
56+
const res = await dynamoClient.send(createUpdate<E>({
5257
Key: {
5358
PK: pk,
5459
SK: sk,
5560
},
5661
ConditionExpression: 'attribute_exists(PK) and attribute_exists(SK)',
5762
ReturnValues: 'ALL_NEW',
58-
}, item)).promise();
63+
}, item));
5964
return res.Attributes ? res.Attributes as E : undefined;
6065
}
6166

62-
export async function pagedQuery<T>(query: Omit<DynamoDB.DocumentClient.QueryInput, 'TableName'>): Promise<T[]> {
67+
export async function pagedQuery<T>(query: Omit<dynamodb.QueryCommandInput, 'TableName'>): Promise<T[]> {
6368
let startKey;
6469
const result: T[] = [];
6570
do {
66-
const res: DynamoDB.DocumentClient.QueryOutput = await dynamoClient.query({
71+
const res: dynamodb.QueryCommandOutput = await dynamoClient.send(new dynamodb.QueryCommand({
6772
...query,
6873
TableName: TABLE_NAME,
6974
ExclusiveStartKey: startKey,
70-
}).promise();
75+
}));
7176
if (res.Items) {
7277
result.push(...res.Items as T[]);
7378
}
@@ -76,15 +81,15 @@ export async function pagedQuery<T>(query: Omit<DynamoDB.DocumentClient.QueryInp
7681
return result;
7782
}
7883

79-
export async function pagedScan<T>(query: Omit<DynamoDB.DocumentClient.ScanInput, 'TableName'>): Promise<T[]> {
84+
export async function pagedScan<T>(query: Omit<dynamodb.ScanCommandInput, 'TableName'>): Promise<T[]> {
8085
let startKey;
8186
const result: T[] = [];
8287
do {
83-
const res: DynamoDB.DocumentClient.ScanOutput = await dynamoClient.scan({
88+
const res: dynamodb.ScanCommandOutput = await dynamoClient.send(new dynamodb.ScanCommand({
8489
...query,
8590
TableName: TABLE_NAME,
8691
ExclusiveStartKey: startKey,
87-
}).promise();
92+
}));
8893
if (res.Items) {
8994
result.push(...res.Items as T[]);
9095
}
@@ -101,7 +106,7 @@ export function padLeftZeros(val: number | string | undefined) {
101106
return ('00' + val).slice(-2);
102107
}
103108

104-
export function createUpdate<T>(request: Omit<DynamoDB.DocumentClient.UpdateItemInput, 'TableName'>, data: Partial<T>): DynamoDB.DocumentClient.UpdateItemInput {
109+
export function createUpdate<T>(request: Omit<dynamodb.UpdateCommandInput, 'TableName'>, data: Partial<T>): dynamodb.UpdateCommand {
105110
const fieldsToSet = [];
106111
const fieldsToRemove = [];
107112
const expressionNames: any = {};
@@ -129,7 +134,7 @@ export function createUpdate<T>(request: Omit<DynamoDB.DocumentClient.UpdateItem
129134
if (request.UpdateExpression) {
130135
update += request.UpdateExpression;
131136
}
132-
return {
137+
return new dynamodb.UpdateCommand({
133138
...request,
134139
TableName: TABLE_NAME,
135140
UpdateExpression: update,
@@ -147,5 +152,5 @@ export function createUpdate<T>(request: Omit<DynamoDB.DocumentClient.UpdateItem
147152
...expressionValues,
148153
},
149154
},
150-
};
155+
});
151156
}

src/http/auth.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { env } from 'process';
22
import Axios from 'axios';
3-
import { verify, JwtHeader, SigningKeyCallback } from 'jsonwebtoken';
4-
// import jwkToPem = require('jwk-to-pem');
3+
import { JwtHeader, SigningKeyCallback, verify } from 'jsonwebtoken';
54
import jwkToPem from 'jwk-to-pem';
65
import logger from 'lambda-log';
76
import { ForbiddenError, UnauthenticatedError } from '../types/errors';

0 commit comments

Comments
 (0)