zuburi-game-platform
v0.2.8
Published
Framework-independent TypeScript SDK for KZTK Game Platform
Readme
zuburi-game-platform
ZUBURI のゲームから ZUBURI Game Platform を利用するための React 非依存 TypeScript SDK です。
Install
pnpm add zuburi-game-platform @supabase/supabase-jsBasic usage
import { createGamePlatformClient } from 'zuburi-game-platform'
import { supabase } from '../lib/supabase'
export const platform = createGamePlatformClient({
supabase,
gameId: 'coffee_roaster',
})SDK は Supabase Client を生成しません。service_role / Secret key / userId は渡しません。
Storage policy
Game Platform は履歴を蓄積せず、現在状態を保持する state-first 構成です。
保持する主な値:
- ポイント現在残高・累積獲得・累積消費
- 実績進捗・解除状態
- ログインボーナス現在状態
- 各ゲームの必要な集計値
イベント履歴、ポイント増減履歴、開封履歴などは原則保存しません。
詳細: ../../docs/STATE_FIRST_STORAGE_POLICY.md
Client events
ゲームから送信できるイベントは Platform 標準の4種類だけです。
game_started
ゲーム開始。value に開始時の数値を付けてもよい
game_finished
ゲーム終了。value に最終スコアなどを付けてもよい
personal_best_updated
自己ベスト更新。value 必須
item_obtained
アイテム獲得。metadata.itemId 必須、quantity は任意import { PLATFORM_EVENTS } from 'zuburi-game-platform'
await platform.events.emit({
type: PLATFORM_EVENTS.GAME_STARTED,
value: 1,
})
await platform.events.emit({
type: PLATFORM_EVENTS.GAME_FINISHED,
sourceId: 'run:123',
value: 85,
})
await platform.events.emit({
type: PLATFORM_EVENTS.PERSONAL_BEST_UPDATED,
value: 120,
})
await platform.events.emit({
type: PLATFORM_EVENTS.ITEM_OBTAINED,
metadata: {
itemId: 'golden-bean',
quantity: 1,
},
})独自 EventMap をゲーム側から追加する API はありません。TypeScript の型を回避して任意文字列を渡しても SDK が送信前に拒否します。
sourceId は Event Definition で必要な場合の識別情報です。イベントはDBへ永続保存されません。
永続イベント行による idempotency 管理を行わないため、SDKは書き込みRPCを自動リトライしません。読み取りRPCのみ一時エラー時に最大1回リトライします。
Points
const account = await platform.points.getAccount()
account.balance
account.lifetimeEarned
account.lifetimeSpentポイント履歴取得、points.add()、points.set() はありません。
Score multiplier rewards
Point Reward Rule は管理画面で次の2方式を選べます。
fixed: Event 1回につき固定ポイントを加算value_multiplier: Event のvalue × 倍率を端数切り捨てして加算
たとえば倍率を 0.1 にして、ゲーム終了時にスコア 1234 を送ると 123pt 加算されます。
const result = await platform.events.emit({
type: PLATFORM_EVENTS.GAME_FINISHED,
value: 1234,
})
console.log(result.points.delta) // 123(倍率0.1の場合)倍率はフロント側で掛けず、Backend が管理画面の設定を参照して計算します。倍率ルールで value がない、または負数の場合は Event を拒否します。
ブラウザから送る value 自体は改変可能です。改変耐性が必要なスコアはゲーム固有RPCで検証して trusted event を使ってください。
Achievements
const achievements = await platform.achievements.list()進捗・解除判定・報酬付与は Backend が行います。
Login bonus
const status = await platform.loginBonus.getStatus()
const result = await platform.loginBonus.claimAvailable()
await platform.loginBonus.claimProgram('summer_campaign_2026')受取履歴を毎回追加せず、ユーザー・プログラムごとの現在状態を更新します。
Development write guard
const platform = createGamePlatformClient({
supabase,
gameId: 'coffee_roaster',
writesEnabled: import.meta.env.VITE_DEVELOPMENT_MODE !== 'true',
})writesEnabled=false の場合、Event送信とLogin Bonus claimは WRITE_DISABLED になります。
Security boundary
SDKは意図的に以下を提供しません。
points.add()
points.set()
points.listTransactions()
achievements.unlock()
achievements.setProgress()
events.emitTrusted()スコア・勝敗など改変耐性が必要な処理はゲーム固有RPCで検証してください。
Repository development
pnpm install
pnpm checkSDK build は dist を削除してから生成します。
Publishing
main への変更は既存の Release workflow の対象です。
