{"version":3,"sources":["../src/index.ts","../src/messenger.ts","../src/sdk.ts","../src/types.ts"],"sourcesContent":["/**\n * @metaarena/sdk\n *\n * MetaArena 게임 SDK — 브라우저에서 동작하는 게임을 토너먼트 플랫폼에 연동합니다.\n *\n * @example\n * ```typescript\n * import { MetaArenaSDK } from '@metaarena/sdk'\n *\n * const sdk = new MetaArenaSDK()\n *\n * sdk.onStart(({ tournamentId, playerToken }) => {\n *   startGame()\n * })\n *\n * sdk.updateScore(score)\n * sdk.gameOver({ score, playTimeMs })\n * ```\n */\n\nexport { MetaArenaSDK, SDK_VERSION } from './sdk.js'\nexport { HostMessenger }             from './messenger.js'\nexport { SDKError }                  from './types.js'\nexport type {\n  GameStartContext,\n  GameOverPayload,\n  OutboundMessage,\n  InboundMessage,\n} from './types.js'\n","/**\n * postMessage 기반 iframe ↔ 플랫폼 통신 모듈\n *\n * 게임(iframe)과 MetaArena 플랫폼(부모 창) 사이의 메시지 교환을 담당합니다.\n * SDK 내부에서만 사용합니다.\n */\n\nimport type { OutboundMessage, InboundMessage } from './types.js'\n\ntype InboundType = InboundMessage['type']\ntype MessageHandler<T = unknown> = (data: T) => void\n\nexport class Messenger {\n  private handlers = new Map<string, MessageHandler[]>()\n  private boundListener: (event: MessageEvent) => void\n\n  constructor() {\n    this.boundListener = this.handleMessage.bind(this)\n    window.addEventListener('message', this.boundListener)\n  }\n\n  /** 수신 메시지 핸들러 등록 */\n  on<T extends InboundMessage>(type: T['type'], handler: MessageHandler<T>): void {\n    const existing = this.handlers.get(type) ?? []\n    this.handlers.set(type, [...existing, handler as MessageHandler])\n  }\n\n  /** 수신 메시지 핸들러 해제 */\n  off<T extends InboundMessage>(type: T['type'], handler: MessageHandler<T>): void {\n    const existing = this.handlers.get(type) ?? []\n    this.handlers.set(type, existing.filter(h => h !== handler))\n  }\n\n  /** 부모 창(플랫폼)으로 메시지 전송 */\n  sendToHost(message: OutboundMessage): void {\n    if (typeof window === 'undefined' || window.parent === window) return\n    window.parent.postMessage(message, '*')\n  }\n\n  private handleMessage(event: MessageEvent): void {\n    const data = event.data as InboundMessage | null\n    if (!data?.type?.startsWith('METAARENA_')) return\n\n    const handlers = this.handlers.get(data.type) ?? []\n    handlers.forEach(handler => handler(data))\n  }\n\n  /** 이벤트 리스너 해제 */\n  destroy(): void {\n    window.removeEventListener('message', this.boundListener)\n    this.handlers.clear()\n  }\n}\n\n/**\n * 플랫폼(호스트) 측 헬퍼 — 게임 iframe으로 GAME_START를 전송할 때 사용\n * (MetaArena 플랫폼 코드에서 사용, 게임 개발자가 직접 사용할 일 없음)\n */\nexport class HostMessenger {\n  sendGameStart(\n    frame: HTMLIFrameElement,\n    payload: { tournament_id: string; player_token: string; api_base: string },\n  ): void {\n    const origin = frame.src ? new URL(frame.src).origin : '*'\n    frame.contentWindow?.postMessage({ type: 'METAARENA_GAME_START', ...payload }, origin)\n  }\n}\n","/**\n * MetaArenaSDK — 메인 클래스\n *\n * 브라우저에서 동작하는 게임(iframe)이 MetaArena 플랫폼과 통신하는 SDK입니다.\n * API Key / Secret은 필요 없습니다 — 클라이언트 사이드 점수 제출은 플랫폼이 처리합니다.\n *\n * @example\n * ```typescript\n * import { MetaArenaSDK } from '@metaarena/sdk'\n *\n * const sdk = new MetaArenaSDK()\n *\n * sdk.onStart(({ tournamentId, playerToken }) => {\n *   // playerToken: 서버 사이드 게임이라면 게임 서버로 전달\n *   startGame()\n * })\n *\n * sdk.updateScore(currentScore)  // HUD 업데이트\n *\n * sdk.gameOver({ score: currentScore, playTimeMs: elapsed })\n * ```\n */\n\nimport { Messenger } from './messenger.js'\nimport type { GameStartContext, GameOverPayload, GameStartMessage } from './types.js'\n\nexport const SDK_VERSION = '1.0.0'\n\nexport class MetaArenaSDK {\n  private messenger: Messenger\n  private startCallbacks: Array<(ctx: GameStartContext) => void> = []\n\n  constructor() {\n    this.messenger = new Messenger()\n    // 플랫폼이 보내는 GAME_START 메시지 수신 등록\n    this.messenger.on<GameStartMessage>('METAARENA_GAME_START', msg => {\n      const ctx: GameStartContext = {\n        tournamentId: msg.tournament_id,\n        playerToken:  msg.player_token,\n        apiBase:      msg.api_base ?? 'https://api.metaarena.io',\n      }\n      this.startCallbacks.forEach(cb => cb(ctx))\n    })\n    // 플랫폼에 SDK 로드 완료 알림 → 플랫폼이 GAME_START로 응답\n    this.messenger.sendToHost({ type: 'METAARENA_READY' })\n  }\n\n  /**\n   * 게임 시작 신호 수신 핸들러 등록\n   * 플랫폼이 METAARENA_GAME_START를 전송하면 호출됩니다.\n   */\n  onStart(callback: (ctx: GameStartContext) => void): void {\n    this.startCallbacks.push(callback)\n  }\n\n  /**\n   * 현재 점수를 플랫폼 HUD에 실시간 반영\n   * 점수가 바뀔 때마다 호출합니다. 이 메서드만으로는 점수가 제출되지 않습니다.\n   */\n  updateScore(score: number): void {\n    this.messenger.sendToHost({ type: 'METAARENA_SCORE', score })\n  }\n\n  /**\n   * 게임 종료 처리\n   *\n   * - 플랫폼에 GAME_OVER 신호를 전송해 게임 오버 모달을 표시합니다.\n   * - 클라이언트 사이드 게임: 플랫폼이 자동으로 MetaArena API에 점수를 제출합니다.\n   * - 서버 사이드 게임: UI 표시만 수행하며, 점수 제출은 게임 서버에서 직접 처리합니다.\n   */\n  gameOver({ score, playTimeMs }: GameOverPayload): void {\n    this.messenger.sendToHost({\n      type: 'METAARENA_GAME_OVER',\n      score,\n      play_time_ms: playTimeMs,\n    })\n  }\n\n  /** SDK 및 이벤트 리스너 정리 */\n  destroy(): void {\n    this.messenger.destroy()\n    this.startCallbacks = []\n  }\n}\n","/**\n * @metaarena/sdk 타입 정의\n */\n\n/** onStart() 콜백으로 전달되는 게임 시작 컨텍스트 */\nexport interface GameStartContext {\n  /** 현재 토너먼트 UUID */\n  tournamentId: string\n  /** 플레이어 JWT — 서버 사이드 게임에서 서버로 전달해 점수 제출 시 사용 */\n  playerToken: string\n  /** MetaArena API 베이스 URL (환경별 자동 설정) */\n  apiBase: string\n}\n\n/** gameOver() 에 전달하는 페이로드 */\nexport interface GameOverPayload {\n  /** 최종 점수 (0 이상 정수) */\n  score: number\n  /** 총 플레이 시간 (밀리초). 서버 범위 검증에 활용되므로 포함 권장 */\n  playTimeMs?: number\n}\n\n// ── 플랫폼 → 게임 (수신) ─────────────────────────────────────\n\nexport interface GameStartMessage {\n  type: 'METAARENA_GAME_START'\n  tournament_id: string\n  player_token: string\n  api_base?: string\n}\n\n// ── 게임 → 플랫폼 (송신) ─────────────────────────────────────\n\nexport interface ReadyMessage    { type: 'METAARENA_READY' }\nexport interface ScoreMessage    { type: 'METAARENA_SCORE'; score: number }\nexport interface GameOverMessage { type: 'METAARENA_GAME_OVER'; score: number; play_time_ms?: number }\n\nexport type OutboundMessage = ReadyMessage | ScoreMessage | GameOverMessage\nexport type InboundMessage  = GameStartMessage\n\n/** SDK 에러 */\nexport class SDKError extends Error {\n  constructor(message: string, public readonly code: string) {\n    super(message)\n    this.name = 'SDKError'\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACYO,IAAM,YAAN,MAAgB;AAAA,EAIrB,cAAc;AAHd,SAAQ,WAAW,oBAAI,IAA8B;AAInD,SAAK,gBAAgB,KAAK,cAAc,KAAK,IAAI;AACjD,WAAO,iBAAiB,WAAW,KAAK,aAAa;AAAA,EACvD;AAAA;AAAA,EAGA,GAA6B,MAAiB,SAAkC;AAC9E,UAAM,WAAW,KAAK,SAAS,IAAI,IAAI,KAAK,CAAC;AAC7C,SAAK,SAAS,IAAI,MAAM,CAAC,GAAG,UAAU,OAAyB,CAAC;AAAA,EAClE;AAAA;AAAA,EAGA,IAA8B,MAAiB,SAAkC;AAC/E,UAAM,WAAW,KAAK,SAAS,IAAI,IAAI,KAAK,CAAC;AAC7C,SAAK,SAAS,IAAI,MAAM,SAAS,OAAO,OAAK,MAAM,OAAO,CAAC;AAAA,EAC7D;AAAA;AAAA,EAGA,WAAW,SAAgC;AACzC,QAAI,OAAO,WAAW,eAAe,OAAO,WAAW,OAAQ;AAC/D,WAAO,OAAO,YAAY,SAAS,GAAG;AAAA,EACxC;AAAA,EAEQ,cAAc,OAA2B;AAC/C,UAAM,OAAO,MAAM;AACnB,QAAI,CAAC,MAAM,MAAM,WAAW,YAAY,EAAG;AAE3C,UAAM,WAAW,KAAK,SAAS,IAAI,KAAK,IAAI,KAAK,CAAC;AAClD,aAAS,QAAQ,aAAW,QAAQ,IAAI,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,UAAgB;AACd,WAAO,oBAAoB,WAAW,KAAK,aAAa;AACxD,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;AAMO,IAAM,gBAAN,MAAoB;AAAA,EACzB,cACE,OACA,SACM;AACN,UAAM,SAAS,MAAM,MAAM,IAAI,IAAI,MAAM,GAAG,EAAE,SAAS;AACvD,UAAM,eAAe,YAAY,EAAE,MAAM,wBAAwB,GAAG,QAAQ,GAAG,MAAM;AAAA,EACvF;AACF;;;ACxCO,IAAM,cAAc;AAEpB,IAAM,eAAN,MAAmB;AAAA,EAIxB,cAAc;AAFd,SAAQ,iBAAyD,CAAC;AAGhE,SAAK,YAAY,IAAI,UAAU;AAE/B,SAAK,UAAU,GAAqB,wBAAwB,SAAO;AACjE,YAAM,MAAwB;AAAA,QAC5B,cAAc,IAAI;AAAA,QAClB,aAAc,IAAI;AAAA,QAClB,SAAc,IAAI,YAAY;AAAA,MAChC;AACA,WAAK,eAAe,QAAQ,QAAM,GAAG,GAAG,CAAC;AAAA,IAC3C,CAAC;AAED,SAAK,UAAU,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,UAAiD;AACvD,SAAK,eAAe,KAAK,QAAQ;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,OAAqB;AAC/B,SAAK,UAAU,WAAW,EAAE,MAAM,mBAAmB,MAAM,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,EAAE,OAAO,WAAW,GAA0B;AACrD,SAAK,UAAU,WAAW;AAAA,MACxB,MAAM;AAAA,MACN;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,UAAU,QAAQ;AACvB,SAAK,iBAAiB,CAAC;AAAA,EACzB;AACF;;;AC1CO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YAAY,SAAiC,MAAc;AACzD,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}