こんにちは。pregum_foxです。
今回は備忘録なので短めです。
背景
ローカルの開発環境にて、毎回ユーザーを作成するのが大変なので、seed.sqlに固定したパスワードとメールアドレスで生成されるユーザーをsupabase db reset
コマンドを叩くと自動で生成されるようにしたかったので、調査しました。
前提条件
- dockerが起動していること
supabase init
コマンドが実行されてsupabase/config.tomlファイルが生成されていること- Supabase CLIがインストールされていること
- 設定するプロジェクトでemailのproviderが有効になっていること
- 具体的には以下のような設定になっていればOKです
- 具体的には以下のような設定になっていればOKです
環境
結論
seed.sqlが読み込めるようにconfig.tomlの最後にseed.sqlファイルを読み込む設定を追加します。
https://supabase.com/docs/guides/local-development/seeding-your-database
# 記述されている設定... # ↓ を追加 [db.seed] enabled = true sql_paths = ['./seeds/*.sql']
supabase/seeds/seed.sqlに以下の関数を書いて呼び出すことで実行できました。
Can't seed or signup auth users locally · supabase · Discussion #9251 · GitHub
-- ============================================ -- 1. 拡張機能とヘルパー関数の定義 -- ============================================ CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- 関数はこちらのコードをお借りした -- ref: https://github.com/orgs/supabase/discussions/9251#discussioncomment-6199552 -- パスワード付きのユーザーを作成する関数 CREATE OR REPLACE FUNCTION public.create_user_for_test( email text, password text ) RETURNS uuid AS $$ declare user_id uuid; encrypted_pw text; BEGIN user_id := gen_random_uuid(); encrypted_pw := crypt(password, gen_salt('bf')); INSERT INTO auth.users (instance_id, id, aud, role, email, encrypted_password, email_confirmed_at, recovery_sent_at, last_sign_in_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at, confirmation_token, email_change, email_change_token_new, recovery_token) VALUES ('00000000-0000-0000-0000-000000000000', user_id, 'authenticated', 'authenticated', email, encrypted_pw, '2023-05-03 19:41:43.585805+00', '2023-04-22 13:10:03.275387+00', '2023-04-22 13:10:31.458239+00', '{"provider":"email","providers":["email"]}', '{}', '2023-05-03 19:41:43.580424+00', '2023-05-03 19:41:43.585948+00', '', '', '', ''); INSERT INTO auth.identities (id, user_id, identity_data, provider, last_sign_in_at, created_at, updated_at, provider_id) VALUES (gen_random_uuid(), user_id, format('{"sub":"%s","email":"%s"}', user_id::text, email)::jsonb, 'email', '2023-05-03 19:41:43.582456+00', '2023-05-03 19:41:43.582497+00', '2023-05-03 19:41:43.582497+00', email); RETURN user_id; END; $$ LANGUAGE plpgsql;
実際に呼び出す場合はdoブロックで囲む必要があるので注意です。
doブロックで囲まないと、failed to send batch: ERROR: function public.create_user_for_test(text, text) does not exist (SQLSTATE 42883)
のようなエラーメッセージが表示され実行ができませんでした。
https://github.com/supabase/cli/issues/882#issuecomment-1595725535
下記の例では、以下の2つのusersレコードを作成しています。
- email:
dev1@example.com
, password:password123
- email:
dev2@example.com
, password:password123
-- ============================================ -- 3. 開発用データの作成 -- ============================================ -- 開発用のテストユーザーを追加(既存のテストユーザーに加えて) -- seed.sql内で関数を実行する場合は、doブロックで囲む必要があった -- ref: https://github.com/supabase/cli/issues/882#issuecomment-1595725535 do $$ begin -- ユーザーの作成 perform public.create_user_for_test('dev1@example.com'::text, 'password123'::text); perform public.create_user_for_test('dev2@example.com'::text, 'password123'::text); end $$;
生成したuser_idに対して何かしらのデータを紐付けたい場合は、doブロック内で変数を定義して、sqlを書くことで作成できました。
イメージ
-- ============================================ -- 3. 開発用データの作成 -- ============================================ -- 開発用のテストユーザーを追加(既存のテストユーザーに加えて) -- seed.sql内で関数を実行する場合は、doブロックで囲む必要がありました -- ref: https://github.com/supabase/cli/issues/882#issuecomment-1595725535 do $$ declare dev1_user_id uuid; dev2_user_id uuid; dev1_exhibition_id int; begin -- ユーザーの作成 dev1_user_id := public.create_user_for_test('dev1@example.com'::text, 'password123'::text); dev2_user_id := public.create_user_for_test('dev2@example.com'::text, 'password123'::text); -- dev1の展示会を作成 INSERT INTO public.exhibitions ( name, description, author_user_id, start_at, end_at, location, created_at, updated_at ) VALUES ( '開発用展示会1', '開発ユーザー1の展示会です', dev1_user_id, '2024-01-01 00:00:00+00', '2024-12-31 23:59:59+00', '開発美術館', NOW(), NOW() ) RETURNING id INTO dev1_exhibition_id; -- dev1の作品を作成 INSERT INTO public.artworks ( name, description, artist_name, author_user_id, exhibition_id, created_at, updated_at ) VALUES ( '開発用作品1', '開発用展示会1の作品1です', '開発作家1', dev1_user_id, dev1_exhibition_id, NOW(), NOW() ); -- 作品の画像を追加 INSERT INTO public.artwork_images ( image_url, storage_file_path, artwork_id, created_at ) VALUES ( 'https://example.com/dev/artworks/1/image1.jpg', 'dev/artworks/1/image1.jpg', currval('public.artworks_id_seq'), NOW() ); end $$;
seed.sql内の記述順は以下の順番であれば実行できました。
- 関数
- 関数呼び出し
sqlの変更が完了したら、supabase db reset
でseed.sqlを実行し直して、スキーマ、テーブルのレコードを作り直すことで反映が可能です。
手元のFlutterのアプリにてログインできることを確認しました。
もしローカル環境のレコード内にバックアップをとっておきたいデータがある場合は、先にpg_dumpコマンドやTable Plusのexportなどで保存しておくことを推奨します。
ここまで読んでいただきありがとうございます。