AWS SDK for JavaScript v2からv3への移行で、まとめ記事に載っていなくて苦労したことをまとめました。
1. aws-sdk-js-codemod は魔法のツールではなかった
aws-sdk-js-codemodを使うと、簡単にv2のコードをv3のコードに書き換えてくれる
そんな便利なツールがあるのかと思い、試してみました。結果…
変更前
const queryResult = await dynamodb.scan(params).promise()
変更後
const queryResult = await // The `.promise()` call might be on an JS SDK v2 client API.
// If yes, please remove .promise(). If not, remove this comment.
dynamodb.scan(params).promise()
いや、コメント追加されただけやんww
これは、v3だと .promise()
が不要になるということをコメントで教えてくれました。
書き換えてくれるってそういう意味ですか?自分の環境だけですかね…?
2. LambdaInvoke の戻り値の形式が変わった
LambdaInvokeの戻り値が Payload
に入っているのですが、このPayloadが謎の「Uint8ArrayBlobAdapter」という型に変わっていました。
文字列に変換する必要があります。
LambdaInvoke
const result = await lambda.send(command)
// Payload を文字列に変換
const payloadString = Buffer.from(result.Payload).toString('utf-8')
return JSON.parse(payloadString)
3. S3 ListObjectsV2Command で結果が空の場合
ListObjectsV2Command で結果が空の場合、Contentsのキー自体が返らなくなりました。
あと、ディレクトリも結果に含まれるようになったので、ディレクトリは除外する必要があります。
ListObjectsV2Command
const command = new ListObjectsV2Command({
Bucket: 'Bucket',
Prefix: 'FilePath',
})
const res = await s3.send(command)
if (res.Contents) {
for (let file of res.Contents) {
// ディレクトリはスキップ
if (file.Key.endsWith('/')) {
continue
}
4. DynamoDBDocumentClientでAWSXRayを使う
AWSXRay
const AWSXRay = require('aws-xray-sdk-core')
AWSXRay.setContextMissingStrategy('LOG_ERROR')
const dynamodbClient = AWSXRay.captureAWSv3Client(
new DynamoDBClient({
apiVersion: '2012-08-10',
region: 'ap-northeast-1',
}),
)
const dynamodb = DynamoDBDocumentClient.from(dynamodbClient)
const s3 = AWSXRay.captureAWSv3Client(
new S3Client({
apiVersion: '2006-03-01',
region: 'ap-northeast-1',
signatureVersion: 'v4',
}),
)
5. 自動テスト(jest)
v3では、メソッドはすべて send()
なので、引数に渡すcommandで判断しないといけないためコマンドごとに分岐する必要があります。
最終的にこうなりました。。
jest
// aws-xrayをモックする
jest.mock('aws-xray-sdk-core', () => {
return {
setContextMissingStrategy: jest.fn(),
captureAWSv3Client: (client) => client, // 何もせずそのまま返す
captureHTTPs: (client) => client, // 何もせずそのまま返す
}
})
jest.mock('@aws-sdk/client-dynamodb', () => {
return {
DynamoDBClient: jest.fn().mockImplementation(() => {
return {}
}),
}
})
jest.mock('@aws-sdk/lib-dynamodb', () => {
return {
DynamoDBDocumentClient: {
from: jest.fn().mockImplementation(() => {
return {
//send: mockDynamodbSend,
send: jest.fn().mockImplementation((command) => {
if(command.name == 'ScanCommand'){
return mockDynamodbScan()
}
if(command.name == 'QueryCommand'){
return mockDynamodbQuery()
}
if(command.name == 'DeleteCommand'){
return mockDynamodbDelete()
}
if(command.name == 'BatchWriteCommand'){
return mockDynamodbBatchWrite()
}
if(command.name == 'UpdateCommand'){
return mockDynamodbUpdate()
}
if(command.name == 'PutCommand'){
return mockDynamodbPut()
}
}),
}
}),
},
/* Return your other docClient methods here too... */
ScanCommand: jest.fn().mockImplementation(() => {
return { name: 'ScanCommand' }
}),
QueryCommand: jest.fn().mockImplementation(() => {
return { name: 'QueryCommand' }
}),
DeleteCommand: jest.fn().mockImplementation(() => {
return { name: 'DeleteCommand' }
}),
BatchWriteCommand: jest.fn().mockImplementation(() => {
return { name: 'BatchWriteCommand' }
}),
UpdateCommand: jest.fn().mockImplementation(() => {
return { name: 'UpdateCommand' }
}),
PutCommand: jest.fn().mockImplementation(() => {
return { name: 'PutCommand' }
}),
}
})