Cloudflare Workers の PlanetScale インテグレーションを試してみた

2023.08.03

西田@CX事業本部です

今回は Cloudflare Workers と PlanetScale のインテグレーション を試してみたいと思います

Cloudflare Workers のデータベースサポート

Cloudflare には D1 データベースがありますが、その他のデータベースやサーバーレスデータベースの接続をサポートするインテグレーションが用意されています

対応データベース

インテグレーションの内容

Cloudflare Workers の操作画面からから、PlanetScale のインテグレーションを設定すると、PlanetScale のデータベースに接続するための認証情報が作成され、その認証情報を Cloudflare Workers の変数として自動で設定してくれます

この機能によって、データベースの認証情報を自分で生成する必要がなくなります

やってみた

PlanetScaleにデータベースを作成

PlanetScale からデータベースを作成します。具体的な手順は以下を参考にしてください

Create a database — PlanetScale Documentation

今回はデータベースがされており、以下のSQLでテーブルが作成されてる前提とします

CREATE TABLE `posts` (
	`id` int NOT NULL AUTO_INCREMENT,
	`title` varchar(255),
	`content` text,
	PRIMARY KEY (`id`)
) ENGINE InnoDB,
  CHARSET utf8mb4,
  COLLATE utf8mb4_0900_ai_ci;

Cloudflare Workers のプロジェクトを作成

wrangler で Cloudflare Workers のプロジェクトを作成します。今回は TypeScript を選択しました。また、 Deploy with Cloudflareyesを選択しました。この後、PlanetScaleのインテグレーションを設定するのに、publish しておく必要があるためです

wrangler init planetscale-worker

PlanetScale に JavaScript から接続するための Driver をインストールします

npm install @planetscale/database

Cloudflare workers のコンパネから PlanetScale のインテグレーションを有効化する

インテグレーションの有効化を始めると Cloudflare に PlanetSclae のどのリソースにアクセスできる権限を与えるかを選ぶ画面が開きます。こちらで、権限を付与する Organization、Database、Branchを選びます

次に、今回連携するデーターベースを選択します。

全て選択し終えると Passwordがマスクされた状態でCredentialsが表示されます。ですが、こちらの情報を残しておかなくても問題ありません。自動でCloudfalrew Workers の変数に設定されます。

Cloudflare Workers の変数を確認するとそのことが確認できます

データベースに接続するコードを作成

env からPlanetScaleの接続情報を取得し、その接続情報を使って PlanetScale に接続し、データを取得するサンプルです。TypeScript だと Env インターフェースに変数のプロパティの宣言が必要になることに注意してください

src/workers.ts

import { connect, Config } from '@planetscale/database';

export interface Env {
  DATABASE_HOST: string;
  DATABASE_USERNAME: string;
  DATABASE_PASSWORD: string;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const config: Config = {
      host: env.DATABASE_HOST,
      username: env.DATABASE_USERNAME,
      password: env.DATABASE_PASSWORD,
      fetch: (url, init) => {
        if (init) {
          delete init['cache'];
        }

        return fetch(url, init);
      },
    };

    const conn = connect(config);

    const data = await conn.execute('SELECT * FROM posts');

    return new Response(JSON.stringify(data), {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  },
};

最後にデプロイして完了です

wrangler deploy

参考

Integrate Cloudflare Workers with PlanetScale

Integrate PlanetScale with Cloudflare Workers - YouTube

Cloudflare workers