データベースオプション

このページ

EmDashは複数のデータベースバックエンドをサポートしています。デプロイ先に応じて選択してください。

概要

データベース最適な用途デプロイ先
D1Cloudflare Workersエッジ、グローバル分散
HyperdriveCloudflare Workers上のPostgreSQLエッジ、既存のPostgres
PostgreSQLNode.js本番環境Postgresが使えるあらゆるプラットフォーム
libSQLリモートデータベースエッジまたはNode.js
SQLiteNode.js、ローカル開発単一サーバー

Cloudflare D1

D1はCloudflareのサーバーレスSQLiteデータベースです。Cloudflare Workersにデプロイする場合に使用します。

import { d1 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: d1({ binding: "DB" }),
		}),
	],
});

設定

オプションデフォルト説明
bindingstringwrangler.jsoncのD1バインディング名
sessionstring"disabled"読み取りレプリケーションモード(下記参照)
bookmarkCookiestring"__em_d1_bookmark"セッションブックマーク用Cookie名

セットアップ

wrangler.jsonc

{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "emdash-db"
    }
  ]
}

wrangler.toml

[[d1_databases]]
binding = "DB"
database_name = "emdash-db"

リードレプリカ

D1はグローバルに分散されたサイトの読み取りレイテンシーを下げるために読み取りレプリケーションをサポートしています。有効にすると、読み取りクエリは常にプライマリデータベースを照会するのではなく、近くのレプリカにルーティングされます。

EmDashはD1 Sessions APIを使用してこれを透過的に管理します。sessionオプションで有効にします:

import { d1 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: d1({
				binding: "DB",
				session: "auto",
			}),
		}),
	],
});

セッションモード

モード動作
"disabled"セッションなし。すべてのクエリはプライマリへ。デフォルト。
"auto"匿名リクエストは最寄りのレプリカから読み取り。認証済みユーザーはブックマークCookieによるread-your-writes一貫性を取得。
"primary-first""auto"と同様だが、最初のクエリは常にプライマリへ。書き込みが非常に頻繁なサイト向け。

仕組み

  • 匿名訪問者first-unconstrainedを取得 — 最低レイテンシーのために最寄りのレプリカから読み取り。匿名ユーザーは書き込みを行わないため、一貫性保証は不要。
  • 認証済みユーザー(エディター、著者)はブックマークベースのセッションを取得。書き込み後、ブックマークCookieが次のリクエストが少なくともその状態を見ることを保証。
  • 書き込みリクエストPOSTPUTDELETE)は常にプライマリデータベースから開始。
  • ビルド時クエリ(Astroコンテンツコレクション)はセッションを完全にバイパスし、直接プライマリを使用。

libSQL

libSQLはリモート接続をサポートするSQLiteのフォークです。Cloudflare D1なしでリモートデータベースが必要な場合に使用します。

import { libsql } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: libsql({
				url: process.env.LIBSQL_DATABASE_URL,
				authToken: process.env.LIBSQL_AUTH_TOKEN,
			}),
		}),
	],
});

設定

オプション説明
urlstringデータベースURL(libsql://...またはfile:...
authTokenstringリモートデータベースの認証トークン(ローカルではオプション)

ローカル開発

開発中はローカルのlibSQLファイルを使用:

database: libsql({ url: "file:./data.db" });

PostgreSQL

PostgreSQLは完全なリレーショナルデータベースが必要なNode.jsデプロイメントでサポートされています。

import { postgres } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: postgres({
				connectionString: process.env.DATABASE_URL,
			}),
		}),
	],
});

設定

接続文字列または個別パラメータで接続できます:

// 接続文字列
database: postgres({
	connectionString: "postgres://user:password@localhost:5432/emdash",
});

// 個別パラメータ
database: postgres({
	host: "localhost",
	port: 5432,
	database: "emdash",
	user: "emdash",
	password: process.env.DB_PASSWORD,
	ssl: true,
});
オプション説明
connectionStringstringPostgreSQL接続URL
hoststringデータベースホスト
portnumberデータベースポート
databasestringデータベース名
userstringデータベースユーザー
passwordstringデータベースパスワード
sslbooleanSSLを有効化
pool.minnumberプール最小接続数(デフォルト0)
pool.maxnumberプール最大接続数(デフォルト10)

コネクションプーリング

アダプターは内部的にpg.Poolを使用します。デプロイメントに応じてプールサイズを調整してください:

database: postgres({
	connectionString: process.env.DATABASE_URL,
	pool: { min: 2, max: 20 },
});

Hyperdrive

hyperdrive()アダプターを使用して、既存のPostgreSQL — またはPostgres互換(例:PlanetScale Postgres)— データベースでCloudflare Workers上のEmDashを実行します。HyperdriveはCloudflareネットワーク経由で接続をプールし高速化します。EmDashのPostgreSQLダイアレクトがクエリを実行します。

import { hyperdrive, r2 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: hyperdrive({ binding: "HYPERDRIVE" }),
			storage: r2({ binding: "MEDIA" }),
		}),
	],
});

要件

  • サイトにpg >= 8.16.3がインストールされていること(pnpm add pg
  • compatibility_flags: ["nodejs_compat"]
  • compatibility_date >= "2024-09-23"

セットアップ

Hyperdrive設定を作成し、Wrangler設定にバインディングを追加します:

wrangler hyperdrive create emdash-db \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full" \
  --caching-disabled

wrangler.jsonc

{
  "hyperdrive": [
    {
      "binding": "HYPERDRIVE",
      "id": "<your-hyperdrive-id>"
    }
  ]
}

wrangler.toml

[[hyperdrive]]
binding = "HYPERDRIVE"
id = "<your-hyperdrive-id>"

設定

オプションデフォルト説明
bindingstring"HYPERDRIVE"プライマリ(キャッシュ無効)Hyperdriveバインディング
cachedBindingstring匿名読み取り用のキャッシュ有効オプショナルバインディング
maxnumber5Hyperdriveへのインワーカーコネクションプールの最大サイズ

匿名読み取りをキャッシュから提供する

デフォルトでは、管理画面と書き込みがread-after-write一貫性を必要とするため、Hyperdriveキャッシュを完全に無効にします。しかし匿名パブリック読み取り — セッションなし、書き込みなし — は短い古いデータのウィンドウを許容できます。このトレードオフが許容できる場合、同じデータベース上で2つのHyperdrive設定を実行します:1つはキャッシュ無効(プライマリbinding)、もう1つはキャッシュ有効(cachedBinding)。EmDashは匿名読み取りリクエストをキャッシュ有効バインディング経由でルーティングし、すべての認証済みリクエストと書き込みはキャッシュなしのプライマリに留まり、read-after-write一貫性を維持します。

# プライマリ — キャッシュ無効(管理、認証リクエスト、書き込み、マイグレーション用)
wrangler hyperdrive create emdash-db \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full" \
  --caching-disabled

# キャッシュ有効 — 同じ接続文字列、キャッシュ有効(匿名読み取り専用)
wrangler hyperdrive create emdash-db-cached \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full"
{
	"hyperdrive": [
		{ "binding": "HYPERDRIVE", "id": "<caching-disabled-id>" },
		{ "binding": "HYPERDRIVE_CACHED", "id": "<caching-enabled-id>" }
	]
}
database: hyperdrive({ binding: "HYPERDRIVE", cachedBinding: "HYPERDRIVE_CACHED" });

これはCloudflareがキャッシュ用にドキュメント化している2構成パターンです。EmDashはリクエストごとにどのバインディングを使用するか判断します:

  • パブリックサイトパスの匿名読み取りGET/HEAD、セッションなし、/_emdash配下でない)→ キャッシュ有効cachedBinding
  • 認証済みリクエスト(エディター、著者)→ キャッシュなしbinding
  • 書き込みPOSTPUTDELETE、匿名含む)→ キャッシュなしbinding
  • /_emdash配下のすべてのリクエスト(管理、セットアップ、認証、内部API)、匿名GETも含む → キャッシュなしbinding
  • マイグレーションとコールドスタート → 常にプライマリbinding

SQLite

better-sqlite3によるSQLiteは、Node.jsデプロイメントの最もシンプルなオプションです。

import { sqlite } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
		}),
	],
});

設定

オプション説明
urlstringfile:プレフィックス付きファイルパス

ファイルパス

urlfile:で始まる必要があります:

// 相対パス
database: sqlite({ url: "file:./data/emdash.db" });

// 絶対パス
database: sqlite({ url: "file:/var/data/emdash.db" });

// 環境変数から
database: sqlite({ url: `file:${process.env.DATABASE_PATH}` });

マイグレーション

EmDashはサポートされるすべてのダイアレクト(D1、SQLite、libSQL、PostgreSQL)で最初のリクエスト時にマイグレーションを自動実行します。マイグレーションはemdashパッケージにバンドルされ、ビルドに埋め込まれます。

データベースが空(コレクションなし)でセットアップウィザードが完了していない場合、EmDashは初回起動時にシードファイルも適用します。シードは.emdash/seed.jsonpackage.json#emdash.seedのパス、またはseed/seed.jsonから読み取られます — 最初に見つかったもの — そしてコンパイル時にビルドに組み込まれます。いずれも存在しない場合、組み込みのデフォルトシードが使用されます。既存のデータベースに対する以降の起動はそのコンテンツを変更しません。

環境ベースの設定

環境ごとに異なるデータベースを使用:

import { sqlite, libsql, postgres } from "emdash/db";
import { d1 } from "@emdash-cms/cloudflare";

const database = import.meta.env.PROD ? d1({ binding: "DB" }) : sqlite({ url: "file:./data.db" });

export default defineConfig({
	integrations: [emdash({ database })],
});

ビルドモードではなく環境変数に基づいて選択することもできます:

const database = process.env.DATABASE_URL
	? postgres({ connectionString: process.env.DATABASE_URL })
	: sqlite({ url: "file:./data.db" });