Skip to content

Supabase Type Strategy

Barbelic 앱은 장기적으로 Supabase generated database type을 사용합니다. 다만 TypeScript 전면 이전 초기 단계에서는 운영 DB와 네트워크에 의존하지 않고 진행해야 하므로, 프론트가 직접 읽는 row와 RPC부터 수동 최소 타입으로 고정합니다.

Current Manual Baseline

  • 기준 파일: src/react/types/supabase.ts
  • 화면 RPC 응답 타입: src/react/types/screenRpc.ts
  • 직접 table select row 타입: SupabaseTableRowMap
  • 직접 RPC 호출 타입: SupabaseRpcArgsMap, SupabaseRpcReturnMap
  • generated type 호환 껍데기: SupabaseDatabaseManual

현재 수동 row 타입은 프론트 repository가 직접 접근하는 테이블만 포함합니다.

txt
profiles
user_consents
exercise_archetypes
exercises
wodup_exercises
exercise_external_mappings
session
session_exercise
session_exercise_part
exercise_set
exercise_set_part
user_manual_pr_records
daily_conditions
user_exercise_stats
user_exercise_records
user_exercise_pr_states
user_exercise_pr_events
user_exercise_period_stats
user_training_period_stats
user_calendar_day_summaries
user_exercise_session_rollups
wodup_import_batches

user_exercise_estimated_1rm_records는 정책 v1 migration이 비우고 더 이상 화면에서 읽지 않는 legacy projection이므로 수동 frontend table map에서도 제거한다. e1RM은 user_exercise_strength_observations, user_exercise_strength_daily, user_exercise_strength_states에 정책/곡선 버전과 함께 저장하지만 프론트가 이 원시 테이블을 직접 읽지는 않는다. 실제 수행 1..20RM은 기존 PR state/event에만 저장하며, 화면은 버전이 고정된 RPC payload를 사용한다.

화면 RPC payload는 table row 그대로가 아니라 화면 계약입니다. 그래서 get_home_dashboard, get_calendar_month_summary, get_calendar_day_summary, get_session_detail, get_planned_session_detail, get_pr_overview, get_volume_overviewScreenRpcPayloadMap과 adapter output 타입으로 따로 관리합니다.

The session frontend write contract exposes only save_session_v5 (create/update of completed records, plans and group plans) and delete_session_v5 (issue #1215, 2026-09-04; the v4 completed writers and v3 plan writers are retired LG426 stubs). Their owner binding is required in the typed payload. rpc() accepts only the active literal union; there is no generic string escape hatch or retired-name production union.

Future Generated Types

운영 DB 접근과 Supabase CLI 기준이 안정되면 아래 명령으로 generated type을 만듭니다.

bash
supabase gen types typescript --project-id kobxeylancdimqhfkbnl

권장 출력 위치:

txt
src/react/types/supabase.generated.ts

그 다음 단계:

  1. SupabaseDatabaseManual과 generated Database를 비교합니다.
  2. SupabaseTableRowMap을 generated table Row 기반으로 교체합니다.
  3. 프론트가 직접 읽지 않는 table은 앱 화면 타입에 노출하지 않습니다.
  4. 화면 RPC payload는 계속 screenRpc.ts 계약을 우선합니다.

Rules

  • 운영 DB가 필요한 generated type 갱신은 별도 PR에서 수행합니다.
  • 프론트 화면 코드는 DB table shape 대신 domain/screen API 타입을 우선 사용합니다.
  • raw table row 타입은 repository/admin/debug/import 경로에서만 사용합니다.
  • JsonValueJsonObject는 원본 payload, metadata, Supabase JSONB 컬럼에만 사용합니다.
  • generated type 도입 전까지 새 table select가 생기면 SupabaseTableRowMap에 먼저 추가합니다.
  • 알려진 RPC literal은 generic JSON fallback보다 SupabaseRpcArgsMap을 우선하며, 필수 인자가 빠진 호출은 타입 검사에서 실패해야 합니다.
  • Plans are session rows with status = planned and go through the same save_session_v5 payload (contract_version: 5, expected_user_id, immutable source_ref; updates additionally require id and expected_revision). Both save_session_v5 and delete_session_v5 require a durable client mutation UUID plus request hash and return a versioned mutation receipt (v2). The former save_plan_v3 / delete_planned_session_v2 and their expected_updated_at lock are retired (issue #1215, 2026-09-04). Retired workout/plan writer and reconciliation RPCs are compile-time blocked and absent from the public RPC maps.