コンテンツにスキップ

Node.js の基本

@pgmem/core は pgmem バイナリを起動し、PostgreSQL の URL を渡してくれます。バイナリは npm がオプション依存としてインストールするプラットフォーム別パッケージに入っています。postinstall スクリプトはなく、実行時のダウンロードもありません。pgmem は PostgreSQL クライアントや ORM を置き換えるものではありません。Prisma、Drizzle、TypeORM、Kysely、pgpostgres は、ほかのサーバーと同じように URL へ接続するだけで、プールもそのまま使えます。

pgmem と、使っている公式クライアントを一緒にインストールします。

ターミナルウィンドウ
npm install --save-dev @pgmem/core pg

pgnode-postgres です。postgres.js、Prisma、Drizzle、TypeORM も同じように使えるので、アプリケーションで使っているものを入れてください。Node.js 20 以降が必要です。バイナリのパッケージは Linux と macOS の x64・arm64、Windows の x64・arm64 向けにあります。それ以外の環境では PGMEM_BINARYcmd/pgmem のビルドを指定してください。

  1. サーバーを起動します。 PgmemServer.start() はバイナリを起動し、テンプレートのデータベースに対して prepare を実行し、その結果をスナップショットにします。フォークはそこから始まります。

    import { PgmemServer } from '@pgmem/core';
    await using server = await PgmemServer.start({
    database: 'app',
    async prepare({ url }) {
    await migrate(url);
    await seed(url);
    },
    });
    console.log(server.url); // postgres://postgres@127.0.0.1:54321/app?sslmode=disable

    await using はスコープの終わりでサーバーを閉じます。明示的なリソース管理が使えない環境では server.close() を自分で呼んでください。ほかのオプションは userparams{ log_statement: 'all' } のような postgres の設定のオブジェクト)、maxForkswaitTimeoutMslogbinary です。

  2. スキーマを登録します。 prepare の中で行います。prepare にはテンプレートのサーバー(urlhostportuserdatabase)が渡されます。マイグレーションツールを参照してください。

  3. シードデータを入れます。 これも prepare の中です。シードデータを参照してください。スナップショットは開いているトランザクションを待つので、prepare で開いた接続はすべて閉じるかコミットしてください。

  4. 公式クライアントから使います。

    import pg from 'pg';
    const pool = new pg.Pool({ connectionString: server.url });
    const { rows } = await pool.query('SELECT name FROM users WHERE id = $1', [1]);
    await pool.end();

    URL の sslmode=disable は残してください。pgpreferrequire を「TLS 必須」と扱いますが、pgmem には TLS がありません。

どのツールも URL を受け取ります。prepare の中で実行すれば、テンプレートに対して一度だけ走ります。

import { readFile } from 'node:fs/promises';
import pg from 'pg';
async function migrate(url: string) {
const client = new pg.Client({ connectionString: url });
await client.connect();
await client.query(await readFile('schema.sql', 'utf8'));
await client.end();
}

node-postgres はパラメータのないクエリを 1 回のシンプルクエリとして送るので、複数の文を書いてかまいません。

prisma migrate dev でマイグレーションを作る

Section titled “prisma migrate dev でマイグレーションを作る”

prisma migrate dev にはシャドウデータベースが必要です。pgmem のサーバーは持っているすべてのデータベースに接続できるので、Prisma は同じメモリ上のサーバーにシャドウデータベースを作ります。ローカルに PostgreSQL がなくてもマイグレーションを作れます。

scripts/migrate-dev.mjs
import { spawnSync } from 'node:child_process';
import { PgmemServer } from '@pgmem/core';
const server = await PgmemServer.start({ database: 'app', control: false });
try {
const run = spawnSync('npx', ['prisma', 'migrate', 'dev', ...process.argv.slice(2)], {
stdio: 'inherit',
env: { ...process.env, DATABASE_URL: server.url },
shell: process.platform === 'win32',
});
process.exitCode = run.status ?? 1;
} finally {
await server.close();
}
ターミナルウィンドウ
node scripts/migrate-dev.mjs --name add_posts
await client.query(await readFile('seed.sql', 'utf8'));
await using fork = await server.fork(); // 準備済みデータベースの専用の複製
await useDatabase(fork.url);
// pgmem に閉じてもらう書き方
await server.withFork(async (fork) => {
await useDatabase(fork.url);
});
// URL を変えずにフォークをスナップショットの状態に戻す
await fork.reset();

生きているフォークが maxForks 個あると、次のフォークは空きが出るまで待ちます。フォークを閉じても、アイドル状態のプール接続はプールに任されます。error リスナーのないプールでもプロセスが落ちることはありません。次のページでは、テストランナーからの使い方を紹介します。