DB仕様 概要
Speakeasy は 2つの PostgreSQL データベース を使用し、業務データと認証データを分離しています。ORM には Drizzle ORM v1.0 beta を採用し、Cloudflare Hyperdrive 経由で接続プーリングを行います。
データベース構成
Section titled “データベース構成”| DB | パッケージ | 用途 | 使用サービス |
|---|---|---|---|
| Cellar | @speakeasy/cellar | 業務データ(連絡先・チャット・店舗・配信・通知) | Fizz, Vintage, Bell, Base, Tap |
| Vault | @speakeasy/vault | 認証データ(ユーザー・セッション・組織・OAuth) | Proof, Bell |
注意:
VAULT_HYPERDRIVEとPROOF_HYPERDRIVEは同じ Vault DB を指しますが、サービスごとにバインディング名が異なります。
技術スタック
Section titled “技術スタック”| 項目 | 技術 | バージョン |
|---|---|---|
| ORM | Drizzle ORM | 1.0.0-beta.12 |
| マイグレーション | Drizzle Kit | 0.31.1-beta.1 |
| データベース | PostgreSQL | Prisma Postgres |
| 接続プーリング | Cloudflare Hyperdrive | — |
| スキーマ定義 | drizzle-orm/pg-core | — |
| リレーション | Relations V2 (defineRelations) | — |
Cellar DB(業務データベース)
Section titled “Cellar DB(業務データベース)”25 テーブルで構成される業務データベースです。
| カテゴリ | テーブル数 | 主なテーブル |
|---|---|---|
| 連絡先 | 4 | contact, contact_purelovers, contact_chat_ng, contact_chat_ng_history |
| チャット | 4 | chat_room, chat_message, user_room_state, chat_attachment |
| 店舗 | 4 | shop, shop_line_account, shop_transfer, shop_purelovers |
| 一括配信 | 1 | broadcast |
| ラベル | 1 | label |
| 通知 | 2 | shop_notification, notification_setting |
| 店舗通知 | 3 | shop_notification_setting, shop_push_subscription, shop_email_recipient |
| 顧客通知 | 2 | customer_notification_setting, customer_push_subscription |
| PUSH | 2 | push_subscription, push_message |
| ブラックリスト | 2 | domain_blacklist, global_domain_blacklist |
詳細は Cellar DB 概要 を参照してください。
Vault DB(認証データベース)
Section titled “Vault DB(認証データベース)”18 テーブルで構成される認証データベースです。better-auth のプラグインテーブルとカスタムテーブルを含みます。
| カテゴリ | テーブル数 | 主なテーブル |
|---|---|---|
| ユーザー | 4 | user, session, account, verification |
| 組織 | 5 | organization, member, organizationRole, memberRole, invitation |
| APIキー・パスキー | 2 | apikey, passkey |
| OAuth | 4 | oauthApplication, oauthAccessToken, oauthConsent, scimProvider |
| カスタム | 2 | outerMail, outerPhone |
詳細は Vault DB 概要 を参照してください。
共通設計規約
Section titled “共通設計規約”全テーブルは text 型の id カラムを主キーとして使用します(UUID v4)。
id: p.text().primaryKey();タイムスタンプ
Section titled “タイムスタンプ”全テーブルに createdAt / updatedAt カラムを持ちます。
createdAt: p.timestamp('createdAt', { withTimezone: true, precision: 3 }).defaultNow().notNull();updatedAt: p.timestamp('updatedAt', { withTimezone: true, precision: 3 }).defaultNow().notNull();- タイムゾーン付き(
withTimezone: true) - ミリ秒精度(
precision: 3) - デフォルト値:
NOW()
インデックス命名規則
Section titled “インデックス命名規則”| 種別 | パターン | 例 |
|---|---|---|
| 通常インデックス | {table}_{column}_idx | contact_shopId_idx |
| ユニークインデックス | {table}_{columns}_key | contact_chat_ng_contactId_ngType_key |
| 複合インデックス | {table}_{col1}_{col2}_idx | chat_message_roomId_sentAt_idx |
| GIN インデックス | {table}_{column}_idx (using: ‘gin’) | notification_setting_channels_idx |
リレーション定義
Section titled “リレーション定義”Drizzle ORM v1.0 beta の Relations V2 (defineRelations) を使用しています。
import { defineRelations } from 'drizzle-orm';
export const relations = defineRelations(schema, (r) => ({ // one-to-many shop: { contacts: r.many.contact(), chatRooms: r.many.chatRoom() }, // many-to-one contact: { shop: r.one.shop({ from: r.contact.shopId, to: r.shop.id }) }}));詳細は Cellar リレーション / Vault リレーション を参照してください。
セクション構成
Section titled “セクション構成”| ページ | 内容 |
|---|---|
| Cellar DB 概要 | 業務 DB 全テーブル一覧 |
| Vault DB 概要 | 認証 DB 全テーブル一覧 |
| ER図 | 全テーブルの関係図(Mermaid) |
| マイグレーション管理 | Drizzle Kit によるマイグレーション手順 |