{
  "version": 3,
  "sources": ["../src/index.ts"],
  "sourcesContent": [
    "declare global {\n  interface Window {\n    FarcadeSDK: typeof sdk\n  }\n}\n\nexport type ViewContext = 'feed' | 'full_screen' | 'challenge' | 'tournament'\n\nexport type GameState = Record<string, unknown>\n\nexport type Player = {\n  id: string\n  name: string\n  purchasedItems: string[]\n  imageUrl?: string\n}\n\nexport type GameInfo = {\n  players: Player[]\n  player: Player\n  viewContext: ViewContext\n  initialGameState: {\n    id: string\n    gameState: GameState\n  } | null\n}\n\nexport type ReadyEvent = {\n  type: 'ready'\n  data: undefined\n}\n\nexport type PlayAgainEvent = {\n  type: 'play_again'\n  data: undefined\n}\n\nexport type SinglePlayerGameOverEvent = {\n  type: 'game_over'\n  data: {\n    score: number\n  }\n}\n\nexport type MultiplayerGameOverEvent = {\n  type: 'multiplayer_game_over'\n  data: {\n    scores: {\n      playerId: string\n      score: number\n    }[]\n  }\n}\n\nexport type HapticFeedbackEvent = {\n  type: 'haptic_feedback'\n  data: undefined\n}\n\nexport type ToggleMuteEvent = {\n  type: 'toggle_mute'\n  data: {\n    isMuted: boolean\n  }\n}\n\nexport type GameErrorEvent = {\n  type: 'error'\n  data: {\n    message: string\n    source?: string\n    lineno?: number\n    colno?: number\n    error?: Error\n  }\n}\n\nexport type GameInfoEvent = {\n  type: 'game_info'\n  data: GameInfo\n}\n\nexport type MultiplayerSaveGameStateEvent = {\n  type: 'multiplayer_save_game_state'\n  data: {\n    gameState: GameState\n    alertUserIds?: string[]\n  }\n}\n\nexport type GameStateUpdatedEvent = {\n  type: 'game_state_updated'\n  data: {\n    id: string\n    gameState: GameState\n  } | null\n}\n\nexport type RefuteGameStateEvent = {\n  type: 'refute_game_state'\n  data: {\n    gameStateId: string\n  }\n}\n\nexport type SaveGameStateEvent = {\n  type: 'save_game_state'\n  data: {\n    gameState: GameState\n  }\n}\n\nexport type PurchaseEvent = {\n  type: 'purchase'\n  data: {\n    item: string\n  }\n}\n\nexport type PurchaseCompleteEvent = {\n  type: 'purchase_complete'\n  data: {\n    success: boolean\n  }\n}\n\nexport type GameEvent =\n  | PlayAgainEvent\n  | SinglePlayerGameOverEvent\n  | ReadyEvent\n  | HapticFeedbackEvent\n  | ToggleMuteEvent\n  | GameErrorEvent\n  | SaveGameStateEvent\n  | RefuteGameStateEvent\n  | GameInfoEvent\n  | GameStateUpdatedEvent\n  | MultiplayerGameOverEvent\n  | MultiplayerSaveGameStateEvent\n  | PurchaseEvent\n  | PurchaseCompleteEvent\n\nexport type GameEventMessage<T extends GameEvent['type']> = {\n  type: 'game_event'\n  event: Extract<GameEvent, { type: T }>\n}\n\n/**\n * Messages from the game host to the game client\n */\nexport type IncomingGameEvent = GameEventMessage<\n  'play_again' | 'toggle_mute' | 'game_info' | 'game_state_updated' | 'purchase_complete'\n>\n\nexport type OutgoingGameEvent = GameEventMessage<\n  | 'game_over'\n  | 'ready'\n  | 'haptic_feedback'\n  | 'error'\n  | 'save_game_state'\n  | 'refute_game_state'\n  | 'multiplayer_game_over'\n  | 'multiplayer_save_game_state'\n  | 'purchase'\n>\n\ntype EventCallback = (data: unknown) => void\n\nexport class FarcadeSDK {\n  private isClient: boolean\n  private target: Window | null = null\n  private eventListeners: Map<string, Set<EventCallback>> = new Map()\n  private readyPromiseResolve: ((gameInfo: GameInfo) => void) | null = null\n  private purchasePromiseResolve: ((data: PurchaseCompleteEvent['data']) => void) | null = null\n  private _gameInfo?: GameInfo\n  private _gameState?: GameState | null\n\n  constructor() {\n    this.isClient = typeof window !== 'undefined'\n    this.target = this.isClient ? window.parent : null\n\n    if (this.isClient) {\n      window.addEventListener('message', this.handleMessage)\n\n      // Set up global error handler\n      window.addEventListener('error', this.handleGlobalError)\n      window.addEventListener('unhandledrejection', this.handleUnhandledRejection)\n\n      // send the ready message to the game host\n      this.sendMessage('ready', undefined)\n    }\n  }\n\n  on(eventType: IncomingGameEvent['event']['type'], callback: EventCallback) {\n    if (!this.eventListeners.has(eventType)) {\n      this.eventListeners.set(eventType, new Set())\n    }\n    this.eventListeners.get(eventType)?.add(callback)\n  }\n\n  off(eventType: IncomingGameEvent['event']['type'], callback: EventCallback) {\n    this.eventListeners.get(eventType)?.delete(callback)\n  }\n\n  // explicitly named event listeners for better understanding and type safety\n  onPlayAgain(callback: () => void) {\n    this.on('play_again', () => callback())\n  }\n\n  onToggleMute(callback: (data: ToggleMuteEvent['data']) => void) {\n    this.on('toggle_mute', (data) => callback(data as ToggleMuteEvent['data']))\n  }\n\n  onGameStateUpdated(callback: (data: GameStateUpdatedEvent['data']) => void) {\n    this.on('game_state_updated', (data) => callback(data as GameStateUpdatedEvent['data']))\n  }\n\n  onGameInfo(callback: (data: GameInfoEvent['data']) => void) {\n    this.on('game_info', (data) => callback(data as GameInfoEvent['data']))\n  }\n\n  onPurchaseComplete(callback: (data: PurchaseCompleteEvent['data']) => void) {\n    this.on('purchase_complete', (data) => callback(data as PurchaseCompleteEvent['data']))\n  }\n  // end of explicitly named event listeners\n\n  setTarget(target: Window) {\n    this.target = target\n  }\n\n  get purchasedItems(): string[] {\n    return this._gameInfo?.player.purchasedItems || []\n  }\n\n  get gameInfo(): GameInfo | undefined {\n    return this._gameInfo\n  }\n\n  get gameState(): GameState | null | undefined {\n    return this._gameState\n  }\n\n  get players(): Player[] | undefined {\n    return this._gameInfo?.players\n  }\n\n  get player(): Player | undefined {\n    return this._gameInfo?.player\n  }\n\n  get isReady(): boolean {\n    return !!this._gameInfo\n  }\n\n  ready = (): Promise<GameInfo> => {\n    // if the game info is already set, return it immediately\n    if (this._gameInfo) {\n      return Promise.resolve(this._gameInfo)\n    }\n\n    // internal promise allows Remix to return GameInfo as a response to the ready message\n    return new Promise((resolve) => {\n      this.readyPromiseResolve = resolve\n    })\n  }\n\n  purchase = (data: PurchaseEvent['data']): Promise<PurchaseCompleteEvent['data']> => {\n    this.sendMessage('purchase', data)\n\n    // internal promise allows Remix to return PurchaseCompleteEvent data as a response to the purchase message\n    return new Promise((resolve) => {\n      this.purchasePromiseResolve = resolve\n    })\n  }\n\n  reportError = (data: GameErrorEvent['data']) => {\n    this.sendMessage('error', data)\n  }\n\n  hapticFeedback = () => {\n    this.sendMessage('haptic_feedback', undefined)\n  }\n\n  hasItem = (item: string): boolean => {\n    return this._gameInfo?.player.purchasedItems.includes(item) || false\n  }\n\n  singlePlayer = {\n    actions: {\n      ready: this.ready,\n      hapticFeedback: this.hapticFeedback,\n      reportError: this.reportError,\n      purchase: this.purchase,\n      gameOver: (data: SinglePlayerGameOverEvent['data']) => {\n        this.sendMessage('game_over', data)\n      },\n      saveGameState: (data: SaveGameStateEvent['data']) => {\n        this.sendMessage('save_game_state', data)\n      },\n    },\n  }\n\n  multiplayer = {\n    actions: {\n      ...this.singlePlayer.actions,\n      gameOver: (data: MultiplayerGameOverEvent['data']) => {\n        this.sendMessage('multiplayer_game_over', data)\n      },\n      refuteGameState: (data: RefuteGameStateEvent['data']) => {\n        this.sendMessage('refute_game_state', data)\n      },\n      saveGameState: (data: MultiplayerSaveGameStateEvent['data']) => {\n        this.sendMessage('multiplayer_save_game_state', data)\n      },\n    },\n  }\n\n  private emit(eventType: IncomingGameEvent['event']['type'], data: unknown) {\n    // Handle game_info specially to resolve the ready promise\n    if (eventType === 'game_info') {\n      const eventData = data as GameInfoEvent['data']\n      this._gameInfo = eventData\n\n      // Set the game state if it exists and is not already set\n      if (!this._gameState && eventData.initialGameState) {\n        this._gameState = eventData.initialGameState.gameState\n      }\n\n      if (this.readyPromiseResolve) {\n        this.readyPromiseResolve(this._gameInfo)\n        this.readyPromiseResolve = null\n      }\n    }\n\n    // Handle purchase_complete specially to resolve the purchase promise\n    if (eventType === 'purchase_complete' && this.purchasePromiseResolve) {\n      this.purchasePromiseResolve(data as PurchaseCompleteEvent['data'])\n      this.purchasePromiseResolve = null\n    }\n\n    if (eventType === 'game_state_updated') {\n      const eventData = data as GameStateUpdatedEvent['data']\n      if (eventData) {\n        this._gameState = eventData.gameState\n      } else {\n        this._gameState = null\n      }\n    }\n\n    for (const callback of this.eventListeners.get(eventType) || []) {\n      callback(data)\n    }\n  }\n\n  private handleMessage = (event: MessageEvent<IncomingGameEvent>) => {\n    if (event.data?.type !== 'game_event') return\n\n    this.emit(event.data.event.type, event.data.event.data)\n  }\n\n  private sendMessage = <T extends GameEvent['type']>(\n    type: T,\n    data: Extract<GameEvent, { type: T }>['data'],\n  ) => {\n    if (!this.isClient || !this.target) return\n    const gameEvent = { type: 'game_event', event: { type, data } } as GameEventMessage<T>\n    this.target.postMessage(gameEvent, '*')\n  }\n\n  private handleGlobalError = (event: globalThis.ErrorEvent) => {\n    // Send both formats for backward compatibility\n    this.sendMessage('error', {\n      message: event.message || 'Unknown error',\n      source: event.filename,\n      lineno: event.lineno,\n      colno: event.colno,\n      error: event.error,\n    })\n  }\n\n  private handleUnhandledRejection = (event: PromiseRejectionEvent) => {\n    const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason))\n\n    // Send both formats for backward compatibility\n    this.sendMessage('error', {\n      message: error.message,\n      error,\n    })\n  }\n}\n\n// Initialize and add to window\nexport const sdk = new FarcadeSDK()\n\n// Add SDK to window object for easier access in HTML games\nif (typeof window !== 'undefined') {\n  window.FarcadeSDK = sdk\n}\n"
  ],
  "mappings": "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",
  "debugId": "6B911B8154165F1364756E2164756E21",
  "names": []
}