@bluebottle_gg/league-broadcast-client 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2960,6 +2960,7 @@ declare class LeagueBroadcastClient {
2960
2960
  private champSelectData;
2961
2961
  private champSelectWasActive;
2962
2962
  private postGameData;
2963
+ private postGameSeedPromise;
2963
2964
  /** Reactive store for **in-game** state. */
2964
2965
  readonly ingameStore: GameStateStore;
2965
2966
  /** Reactive store for **pre-game** (champion select) state. */
@@ -3002,10 +3003,16 @@ declare class LeagueBroadcastClient {
3002
3003
  private _startClock;
3003
3004
  private _stopClock;
3004
3005
  /**
3005
- * Connect to both in-game and pre-game WebSocket endpoints.
3006
+ * Connect to the in-game, pre-game, and (unless disabled) post-game
3007
+ * WebSocket endpoints.
3006
3008
  *
3007
- * Both connections are attempted in parallel. If either fails the returned
3008
- * promise rejects, but the other connection may still succeed.
3009
+ * All connections are attempted in parallel. If any fails the returned
3010
+ * promise rejects, but the other connections may still succeed.
3011
+ *
3012
+ * On a successful post-game connection the current post-game state
3013
+ * (`isMocking`, `activeComponent`) is seeded from the REST API before the
3014
+ * promise resolves, so pages that connect mid-session see the live backend
3015
+ * state instead of stale defaults.
3009
3016
  */
3010
3017
  connect(): Promise<void>;
3011
3018
  /**
@@ -3164,6 +3171,16 @@ declare class LeagueBroadcastClient {
3164
3171
  private handleRouteUpdate;
3165
3172
  private endChampSelect;
3166
3173
  private setupPostGameMessageHandler;
3174
+ /**
3175
+ * Seed `isMocking` and `activeComponent` from the REST API.
3176
+ *
3177
+ * The post-game WebSocket only broadcasts changes, so a client that
3178
+ * connects while mocking is already enabled or a component is already
3179
+ * active would keep the stale defaults until the next broadcast. Runs on
3180
+ * every (re)connect; event handlers fire only for values that actually
3181
+ * changed. Never rejects — a failed request leaves that field untouched.
3182
+ */
3183
+ private seedPostGameState;
3167
3184
  private handlePostGameRouteUpdate;
3168
3185
  private handlePostGameMockingUpdate;
3169
3186
  private handleActiveComponentChanged;
package/dist/index.js CHANGED
@@ -1961,6 +1961,7 @@ var LeagueBroadcastClient = class {
1961
1961
  this.gameState = 0 /* OutOfGame */;
1962
1962
  this._isTestingEnvironment = false;
1963
1963
  this.champSelectWasActive = false;
1964
+ this.postGameSeedPromise = null;
1964
1965
  // -- In-game event handlers -------------------------------------------------
1965
1966
  this.stateUpdateHandlers = /* @__PURE__ */ new Set();
1966
1967
  this.gameStatusHandlers = /* @__PURE__ */ new Set();
@@ -2020,6 +2021,9 @@ var LeagueBroadcastClient = class {
2020
2021
  this.postGameData = new postGameStateData();
2021
2022
  this.postGameStore = new PostGameStateStore(this.postGameData);
2022
2023
  this.setupPostGameMessageHandler();
2024
+ this.postGameWs.onConnect(() => {
2025
+ this.postGameSeedPromise = this.seedPostGameState();
2026
+ });
2023
2027
  if (this.config.autoConnect) {
2024
2028
  this.connect();
2025
2029
  }
@@ -2047,10 +2051,16 @@ var LeagueBroadcastClient = class {
2047
2051
  // Connection management
2048
2052
  // ===========================================================================
2049
2053
  /**
2050
- * Connect to both in-game and pre-game WebSocket endpoints.
2054
+ * Connect to the in-game, pre-game, and (unless disabled) post-game
2055
+ * WebSocket endpoints.
2056
+ *
2057
+ * All connections are attempted in parallel. If any fails the returned
2058
+ * promise rejects, but the other connections may still succeed.
2051
2059
  *
2052
- * Both connections are attempted in parallel. If either fails the returned
2053
- * promise rejects, but the other connection may still succeed.
2060
+ * On a successful post-game connection the current post-game state
2061
+ * (`isMocking`, `activeComponent`) is seeded from the REST API before the
2062
+ * promise resolves, so pages that connect mid-session see the live backend
2063
+ * state instead of stale defaults.
2054
2064
  */
2055
2065
  async connect() {
2056
2066
  this.startOverlayHealthIfEnabled();
@@ -2078,6 +2088,9 @@ var LeagueBroadcastClient = class {
2078
2088
  );
2079
2089
  throw reasons[0];
2080
2090
  }
2091
+ if (this.postGameSeedPromise) {
2092
+ await this.postGameSeedPromise;
2093
+ }
2081
2094
  }
2082
2095
  /**
2083
2096
  * Disconnect from both WebSocket endpoints.
@@ -2086,7 +2099,10 @@ var LeagueBroadcastClient = class {
2086
2099
  this.ingameWs.disconnect();
2087
2100
  this.preGameWs.disconnect();
2088
2101
  this.postGameWs.disconnect();
2089
- this._overlayHealth?.stop();
2102
+ try {
2103
+ this._overlayHealth?.stop();
2104
+ } catch {
2105
+ }
2090
2106
  this._overlayHealth = null;
2091
2107
  }
2092
2108
  /**
@@ -2613,6 +2629,49 @@ var LeagueBroadcastClient = class {
2613
2629
  }
2614
2630
  });
2615
2631
  }
2632
+ /**
2633
+ * Seed `isMocking` and `activeComponent` from the REST API.
2634
+ *
2635
+ * The post-game WebSocket only broadcasts changes, so a client that
2636
+ * connects while mocking is already enabled or a component is already
2637
+ * active would keep the stale defaults until the next broadcast. Runs on
2638
+ * every (re)connect; event handlers fire only for values that actually
2639
+ * changed. Never rejects — a failed request leaves that field untouched.
2640
+ */
2641
+ async seedPostGameState() {
2642
+ const [mockingResult, activeComponentResult] = await Promise.allSettled([
2643
+ this.api.postGame.getMocking(),
2644
+ this.api.postGame.getActivePostGameAnalysis()
2645
+ ]);
2646
+ const nextData = { ...this.postGameData };
2647
+ if (mockingResult.status === "fulfilled") {
2648
+ nextData.isMocking = Boolean(mockingResult.value);
2649
+ }
2650
+ if (activeComponentResult.status === "fulfilled") {
2651
+ const active = activeComponentResult.value ?? null;
2652
+ if (active !== null || this.postGameData.activeComponent != null) {
2653
+ nextData.activeComponent = active;
2654
+ }
2655
+ }
2656
+ const prevData = this.postGameData;
2657
+ this.postGameData = structuralShare(prevData, nextData);
2658
+ if (this.postGameData === prevData) return;
2659
+ this.postGameStore._setPostGameData(this.postGameData);
2660
+ this.postGameUpdateHandlers.forEach(
2661
+ (handler) => handler(this.postGameData)
2662
+ );
2663
+ if (this.postGameData.isMocking !== prevData.isMocking) {
2664
+ this.postGameEventHandlers.onMockingUpdate.forEach(
2665
+ (h) => h(this.postGameData.isMocking)
2666
+ );
2667
+ }
2668
+ const activeComponent = this.postGameData.activeComponent;
2669
+ if (activeComponent != null && activeComponent !== prevData.activeComponent) {
2670
+ this.postGameEventHandlers.onActiveComponentChanged.forEach(
2671
+ (h) => h(activeComponent)
2672
+ );
2673
+ }
2674
+ }
2616
2675
  handlePostGameRouteUpdate(uri) {
2617
2676
  if (typeof uri !== "string" || uri.length === 0) return;
2618
2677
  this.postGameEventHandlers.onRouteUpdate.forEach((h) => h(uri));