Skip to content

tRPC API からリレーショナルデータベースへの接続

connection ジェネレーターは、tRPC APIリレーショナルデータベース プロジェクトに接続し、プロシージャコンテキストで Prisma クライアントを利用可能にする型安全な tRPC ミドルウェアプラグインを生成します。

このジェネレーターを使用する前に、以下を確認してください:

  1. tRPC API プロジェクト(ts#api で生成)
  2. ts#rdb プロジェクト
Terminal window
pnpm nx g @aws/nx-plugin:connection
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:connection --dry-run

ソースとして tRPC API プロジェクトを選択し、ターゲットとしてリレーショナルデータベースプロジェクトを選択します。

パラメータデフォルト説明
sourceProject 必須string-ソース プロジェクト
targetProject 必須string-接続先のターゲット プロジェクト
sourceComponent string-接続元のソース コンポーネント (コンポーネント名、ソース プロジェクト ルートからの相対パス、またはジェネレーター ID)。プロジェクトをソースとして明示的に選択するには '.' を使用します。
targetComponent string-接続先のターゲット コンポーネント (コンポーネント名、ターゲット プロジェクト ルートからの相対パス、またはジェネレーター ID)。プロジェクトをターゲットとして明示的に選択するには '.' を使用します。
preferInstallDependencies booleantrueジェネレーター実行後に依存関係のインストールを優先するかどうか。複数のジェネレーターをバッチ処理する際にインストールを延期する場合はfalseに設定します(後続のジェネレーターがNxプロジェクトグラフを計算できるよう、必要に応じてインストールは実行されます)。最後に一度だけインストールします。

ジェネレーターは、tRPC API プロジェクト内にミドルウェアファイルを作成します:

  • Directorypackages/api/src
    • Directorymiddleware
      • <db-name>.ts tRPC plugin exposing the Prisma client in procedure context

さらに、tRPC API の dev ターゲットを更新して、ローカル実行時にデータベースが自動的に起動するようにします。

生成されたプラグインを tRPC ルーターに追加して、それを使用するすべてのプロシージャがデータベースにアクセスできるようにします:

packages/api/src/router.ts
import { t } from './init.js';
import { createMyDbPlugin } from './middleware/my-db.js';
export const authenticatedProcedure = t.procedure
.concat(createMyDbPlugin());

プロシージャ内でのデータベースへのアクセス

Section titled “プロシージャ内でのデータベースへのアクセス”

プラグインは IMyDbContext をプロシージャコンテキストにマージし、myDb をオプショナルプロパティとして利用可能にします:

packages/api/src/procedures/users.ts
import { z } from 'zod';
import { authenticatedProcedure } from '../router.js';
export const listUsers = authenticatedProcedure
.output(z.array(z.object({ id: z.string(), name: z.string() })))
.query(async ({ ctx }) => {
// ctx.myDb is the Prisma client — typed as Awaited<ReturnType<typeof getPrisma>>
return await ctx.myDb!.user.findMany();
});

ターゲットデータベースが MySQL エンジンを使用している場合、生成されたミドルウェアは opts.next()try/finally ブロックでラップし、$disconnect() を呼び出します:

packages/api/src/middleware/my-db.ts
return t.procedure.use(async (opts) => {
const myDb = await getPrisma();
try {
return await opts.next({ ctx: { ...opts.ctx, myDb } });
} finally {
await myDb.$disconnect();
}
});

これは、MySQL アダプターがクエリ後に Node.js イベントループを保持し続けることに対処するもので、そうしないと Lambda がストリーミングレスポンスをフラッシュできなくなります。finally で切断することでイベントループが解放され、レスポンスが完了できるようになります。詳細は MySQL: API Gateway ストリーミングモード を参照してください。

PostgreSQL ではこれは不要です — そのアダプターは allowExitOnIdle: true で設定された接続プールを使用します。

異なるターゲットでジェネレーターを再度実行することで、追加のデータベースを接続できます。各データベースは独自のプラグインとコンテキストインターフェースを取得します:

packages/api/src/router.ts
export const dbProcedure = t.procedure
.concat(createMyDbPlugin())
.concat(createOtherDbPlugin());

実行時にAPIがデータベースに接続できるようにするには、API Lambda関数をデータベースと同じVPCにデプロイし、ネットワークおよびIAMアクセスを付与する必要があります。

アプリケーションスタックで、APIをデータベースと同じVPCにデプロイし、allowDefaultPortFromgrantConnectを呼び出して、ネットワークパスを開き、各Lambdaハンドラーに IAM rds-db:connect権限を付与します:

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { vpc, ... });
const api = new MyApi(this, 'Api', {
integrations: MyApi.defaultIntegrations(this)
.withDefaultOptions({
vpc,
vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS },
})
.build(),
});
Object.entries(api.integrations).forEach(([operation, integration]) => {
db.allowDefaultPortFrom(integration.handler, `Allow ${operation} to connect to the database`);
db.grantConnect(integration.handler);
});

API Lambda関数は、プライベート分離サブネットではなく、エグレス付きプライベートサブネットにデプロイしてください。実行時に、getPrisma()はAWS AppConfigからデータベース接続の詳細を取得しますが、これはアウトバウンドインターネットアクセスを必要とするパブリックAWSサービスエンドポイントです。

RDS Proxy を使用せずに接続する場合の SSL 要件

Section titled “RDS Proxy を使用せずに接続する場合の SSL 要件”

Node.js 20以降のLambdaランタイムからAuroraクラスターに直接接続する場合は、NODE_EXTRA_CA_CERTSを設定してAmazon RDS CAバンドルを読み込んでください:

packages/infra/src/stacks/application-stack.ts
const api = new Api(this, 'Api', {
integrations: Api.defaultIntegrations(this)
.withDefaultOptions({
environment: {
NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
},
})
.build(),
});

詳細については、AWS LambdaのAmazon RDS接続のSSL/TLS要件およびAmazon RDS ProxyのTLSドキュメントを参照してください。RDS Proxyを使用する場合、Lambda関数でRDS CAバンドルを設定する必要はありません。

ジェネレーターは、tRPC API の dev ターゲットがデータベースの dev ターゲットに依存するように設定するため、以下を実行すると:

Terminal window
pnpm nx dev <api-project-name>

API と一緒にローカルデータベースが自動的に起動します。