M1 기반: 모노레포, 공통 엔진, 공용 프로토콜, 오목 엔진, 서버 골격
- packages/engine: 시드 RNG(sfc32), GameDefinition 타입, 무작위 대국·정보 유출 테스트 도구 - packages/shared: WS 프로토콜 스키마, 닉네임·방 코드 규칙, 게임 카탈로그 - packages/games/omok: 한국식·렌주·자유룰, 재귀 금수 판정, 무르기·무승부·시계 (테스트 27개) - apps/server: SQLite 스키마, 게스트·디스코드 로그인, 세션, 방 관리(저장·복구·타이머·재접속), WS 게이트웨이, HTTP API Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
100
apps/server/src/db/migrations/001_init.sql
Normal file
100
apps/server/src/db/migrations/001_init.sql
Normal file
@@ -0,0 +1,100 @@
|
||||
CREATE TABLE users (
|
||||
id TEXT PRIMARY KEY,
|
||||
kind TEXT NOT NULL CHECK (kind IN ('guest','member')),
|
||||
nickname TEXT NOT NULL,
|
||||
avatar_url TEXT,
|
||||
use_avatar INTEGER NOT NULL DEFAULT 1,
|
||||
settings_json TEXT NOT NULL DEFAULT '{}',
|
||||
nick_changed_at INTEGER,
|
||||
nick_change_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at INTEGER NOT NULL,
|
||||
last_seen_at INTEGER NOT NULL,
|
||||
deleted_at INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_accounts (
|
||||
provider TEXT NOT NULL,
|
||||
provider_user_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
username TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (provider, provider_user_id)
|
||||
);
|
||||
CREATE INDEX oauth_accounts_user ON oauth_accounts(user_id);
|
||||
|
||||
CREATE TABLE sessions (
|
||||
token_hash TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
created_at INTEGER NOT NULL,
|
||||
expires_at INTEGER NOT NULL,
|
||||
last_used_at INTEGER NOT NULL,
|
||||
user_agent TEXT
|
||||
);
|
||||
CREATE INDEX sessions_user ON sessions(user_id);
|
||||
|
||||
CREATE TABLE rooms (
|
||||
id TEXT PRIMARY KEY,
|
||||
code TEXT NOT NULL,
|
||||
host_id TEXT NOT NULL,
|
||||
game_id TEXT NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('lobby','playing','finished','paused','broken','closed')),
|
||||
visibility TEXT NOT NULL,
|
||||
config_json TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL,
|
||||
closed_at INTEGER
|
||||
);
|
||||
CREATE UNIQUE INDEX rooms_open_code ON rooms(code) WHERE status <> 'closed';
|
||||
CREATE INDEX rooms_status ON rooms(status);
|
||||
|
||||
CREATE TABLE room_state (
|
||||
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
||||
seq INTEGER NOT NULL,
|
||||
state_json TEXT NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE room_log (
|
||||
room_id TEXT NOT NULL,
|
||||
seq INTEGER NOT NULL,
|
||||
game_no INTEGER NOT NULL,
|
||||
actor_id TEXT,
|
||||
kind TEXT NOT NULL,
|
||||
data_json TEXT NOT NULL,
|
||||
at INTEGER NOT NULL,
|
||||
PRIMARY KEY (room_id, seq)
|
||||
);
|
||||
|
||||
CREATE TABLE games (
|
||||
id TEXT PRIMARY KEY,
|
||||
room_id TEXT NOT NULL,
|
||||
game_no INTEGER NOT NULL,
|
||||
game_id TEXT NOT NULL,
|
||||
options_json TEXT NOT NULL,
|
||||
seed_hash TEXT NOT NULL,
|
||||
seed TEXT,
|
||||
started_at INTEGER NOT NULL,
|
||||
ended_at INTEGER,
|
||||
end_reason TEXT,
|
||||
result_json TEXT
|
||||
);
|
||||
CREATE INDEX games_room ON games(room_id);
|
||||
|
||||
CREATE TABLE game_players (
|
||||
game_pk TEXT NOT NULL REFERENCES games(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL,
|
||||
seat INTEGER NOT NULL,
|
||||
rank INTEGER,
|
||||
score REAL,
|
||||
PRIMARY KEY (game_pk, user_id)
|
||||
);
|
||||
CREATE INDEX game_players_user ON game_players(user_id);
|
||||
|
||||
CREATE TABLE user_stats (
|
||||
user_id TEXT NOT NULL,
|
||||
game_id TEXT NOT NULL,
|
||||
played INTEGER NOT NULL DEFAULT 0,
|
||||
wins INTEGER NOT NULL DEFAULT 0,
|
||||
draws INTEGER NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (user_id, game_id)
|
||||
);
|
||||
Reference in New Issue
Block a user