AWS SAMでLambdaを作成する
まずは、AWS SAM CLIを用いてテンプレート環境を作成します。事前に、AWS SAM CLIのインストールを公式ドキュメントに従って行なってください。
準備が完了したら、テンプレートを作成します。
sam init
質問には以下のように答えます。
以下のようにアプリケーションが生成されたら準備完了です。
template.yaml
、samconfig.toml
はLambdaをデプロイするためのSAMの設定、hello-world
にはLambdaのコードが記述されています。events
はテストに利用するLambdaのダミー入力です。
Prismaを導入する
次に、PrismaをLambdaに導入してローカル環境で利用可能にします。
npm install prisma --save-dev
パッケージを導入したら、Prismaプロジェクトを初期化します。
npx prisma init
prisma/schema.prisma
と.env
、.gitignore
がhello-world
に生成されます。
schema.prisma
で利用するデータベースのテーブルのモデル化を行ってください。
そして、Lambdaからデータベースにアクセスするためのクライアントを準備します。
npm install @prisma/client
パッケージの導入と、Prismaクライアントやモデルの情報を扱うためのコードをnode_modules
に生成させます。
npx prisma generate
これで、Lambda内でPrismaを扱うための準備は完了です。
最後にPrismaをモックしてテストできるようにします。
モックしやすいように、アプリ全体でPrisma Clientをインスタンス化した1つのものを利用するようはシングルトンな構成に変更します。
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;
データベースにアクセスするコードはこれを使うように書き換えてください。
そして、テスト環境が設定された後、Prisma Clientをモックするようにします。モックするために利用するライブラリを導入します。
npm install jest-mock-extended --save-dev
次に、モックを行うコードを記述します。
import { PrismaClient } from '@prisma/client'
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
import prisma from './client'
jest.mock('./client', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}))
beforeEach(() => {
mockReset(prismaMock)
})
export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>
このファイルが呼ばれた後にPrisma Clientを呼び出すと代わりにprismaMock
を呼び出すようになります。さらに、テストコードではprismaMock
で各メソッドの戻り値の設定などを行えます。
Jestの設定でsetupFilesAfterEnv
を設定することで、このファイルをテスト環境が設定された後に呼び出させます。
export default {
transform: {
'^.+\\.ts?$': 'ts-jest',
},
clearMocks: true,
collectCoverage: true,
coverageDirectory: 'coverage',
coverageProvider: 'v8',
testMatch: ['**/tests/unit/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/singleton.ts'],
};
SAMの設定を変更する
最後にこれまでのコードをSAMからAWS Lambdaに上げ利用できるようにします。
まずは、prisma/schema.prisma
とnode_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node
をAWSへアップロードするバンドルされたコードに含めるためコード内で呼び出すようにします。
import { PrismaClient } from '@prisma/client';
import schema from '@/prisma/schema.prisma';
import x from '@/node_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node';
if (process.env.NODE_ENV !== 'production') {
console.debug(schema, x);
}
const prisma = new PrismaClient();
export default prisma;
schema.prisma
のbinaryTargets
をそれに合わせて修正してください。
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-1.0.x"]
}
この変更は必ず呼び出されるところであればどこでも問題ないです。
最後にtemplate.yaml
の設定を変更します。
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs20.x
Architectures:
- x86_64
Environment:
Variables:
DATABASE_URL: xxx
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- app.ts
Loader:
- .prisma=file
- .so.node=file
AssetNames: '[name]'
DATABASE_URL
を渡すようにして、esbuildの設定の要素にLoader
とAssetNames
を追加しました。
DATABASE_URL
に渡すconnection_limit
の値はこちらを参考して下さい。
これで準備完了です。sam build
してsam deploy
すればPrismaを使ったLambdaを作成できます。