AWS SDK for JavaScript v3 x Next.js で DynamoDB に PutItem してみた

2022.09.22

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

最近、Next.jsでAWS SDK for JavaScript v3を利用しています。今回は、DynamoDB に対して PutItem したみたので、対応方法について書いていきたいと思います。

前提条件

今回試した環境は以下のとおりです。

  • next
    • ^11.1.4
  • aws-amplify
    • ^4.3.22
  • @aws-sdk/client-dynamodb
    • ^3.121.0"

また、DynamoDB上のテーブルは、以下のようなテーブルを前提とします。

キー 名前 備考
パーティションキー id (String)
ソートキー type (String)
ローカルセカンダリインデックス(LSI) IdTypeIndex パーティションキー:id (String), ソートキー:type (String)

加えて、今回試す環境ではAmplifyのAuthenticatorを利用して認証していることを前提としています。詳細については以下のエントリもご参照ください。

API Routes で DynamoDB に PutItem する

まずは、API Routes を利用して DynamoDB に PutItem するコードです。

pages/api/put-item-api.ts

import type { Credentials } from '@aws-sdk/types'

import type { NextApiRequest, NextApiResponse } from 'next'

import { DynamoDBClient, PutItemCommand, PutItemCommandInput, PutItemCommandOutput } from '@aws-sdk/client-dynamodb'
import { withSSRContext } from 'aws-amplify'

export default async function handler(req: NextApiRequest, res: NextApiResponse<PutItemCommandOutput>) {
  const body = JSON.parse(req.body)
  const SSR = withSSRContext({ req: req })
  const credentials: Credentials = await SSR.API.Auth.currentCredentials()
  const input: PutItemCommandInput = body.input

  const client = new DynamoDBClient({
    credentials: credentials,
    region: 'ap-northeast-1',
  })

  const command: PutItemCommand = new PutItemCommand(input)
  const response: PutItemCommandOutput = await client.send(command)

  res.json(response)
}

このAPIは、リクエストにPutItemInputの情報を渡すことで、DynamoDBにPutItemコマンドを発行して結果を返すだけのAPIになっています。

API の呼び出し元

次に、APIを呼び出す側のコードです。

libs/put-item.ts

import { PutItemCommandInput, PutItemCommandOutput } from '@aws-sdk/client-dynamodb'
import { marshall } from '@aws-sdk/util-dynamodb'

async function callApi(input: PutItemCommandInput): Promise<PutItemCommandOutput> {
  const res = await fetch('/api/put-item-api', {
    method: 'POST',
    body: JSON.stringify({ input: input }),
  })
  const data = await res.json()
  if (!res.ok) {
    throw new Error(data.message)
  }

  return data as PutItemCommandOutput
}

export async function putItem(): Promise<PutItemCommandOutput> {
  const item = {
    id: '51f66320-7233-48e9-a718-733735da4249',
    type: 'White Mage',
  }

  const input: PutItemCommandInput = {
    TableName: 'SampleTable',
    Item: marshall(item),
  }

  const result: PutItemCommandOutput = await callApi(input)

  return result
}

callApiでは、単純にAPIに対してPOSTリクエストをしています。なお、このリクエストのbodyに対してPutItemCommandInputをJSON化したものを渡してあげることで、API側でもPutItemCommandInputを利用できるようにしています。

また、putItemでは、このcallApiの呼び出しを行い、取得された結果をそのまま返却しています。

callApiの引数として渡すPutItemCommandInputにはTableNameItemを指定しており、TableNameにはDynamoDBのテーブル名、Itemには登録したいアイテムを値として設定します。

なお、Item'id': { S: '51f66320-7233-48e9-a718-733735da4249' }のようなDynamoDB形式での値の指定をする必要がありますが、この記述を楽にするために@aws-sdk/util-dynamodbmarshallを利用しています。

まとめ

以上、AWS SDK for JavaScript v3 x Next.js で DynamoDB に PutItem してみました。

PutItemCommandは割とシンプルなコマンドなので、手始めに試すにはちょうど良いコマンドかもしれません。

どなたかのお役に立てば幸いです。それでは!

参考

関連エントリ