@bluebottle_gg/league-broadcast-client 0.1.0 → 0.2.0

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.js CHANGED
@@ -326,6 +326,134 @@ function shallowEqual(a, b) {
326
326
  return true;
327
327
  }
328
328
 
329
+ // src/reactivity/ChampSelectStateStore.ts
330
+ var ChampSelectStateStore = class {
331
+ constructor(initialState) {
332
+ /** Global listeners — called on every state change regardless of selector. */
333
+ this.listeners = /* @__PURE__ */ new Set();
334
+ /** Monotonically increasing version — used for cheap stale checks. */
335
+ this.version = 0;
336
+ this.snapshot = Object.freeze({
337
+ champSelectData: initialState,
338
+ isActive: initialState.isActive,
339
+ version: this.version
340
+ });
341
+ }
342
+ // ---------------------------------------------------------------------------
343
+ // Core API
344
+ // ---------------------------------------------------------------------------
345
+ /** Return the current full snapshot. */
346
+ getSnapshot() {
347
+ return this.snapshot;
348
+ }
349
+ /** Return the current version number. */
350
+ getVersion() {
351
+ return this.version;
352
+ }
353
+ /**
354
+ * Subscribe to **all** state changes (unfiltered).
355
+ * Returns an unsubscribe function.
356
+ */
357
+ subscribe(listener) {
358
+ this.listeners.add(listener);
359
+ return () => {
360
+ this.listeners.delete(listener);
361
+ };
362
+ }
363
+ // ---------------------------------------------------------------------------
364
+ // Selectors
365
+ // ---------------------------------------------------------------------------
366
+ /**
367
+ * Create a **subscribable slice** that only triggers when the selected
368
+ * value changes according to `equalityFn` (defaults to `===`).
369
+ */
370
+ select(selector, equalityFn = Object.is) {
371
+ let currentValue = selector(this.snapshot);
372
+ let lastVersion = this.version;
373
+ const sliceListeners = /* @__PURE__ */ new Set();
374
+ const getSnapshot = () => {
375
+ if (lastVersion !== this.version) {
376
+ const next = selector(this.snapshot);
377
+ if (!equalityFn(currentValue, next)) {
378
+ currentValue = next;
379
+ }
380
+ lastVersion = this.version;
381
+ }
382
+ return currentValue;
383
+ };
384
+ const subscribe = (listener) => {
385
+ sliceListeners.add(listener);
386
+ const unsub = this.subscribe(() => {
387
+ const prev = currentValue;
388
+ const next = selector(this.snapshot);
389
+ lastVersion = this.version;
390
+ if (!equalityFn(prev, next)) {
391
+ currentValue = next;
392
+ listener();
393
+ }
394
+ });
395
+ return () => {
396
+ sliceListeners.delete(listener);
397
+ unsub();
398
+ };
399
+ };
400
+ return { subscribe, getSnapshot };
401
+ }
402
+ // ---------------------------------------------------------------------------
403
+ // Convenience helpers
404
+ // ---------------------------------------------------------------------------
405
+ /**
406
+ * Watch a derived value and invoke `callback` whenever it changes.
407
+ * Returns an unsubscribe function.
408
+ */
409
+ watch(selector, callback, equalityFn = Object.is) {
410
+ let prev = selector(this.snapshot);
411
+ return this.subscribe(() => {
412
+ const next = selector(this.snapshot);
413
+ if (!equalityFn(prev, next)) {
414
+ const old = prev;
415
+ prev = next;
416
+ callback(next, old);
417
+ }
418
+ });
419
+ }
420
+ /**
421
+ * Watch a derived value and invoke `callback` whenever it changes,
422
+ * **and** invoke it immediately with the current value.
423
+ */
424
+ watchImmediate(selector, callback, equalityFn = Object.is) {
425
+ const current = selector(this.snapshot);
426
+ callback(current, void 0);
427
+ return this.watch(selector, callback, equalityFn);
428
+ }
429
+ // ---------------------------------------------------------------------------
430
+ // Internal — called by LeagueBroadcastClient
431
+ // ---------------------------------------------------------------------------
432
+ /** @internal Replace champ-select data snapshot and notify listeners. */
433
+ _setChampSelectData(data) {
434
+ this.version++;
435
+ this.snapshot = Object.freeze({
436
+ champSelectData: data,
437
+ isActive: data.isActive,
438
+ version: this.version
439
+ });
440
+ this.emit();
441
+ }
442
+ /** @internal Replace entire snapshot (used on champ select end / reset). */
443
+ _reset(data) {
444
+ this.version++;
445
+ this.snapshot = Object.freeze({
446
+ champSelectData: data,
447
+ isActive: data.isActive,
448
+ version: this.version
449
+ });
450
+ this.emit();
451
+ }
452
+ emit() {
453
+ this.listeners.forEach((l) => l());
454
+ }
455
+ };
456
+
329
457
  // src/reactivity/structuralShare.ts
330
458
  function structuralShare(prev, next) {
331
459
  if (Object.is(prev, next)) {
@@ -358,6 +486,14 @@ function structuralShare(prev, next) {
358
486
  const nextKeys = Object.keys(nextObj);
359
487
  const prevKeys = Object.keys(prevObj);
360
488
  let changed = nextKeys.length !== prevKeys.length;
489
+ if (!changed) {
490
+ for (const key of prevKeys) {
491
+ if (!Object.prototype.hasOwnProperty.call(nextObj, key)) {
492
+ changed = true;
493
+ break;
494
+ }
495
+ }
496
+ }
361
497
  const result = Object.create(
362
498
  Object.getPrototypeOf(next)
363
499
  );
@@ -398,156 +534,829 @@ var ingameFrontendData = class {
398
534
  }
399
535
  };
400
536
 
537
+ // types/pregame/champselectstatedata.ts
538
+ var champSelectStateData = class {
539
+ constructor() {
540
+ this.isActive = false;
541
+ this.isConnected = false;
542
+ this.isTestingEnvironment = false;
543
+ this.blueTeam = {};
544
+ this.redTeam = {};
545
+ this.metaData = {};
546
+ this.timer = {};
547
+ }
548
+ };
549
+
550
+ // src/api/ApiClient.ts
551
+ var ApiClient = class {
552
+ constructor(baseUrl) {
553
+ this.baseUrl = baseUrl;
554
+ }
555
+ /** Update the base URL (e.g. after reconnecting to a different host/port). */
556
+ updateBaseUrl(baseUrl) {
557
+ this.baseUrl = baseUrl;
558
+ }
559
+ /** Current base URL. */
560
+ getBaseUrl() {
561
+ return this.baseUrl;
562
+ }
563
+ // ── HTTP verbs ──────────────────────────────────────────────────────────
564
+ async get(path) {
565
+ return this.request("GET", path);
566
+ }
567
+ async post(path, body) {
568
+ return this.request("POST", path, body);
569
+ }
570
+ async put(path, body) {
571
+ return this.request("PUT", path, body);
572
+ }
573
+ async patch(path, body) {
574
+ return this.request("PATCH", path, body);
575
+ }
576
+ async delete(path) {
577
+ return this.request("DELETE", path);
578
+ }
579
+ /**
580
+ * POST with a raw string body (e.g. base64 image data).
581
+ * Sets Content-Type to text/plain instead of application/json.
582
+ */
583
+ async postRaw(path, rawBody) {
584
+ return this.request("POST", path, rawBody, "text/plain");
585
+ }
586
+ /**
587
+ * PUT with a raw string body (e.g. base64 image data).
588
+ * Sets Content-Type to text/plain instead of application/json.
589
+ */
590
+ async putRaw(path, rawBody) {
591
+ return this.request("PUT", path, rawBody, "text/plain");
592
+ }
593
+ // ── Internal ────────────────────────────────────────────────────────────
594
+ buildUrl(path) {
595
+ const base = this.baseUrl.endsWith("/") ? this.baseUrl.slice(0, -1) : this.baseUrl;
596
+ const cleanPath = path.startsWith("/") ? path.slice(1) : path;
597
+ return `${base}/${cleanPath}`;
598
+ }
599
+ async request(method, path, body, contentType) {
600
+ const url = this.buildUrl(path);
601
+ const headers = {};
602
+ let bodyStr;
603
+ if (body !== void 0) {
604
+ if (contentType === "text/plain") {
605
+ headers["Content-Type"] = "text/plain";
606
+ bodyStr = String(body);
607
+ } else {
608
+ headers["Content-Type"] = "application/json";
609
+ bodyStr = JSON.stringify(body);
610
+ }
611
+ }
612
+ const res = await fetch(url, {
613
+ method,
614
+ headers,
615
+ body: bodyStr
616
+ });
617
+ if (!res.ok) {
618
+ const errorBody = await res.text().catch(() => "");
619
+ throw new ApiError(res.status, res.statusText, errorBody, url);
620
+ }
621
+ return this.parseResponse(res);
622
+ }
623
+ async parseResponse(res) {
624
+ const text = await res.text();
625
+ if (!text || text.length === 0) return void 0;
626
+ try {
627
+ return JSON.parse(text);
628
+ } catch {
629
+ return text;
630
+ }
631
+ }
632
+ };
633
+ var ApiError = class extends Error {
634
+ constructor(status, statusText, body, url) {
635
+ super(`API Error ${status} (${statusText}) at ${url}`);
636
+ this.status = status;
637
+ this.statusText = statusText;
638
+ this.body = body;
639
+ this.url = url;
640
+ this.name = "ApiError";
641
+ }
642
+ };
643
+
644
+ // src/api/generated/PreGameApi.ts
645
+ var PreGameApi = class {
646
+ constructor(client) {
647
+ this.client = client;
648
+ }
649
+ /** `POST championselect/mock/{doMocking}` */
650
+ async mockChampionSelect(doMocking, randomizationinterval) {
651
+ return this.client.post(`championselect/mock/${doMocking}${randomizationinterval !== void 0 ? `?randomizationinterval=${encodeURIComponent(String(randomizationinterval))}` : ""}`);
652
+ }
653
+ /** `GET championselect/mock` */
654
+ async getMockingStatus() {
655
+ return this.client.get("championselect/mock");
656
+ }
657
+ /** `GET championselect/bans` */
658
+ async getBans() {
659
+ return this.client.get("championselect/bans");
660
+ }
661
+ /** `GET championselect/frontend` */
662
+ async getFrontendUrl() {
663
+ return this.client.get("championselect/frontend");
664
+ }
665
+ /** `GET championselect/stage/{stageSide}/teamid` */
666
+ async getTeamIdOnSide(stageSide) {
667
+ return this.client.get(`championselect/stage/${stageSide}/teamid`);
668
+ }
669
+ /** `POST championselect/frontend` */
670
+ async changeRouting(uri) {
671
+ return this.client.post(`championselect/frontend?uri=${encodeURIComponent(String(uri))}`);
672
+ }
673
+ /** `GET championselect/stage/{stageside}/{slotid}` */
674
+ async getPlayerPUUIDInSlot(stageside, slotid) {
675
+ return this.client.get(`championselect/stage/${stageside}/${slotid}`);
676
+ }
677
+ };
678
+
679
+ // src/api/generated/GameApi.ts
680
+ var GameApi = class {
681
+ constructor(client) {
682
+ this.client = client;
683
+ }
684
+ /** `GET game/current` */
685
+ async getCurrentGame() {
686
+ return this.client.get("game/current");
687
+ }
688
+ /** `GET game/previous` */
689
+ async getPreviousGame() {
690
+ return this.client.get("game/previous");
691
+ }
692
+ /** `GET game/{gameid}` */
693
+ async getGame(gameid) {
694
+ return this.client.get(`game/${gameid}`);
695
+ }
696
+ /** `PATCH game/{gameid}` */
697
+ async updateGame(gameid, game) {
698
+ return this.client.patch(`game/${gameid}`, game);
699
+ }
700
+ /** `PUT game/{gameid}/teams` */
701
+ async setSideSelection(gameid, teams) {
702
+ return this.client.put(`game/${gameid}/teams`, teams);
703
+ }
704
+ /** `GET game/{gameid}/teams` */
705
+ async getTeamsInGame(gameid) {
706
+ return this.client.get(`game/${gameid}/teams`);
707
+ }
708
+ /** `DELETE game/{gameid}/winner` */
709
+ async removeGameWinner(gameid) {
710
+ return this.client.delete(`game/${gameid}/winner`);
711
+ }
712
+ /** `PUT game/{gameid}/winner/{teamid}` */
713
+ async setGameWinner(gameid, teamid) {
714
+ return this.client.put(`game/${gameid}/winner/${teamid}`);
715
+ }
716
+ /** `GET game/{gameid}/bans` */
717
+ async getBans(gameid) {
718
+ return this.client.get(`game/${gameid}/bans`);
719
+ }
720
+ /** `GET game/{gameid}/bans/{teamid}` */
721
+ async getBansForTeam(gameid, teamid) {
722
+ return this.client.get(`game/${gameid}/bans/${teamid}`);
723
+ }
724
+ /** `PUT game/{gameid}/bans` */
725
+ async setBans(gameid, bans) {
726
+ return this.client.put(`game/${gameid}/bans`, bans);
727
+ }
728
+ /** `PUT game/{gameid}/bans/{teamid}` */
729
+ async setBansForTeam(gameid, teamid, bans) {
730
+ return this.client.put(`game/${gameid}/bans/${teamid}`, bans);
731
+ }
732
+ /** `GET game/{gameid}/picks` */
733
+ async getPicks(gameid) {
734
+ return this.client.get(`game/${gameid}/picks`);
735
+ }
736
+ /** `GET game/{gameid}/picks/{teamid}` */
737
+ async getPicksForTeam(gameid, teamid) {
738
+ return this.client.get(`game/${gameid}/picks/${teamid}`);
739
+ }
740
+ /** `PUT game/{gameid}/picks` */
741
+ async setPicks(gameid, picks) {
742
+ return this.client.put(`game/${gameid}/picks`, picks);
743
+ }
744
+ /** `PUT game/{gameid}/picks/{teamid}` */
745
+ async setPicksForTeam(gameid, teamid, picks) {
746
+ return this.client.put(`game/${gameid}/picks/${teamid}`, picks);
747
+ }
748
+ };
749
+
750
+ // src/api/generated/GameStateApi.ts
751
+ var GameStateApi = class {
752
+ constructor(client) {
753
+ this.client = client;
754
+ }
755
+ /** `GET game/state/time` */
756
+ async getGameTime() {
757
+ return this.client.get("game/state/time");
758
+ }
759
+ /** `GET game/state/team/{teamId}/dragons` */
760
+ async getTeamDragons(teamId) {
761
+ return this.client.get(`game/state/team/${teamId}/dragons`);
762
+ }
763
+ /** `PATCH game/state/team/{teamId}/dragons` */
764
+ async updateTeamDragons(teamId, dragons) {
765
+ return this.client.patch(`game/state/team/${teamId}/dragons`, dragons);
766
+ }
767
+ /** `GET game/state/team/all/index` */
768
+ async getActiveTeams() {
769
+ return this.client.get("game/state/team/all/index");
770
+ }
771
+ /** `GET game/state/team/all/participant` */
772
+ async getAllTeamParticipants() {
773
+ return this.client.get("game/state/team/all/participant");
774
+ }
775
+ /** `GET game/state/team/{teamId}/participant` */
776
+ async getTeamParticipants(teamId) {
777
+ return this.client.get(`game/state/team/${teamId}/participant`);
778
+ }
779
+ /** `GET game/state/team/all/participant/order` */
780
+ async getTeamParticipantOrder() {
781
+ return this.client.get("game/state/team/all/participant/order");
782
+ }
783
+ /** `PUT game/state/team/all/participant/order` */
784
+ async updateTeamParticipantOrder(orderedNames) {
785
+ return this.client.put("game/state/team/all/participant/order", orderedNames);
786
+ }
787
+ };
788
+
789
+ // src/api/generated/MatchApi.ts
790
+ var MatchApi = class {
791
+ constructor(client) {
792
+ this.client = client;
793
+ }
794
+ /** `GET match/season/{seasonId}/simple` */
795
+ async getSimpleMatches(seasonId) {
796
+ return this.client.get(`match/season/${seasonId}/simple`);
797
+ }
798
+ /** `GET match/season/{seasonId}` */
799
+ async getMatches(seasonId) {
800
+ return this.client.get(`match/season/${seasonId}`);
801
+ }
802
+ /** `GET match/simple` */
803
+ async getAllSimpleMatches() {
804
+ return this.client.get("match/simple");
805
+ }
806
+ /** `GET match` */
807
+ async getAllMatches() {
808
+ return this.client.get("match");
809
+ }
810
+ /** `GET match/current` */
811
+ async getCurrentMatch() {
812
+ return this.client.get("match/current");
813
+ }
814
+ /** `POST match/current` */
815
+ async completeCurrentMatch() {
816
+ return this.client.post("match/current");
817
+ }
818
+ /** `GET match/current/id` */
819
+ async getCurrentMatchId() {
820
+ return this.client.get("match/current/id");
821
+ }
822
+ /** `GET match/previous/id` */
823
+ async getPreviousMatchId() {
824
+ return this.client.get("match/previous/id");
825
+ }
826
+ /** `POST match/current/{seriesid}` */
827
+ async setCurrentMatch(seriesid) {
828
+ return this.client.post(`match/current/${seriesid}`);
829
+ }
830
+ /** `GET match/current/bestof` */
831
+ async getCurrentMatchBestOf() {
832
+ return this.client.get("match/current/bestof");
833
+ }
834
+ /** `PUT match/current/bestof` */
835
+ async setCurrentMatchBestOf(type) {
836
+ return this.client.put("match/current/bestof", type);
837
+ }
838
+ /** `GET match/current/teams` */
839
+ async getCurrentMatchTeams() {
840
+ return this.client.get("match/current/teams");
841
+ }
842
+ /** `PUT match/current/teams` */
843
+ async setCurrentMatchTeams(teamIds) {
844
+ return this.client.put("match/current/teams", teamIds);
845
+ }
846
+ /** `GET match/current/game` */
847
+ async getCurrentGame() {
848
+ return this.client.get("match/current/game");
849
+ }
850
+ /** `GET match/current/ruleset` */
851
+ async getCurrentMatchRuleset() {
852
+ return this.client.get("match/current/ruleset");
853
+ }
854
+ /** `PUT match/current/ruleset/{ruleset}` */
855
+ async setCurrentMatchRuleset(ruleset) {
856
+ return this.client.put(`match/current/ruleset/${ruleset}`);
857
+ }
858
+ /** `GET match/current/fearless/bans` */
859
+ async getBans() {
860
+ return this.client.get("match/current/fearless/bans");
861
+ }
862
+ /** `GET match/current/onstage` */
863
+ async getCurrentMatchOnStage() {
864
+ return this.client.get("match/current/onstage");
865
+ }
866
+ /** `GET match/{matchid}` */
867
+ async getMatch(matchid) {
868
+ return this.client.get(`match/${matchid}`);
869
+ }
870
+ /** `DELETE match/{matchid}` */
871
+ async deleteMatch(matchid) {
872
+ return this.client.delete(`match/${matchid}`);
873
+ }
874
+ /** `GET match/{matchid}/teams` */
875
+ async getMatchTeams(matchid) {
876
+ return this.client.get(`match/${matchid}/teams`);
877
+ }
878
+ /** `PUT match/{matchid}/teams` */
879
+ async setMatchTeams(matchid, teamIds) {
880
+ return this.client.put(`match/${matchid}/teams`, teamIds);
881
+ }
882
+ /** `GET match/{matchid}/games` */
883
+ async getMatchGames(matchid) {
884
+ return this.client.get(`match/${matchid}/games`);
885
+ }
886
+ /** `GET match/{matchid}/winner` */
887
+ async getMatchWinner(matchid) {
888
+ return this.client.get(`match/${matchid}/winner`);
889
+ }
890
+ /** `PUT match/{matchid}/winner/{teamid}` */
891
+ async setMatchWinner(matchid, teamid) {
892
+ return this.client.put(`match/${matchid}/winner/${teamid}`);
893
+ }
894
+ /** `DELETE match/{matchid}/winner` */
895
+ async removeMatchWinner(matchid) {
896
+ return this.client.delete(`match/${matchid}/winner`);
897
+ }
898
+ /** `GET match/{matchid}/bestof` */
899
+ async getMatchBestOf(matchid) {
900
+ return this.client.get(`match/${matchid}/bestof`);
901
+ }
902
+ /** `PUT match/{matchid}/bestof/{type}` */
903
+ async setMatchBestOf(matchid, type) {
904
+ return this.client.put(`match/${matchid}/bestof/${type}`);
905
+ }
906
+ /** `GET match/{matchid}/ruleset` */
907
+ async getMatchRuleset(matchid) {
908
+ return this.client.get(`match/${matchid}/ruleset`);
909
+ }
910
+ /** `PUT match/{matchid}/ruleset/{ruleset}` */
911
+ async setMatchRuleset(matchid, ruleset) {
912
+ return this.client.put(`match/${matchid}/ruleset/${ruleset}`);
913
+ }
914
+ /** `GET match/{matchid}/name` */
915
+ async getMatchName(matchid) {
916
+ return this.client.get(`match/${matchid}/name`);
917
+ }
918
+ /** `PATCH match/{matchid}/name/{matchName}` */
919
+ async setMatchName(matchid, matchName) {
920
+ return this.client.patch(`match/${matchid}/name/${matchName}`);
921
+ }
922
+ /** `PATCH match/{matchid}` */
923
+ async updateMatch(matchid, matchUpdate) {
924
+ return this.client.patch(`match/${matchid}`, matchUpdate);
925
+ }
926
+ /** `GET match/{matchid}/fearless/bans` */
927
+ async getMatchBans(matchid) {
928
+ return this.client.get(`match/${matchid}/fearless/bans`);
929
+ }
930
+ /** `GET match/{seriesid}/onstage` */
931
+ async getMatchOnStage(seriesid) {
932
+ return this.client.get(`match/${seriesid}/onstage`);
933
+ }
934
+ /** `PUT match` */
935
+ async addMatch(match) {
936
+ return this.client.put("match", match);
937
+ }
938
+ /** `GET match/{matchId}/stage/team/{stageSide}` */
939
+ async getTeamOnStageSide(matchId, stageSide) {
940
+ return this.client.get(`match/${matchId}/stage/team/${stageSide}`);
941
+ }
942
+ /** `GET match/current/stage/team/{stageSide}` */
943
+ async getTeamOnStageSideCurrent(stageSide) {
944
+ return this.client.get(`match/current/stage/team/${stageSide}`);
945
+ }
946
+ };
947
+
948
+ // src/api/generated/SeasonApi.ts
949
+ var SeasonApi = class {
950
+ constructor(client) {
951
+ this.client = client;
952
+ }
953
+ /** `GET season/current` */
954
+ async getCurrentSeason() {
955
+ return this.client.get("season/current");
956
+ }
957
+ /** `GET season/current/match` */
958
+ async getCurrentSeasonScheduledMatch() {
959
+ return this.client.get("season/current/match");
960
+ }
961
+ /** `GET season/current/id` */
962
+ async getCurrentSeasonId() {
963
+ return this.client.get("season/current/id");
964
+ }
965
+ /** `POST season/current` */
966
+ async setCurrentSeason(newCurrentSeasonId) {
967
+ return this.client.post("season/current", newCurrentSeasonId);
968
+ }
969
+ /** `GET season/current/teams` */
970
+ async getCurrentSeasonTeams() {
971
+ return this.client.get("season/current/teams");
972
+ }
973
+ /** `GET season/current/teamswithmembers` */
974
+ async getCurrentSeasonTeamsWithMembers() {
975
+ return this.client.get("season/current/teamswithmembers");
976
+ }
977
+ /** `GET season/current/icon` */
978
+ async getCurrentSeasonIcon() {
979
+ return this.client.get("season/current/icon");
980
+ }
981
+ /** `PUT season/current/icon` */
982
+ async setCurrentSeasonIcon() {
983
+ return this.client.put("season/current/icon");
984
+ }
985
+ /** `GET season` */
986
+ async getAllSeasons() {
987
+ return this.client.get("season");
988
+ }
989
+ /** `GET season/{seasonId}` */
990
+ async getSeasonById(seasonId) {
991
+ return this.client.get(`season/${seasonId}`);
992
+ }
993
+ /** `GET season/{seasonId}/matches` */
994
+ async getMatchesInSeason(seasonId) {
995
+ return this.client.get(`season/${seasonId}/matches`);
996
+ }
997
+ /** `GET season/{seasonId}/matches/count` */
998
+ async getMatchesInSeasonCount(seasonId) {
999
+ return this.client.get(`season/${seasonId}/matches/count`);
1000
+ }
1001
+ /** `GET season/{seasonId}/matches/day/{day}` */
1002
+ async getMatchesInSeasonOnDay(seasonId, day) {
1003
+ return this.client.get(`season/${seasonId}/matches/day/${day}`);
1004
+ }
1005
+ /** `GET season/{seasonId}/teams` */
1006
+ async getTeamsInSeason(seasonId) {
1007
+ return this.client.get(`season/${seasonId}/teams`);
1008
+ }
1009
+ /** `GET season/{seasonId}/teamswithmembers` */
1010
+ async getTeamsWithMembersInSeason(seasonId) {
1011
+ return this.client.get(`season/${seasonId}/teamswithmembers`);
1012
+ }
1013
+ /** `POST season` */
1014
+ async createOrUpdateSeason(seasonData) {
1015
+ return this.client.post("season", seasonData);
1016
+ }
1017
+ /** `GET season/{seasonId}/icon` */
1018
+ async getSeasonIcon(seasonId) {
1019
+ return this.client.get(`season/${seasonId}/icon`);
1020
+ }
1021
+ /** `PUT season/{seasonId}/icon` */
1022
+ async setSeasonIcon(seasonId) {
1023
+ return this.client.put(`season/${seasonId}/icon`);
1024
+ }
1025
+ /** `DELETE season/{seasonId}` */
1026
+ async deleteSeason(seasonId) {
1027
+ return this.client.delete(`season/${seasonId}`);
1028
+ }
1029
+ };
1030
+
1031
+ // src/api/generated/IngameApi.ts
1032
+ var IngameApi = class {
1033
+ constructor(client) {
1034
+ this.client = client;
1035
+ }
1036
+ /** `GET ingame/status` */
1037
+ async getGameState() {
1038
+ return this.client.get("ingame/status");
1039
+ }
1040
+ /** `POST ingame/enable` */
1041
+ async enableComponent() {
1042
+ return this.client.post("ingame/enable");
1043
+ }
1044
+ /** `POST ingame/disable` */
1045
+ async disableComponent() {
1046
+ return this.client.post("ingame/disable");
1047
+ }
1048
+ /** `POST ingame/mock/{doMocking}` */
1049
+ async mockIngame(doMocking) {
1050
+ return this.client.post(`ingame/mock/${doMocking}`);
1051
+ }
1052
+ /** `GET ingame/mock` */
1053
+ async getMockingStatus() {
1054
+ return this.client.get("ingame/mock");
1055
+ }
1056
+ /** `GET ingame/frontend` */
1057
+ async getFrontendUrl() {
1058
+ return this.client.get("ingame/frontend");
1059
+ }
1060
+ /** `GET ingame/showing` */
1061
+ async getCurrentCommonSerializationOptions() {
1062
+ return this.client.get("ingame/showing");
1063
+ }
1064
+ /** `POST ingame/showing` */
1065
+ async setCurrentCommonSerializationOptions(data) {
1066
+ return this.client.post("ingame/showing", data);
1067
+ }
1068
+ /** `GET ingame/showing/{socketid}` */
1069
+ async getCurrentFrontendSerializationOptions(socketid) {
1070
+ return this.client.get(`ingame/showing/${socketid}`);
1071
+ }
1072
+ /** `POST ingame/showing/{socketid}` */
1073
+ async setCurrentFrontendSerializationOptions(socketid, data) {
1074
+ return this.client.post(`ingame/showing/${socketid}`, data);
1075
+ }
1076
+ /** `GET ingame/stage/{stageSide}/{playerSlot}/networkId` */
1077
+ async getPlayerPUUIDInSlot(stageSide, playerSlot) {
1078
+ return this.client.get(`ingame/stage/${stageSide}/${playerSlot}/networkId`);
1079
+ }
1080
+ /** `GET ingame/stage/{stageSide}/ingameteamid` */
1081
+ async getIngameTeamOnStageSide(stageSide) {
1082
+ return this.client.get(`ingame/stage/${stageSide}/ingameteamid`);
1083
+ }
1084
+ /** `GET ingame/state/activeOverlays` */
1085
+ async getActiveOverlays() {
1086
+ return this.client.get("ingame/state/activeOverlays");
1087
+ }
1088
+ };
1089
+
1090
+ // src/api/RestApi.ts
1091
+ var RestApi = class {
1092
+ constructor(baseUrl) {
1093
+ this.client = new ApiClient(baseUrl);
1094
+ this.ingame = new IngameApi(this.client);
1095
+ this.game = new GameApi(this.client);
1096
+ this.match = new MatchApi(this.client);
1097
+ this.season = new SeasonApi(this.client);
1098
+ this.preGame = new PreGameApi(this.client);
1099
+ this.gameState = new GameStateApi(this.client);
1100
+ }
1101
+ /**
1102
+ * Update the base URL for all API modules (e.g. after changing host/port).
1103
+ */
1104
+ updateBaseUrl(baseUrl) {
1105
+ this.client.updateBaseUrl(baseUrl);
1106
+ }
1107
+ /**
1108
+ * Get direct access to the underlying HTTP client for custom requests.
1109
+ */
1110
+ getHttpClient() {
1111
+ return this.client;
1112
+ }
1113
+ };
1114
+
401
1115
  // src/LeagueBroadcastClient.ts
402
1116
  var LeagueBroadcastClient = class {
403
1117
  constructor(config) {
404
1118
  this.gameState = 0 /* OutOfGame */;
405
- this.isTestingEnvironment = false;
406
- // Event handlers
1119
+ this._isTestingEnvironment = false;
1120
+ this.champSelectWasActive = false;
1121
+ // -- In-game event handlers -------------------------------------------------
407
1122
  this.stateUpdateHandlers = /* @__PURE__ */ new Set();
408
1123
  this.gameStatusHandlers = /* @__PURE__ */ new Set();
409
- this.eventHandlers = {};
1124
+ this.ingameEventHandlers = {};
1125
+ // -- Pre-game event handlers ------------------------------------------------
1126
+ this.champSelectUpdateHandlers = /* @__PURE__ */ new Set();
1127
+ this.champSelectEventHandlers = {};
410
1128
  this.config = {
411
1129
  host: config.host,
412
1130
  port: config.port ?? 58869,
413
- wsRoute: config.wsRoute ?? "/ws/in",
1131
+ ingameWsRoute: config.ingameWsRoute ?? "/ws/in",
1132
+ preGameWsRoute: config.preGameWsRoute ?? "/ws/pre",
414
1133
  apiRoute: config.apiRoute ?? "/api",
415
1134
  cacheRoute: config.cacheRoute ?? "/cache",
416
1135
  useHttps: config.useHttps ?? false,
417
1136
  autoConnect: config.autoConnect ?? true
418
1137
  };
419
- this.ws = new WebSocketManager();
1138
+ const httpProtocol = this.config.useHttps ? "https" : "http";
1139
+ const apiBaseUrl = `${httpProtocol}://${this.config.host}:${this.config.port}${this.config.apiRoute}`;
1140
+ this.api = new RestApi(apiBaseUrl);
1141
+ this.ingameWs = new WebSocketManager();
420
1142
  this.gameData = new ingameFrontendData();
421
- this.store = new GameStateStore(this.gameData, this.gameState);
422
- this.setupMessageHandler();
1143
+ this.ingameStore = new GameStateStore(this.gameData, this.gameState);
1144
+ this.setupIngameMessageHandler();
1145
+ this.preGameWs = new WebSocketManager();
1146
+ this.champSelectData = new champSelectStateData();
1147
+ this.preGameStore = new ChampSelectStateStore(this.champSelectData);
1148
+ this.setupPreGameMessageHandler();
423
1149
  if (this.config.autoConnect) {
424
1150
  this.connect();
425
1151
  }
426
1152
  }
1153
+ // ===========================================================================
1154
+ // Connection management
1155
+ // ===========================================================================
427
1156
  /**
428
- * Connect to the League Broadcast backend
1157
+ * Connect to both in-game and pre-game WebSocket endpoints.
1158
+ *
1159
+ * Both connections are attempted in parallel. If either fails the returned
1160
+ * promise rejects, but the other connection may still succeed.
429
1161
  */
430
1162
  async connect() {
431
1163
  const protocol = this.config.useHttps ? "wss" : "ws";
432
- const url = `${protocol}://${this.config.host}:${this.config.port}${this.config.wsRoute}`;
433
- try {
434
- await this.ws.connect(url);
435
- } catch (error) {
436
- console.error("[LeagueBroadcastClient] Connection failed:", error);
437
- throw error;
1164
+ const base = `${protocol}://${this.config.host}:${this.config.port}`;
1165
+ const ingameUrl = `${base}${this.config.ingameWsRoute}`;
1166
+ const preGameUrl = `${base}${this.config.preGameWsRoute}`;
1167
+ const results = await Promise.allSettled([
1168
+ this.ingameWs.connect(ingameUrl),
1169
+ this.preGameWs.connect(preGameUrl)
1170
+ ]);
1171
+ const failures = results.filter((r) => r.status === "rejected");
1172
+ if (failures.length > 0) {
1173
+ const reasons = failures.map(
1174
+ (r) => r.reason
1175
+ );
1176
+ console.error(
1177
+ "[LeagueBroadcastClient] One or more connections failed:",
1178
+ reasons
1179
+ );
1180
+ throw reasons[0];
438
1181
  }
439
1182
  }
440
1183
  /**
441
- * Disconnect from the League Broadcast backend
1184
+ * Disconnect from both WebSocket endpoints.
442
1185
  */
443
1186
  disconnect() {
444
- this.ws.disconnect();
1187
+ this.ingameWs.disconnect();
1188
+ this.preGameWs.disconnect();
445
1189
  }
446
1190
  /**
447
- * Check if connected to the backend
1191
+ * Whether the in-game WebSocket is connected.
448
1192
  */
449
- isConnected() {
450
- return this.ws.isConnected();
1193
+ isIngameConnected() {
1194
+ return this.ingameWs.isConnected();
451
1195
  }
452
1196
  /**
453
- * Get the current game data
1197
+ * Whether the pre-game WebSocket is connected.
454
1198
  */
455
- getGameData() {
1199
+ isPreGameConnected() {
1200
+ return this.preGameWs.isConnected();
1201
+ }
1202
+ // ===========================================================================
1203
+ // In-game data access
1204
+ // ===========================================================================
1205
+ /** Get the current in-game data. */
1206
+ getIngameData() {
456
1207
  return this.gameData;
457
1208
  }
458
- /**
459
- * Get the current game state
460
- */
461
- getGameState() {
1209
+ /** Get the current game state. */
1210
+ getIngameState() {
462
1211
  return this.gameState;
463
1212
  }
464
- /**
465
- * Check if in testing environment
466
- */
1213
+ /** Whether the backend is in a testing / replay environment. */
467
1214
  isInTestingEnvironment() {
468
- return this.isTestingEnvironment;
1215
+ return this._isTestingEnvironment;
469
1216
  }
470
- /**
471
- * Register a handler for state updates
472
- */
473
- onStateUpdate(handler) {
1217
+ // ===========================================================================
1218
+ // Pre-game data access
1219
+ // ===========================================================================
1220
+ /** Get the current champion-select state. */
1221
+ getChampSelectData() {
1222
+ return this.champSelectData;
1223
+ }
1224
+ /** Whether champion select is currently active. */
1225
+ isChampSelectActive() {
1226
+ return this.champSelectData.isActive;
1227
+ }
1228
+ // ===========================================================================
1229
+ // In-game event handlers
1230
+ // ===========================================================================
1231
+ /** Register a handler for in-game state updates. */
1232
+ onIngameStateUpdate(handler) {
474
1233
  this.stateUpdateHandlers.add(handler);
475
1234
  return () => this.stateUpdateHandlers.delete(handler);
476
1235
  }
477
- /**
478
- * Register a handler for game status changes
479
- */
480
- onGameStatusChange(handler) {
1236
+ /** Register a handler for in-game status changes (running, paused, out of game). */
1237
+ onIngameStatusChange(handler) {
481
1238
  this.gameStatusHandlers.add(handler);
482
1239
  return () => this.gameStatusHandlers.delete(handler);
483
1240
  }
484
- /**
485
- * Register handlers for game events
486
- */
487
- onGameEvents(handlers) {
488
- this.eventHandlers = { ...this.eventHandlers, ...handlers };
1241
+ /** Register handlers for in-game events (kills, objectives, etc.). */
1242
+ onIngameEvents(handlers) {
1243
+ this.ingameEventHandlers = { ...this.ingameEventHandlers, ...handlers };
489
1244
  }
490
- /**
491
- * Register a handler for connection events
492
- */
493
- onConnect(handler) {
494
- return this.ws.onConnect(handler);
1245
+ // ===========================================================================
1246
+ // Pre-game event handlers
1247
+ // ===========================================================================
1248
+ /** Register a handler for champ-select state updates. */
1249
+ onChampSelectUpdate(handler) {
1250
+ this.champSelectUpdateHandlers.add(handler);
1251
+ return () => this.champSelectUpdateHandlers.delete(handler);
495
1252
  }
496
- /**
497
- * Register a handler for disconnection events
498
- */
499
- onDisconnect(handler) {
500
- return this.ws.onDisconnect(handler);
1253
+ /** Register handlers for champ-select lifecycle and action events. */
1254
+ onChampSelectEvents(handlers) {
1255
+ this.champSelectEventHandlers = {
1256
+ ...this.champSelectEventHandlers,
1257
+ ...handlers
1258
+ };
501
1259
  }
502
- /**
503
- * Register a handler for error events
504
- */
505
- onError(handler) {
506
- return this.ws.onError(handler);
1260
+ // ===========================================================================
1261
+ // Connection event handlers
1262
+ // ===========================================================================
1263
+ /** Register a handler for in-game connection. */
1264
+ onIngameConnect(handler) {
1265
+ return this.ingameWs.onConnect(handler);
507
1266
  }
508
- // ---------------------------------------------------------------------------
509
- // Reactive API — convenience wrappers around this.store
510
- // ---------------------------------------------------------------------------
1267
+ /** Register a handler for in-game disconnection. */
1268
+ onIngameDisconnect(handler) {
1269
+ return this.ingameWs.onDisconnect(handler);
1270
+ }
1271
+ /** Register a handler for in-game connection errors. */
1272
+ onIngameError(handler) {
1273
+ return this.ingameWs.onError(handler);
1274
+ }
1275
+ /** Register a handler for pre-game connection. */
1276
+ onPreGameConnect(handler) {
1277
+ return this.preGameWs.onConnect(handler);
1278
+ }
1279
+ /** Register a handler for pre-game disconnection. */
1280
+ onPreGameDisconnect(handler) {
1281
+ return this.preGameWs.onDisconnect(handler);
1282
+ }
1283
+ /** Register a handler for pre-game connection errors. */
1284
+ onPreGameError(handler) {
1285
+ return this.preGameWs.onError(handler);
1286
+ }
1287
+ // ===========================================================================
1288
+ // Reactive API — in-game (convenience wrappers around this.store)
1289
+ // ===========================================================================
511
1290
  /**
512
- * Create a subscribable slice of game state.
1291
+ * Create a subscribable slice of **in-game** state.
513
1292
  * The slice only notifies listeners when the selected value actually changes.
514
1293
  *
515
1294
  * Works directly with React 18+ `useSyncExternalStore`:
516
1295
  * ```tsx
517
- * const kills = client.select(s => s.gameData.scoreboard?.teams[0]?.kills);
1296
+ * const kills = client.selectIngame(s => s.gameData.scoreboard?.teams[0]?.kills);
518
1297
  * function Kills() {
519
1298
  * const value = useSyncExternalStore(kills.subscribe, kills.getSnapshot);
520
1299
  * return <span>{value}</span>;
521
1300
  * }
522
1301
  * ```
523
1302
  */
524
- select(selector, equalityFn) {
525
- return this.store.select(selector, equalityFn);
1303
+ selectIngame(selector, equalityFn) {
1304
+ return this.ingameStore.select(selector, equalityFn);
526
1305
  }
527
1306
  /**
528
- * Watch a derived value and invoke `callback` whenever it changes.
1307
+ * Watch a derived **in-game** value and invoke `callback` whenever it changes.
529
1308
  * Returns an unsubscribe function.
530
1309
  *
531
1310
  * ```ts
532
- * client.watch(
1311
+ * client.watchIngame(
533
1312
  * s => s.gameData.scoreboard?.teams[0]?.kills,
534
1313
  * (kills, prev) => console.log(`Kills: ${prev} → ${kills}`),
535
1314
  * );
536
1315
  * ```
537
1316
  */
538
- watch(selector, callback, equalityFn) {
539
- return this.store.watch(selector, callback, equalityFn);
1317
+ watchIngame(selector, callback, equalityFn) {
1318
+ return this.ingameStore.watch(selector, callback, equalityFn);
540
1319
  }
1320
+ // ===========================================================================
1321
+ // Reactive API — pre-game (convenience wrappers around this.preGameStore)
1322
+ // ===========================================================================
541
1323
  /**
542
- * Get the base HTTP URL for API requests
1324
+ * Create a subscribable slice of **pre-game** (champion select) state.
1325
+ *
1326
+ * ```tsx
1327
+ * const timer = client.selectChampSelect(s => s.champSelectData.timer);
1328
+ * function DraftTimer() {
1329
+ * const value = useSyncExternalStore(timer.subscribe, timer.getSnapshot);
1330
+ * return <span>{value?.timeRemaining}</span>;
1331
+ * }
1332
+ * ```
1333
+ */
1334
+ selectChampSelect(selector, equalityFn) {
1335
+ return this.preGameStore.select(selector, equalityFn);
1336
+ }
1337
+ /**
1338
+ * Watch a derived **pre-game** value and invoke `callback` whenever it
1339
+ * changes. Returns an unsubscribe function.
1340
+ *
1341
+ * ```ts
1342
+ * client.watchChampSelect(
1343
+ * s => s.champSelectData.timer.timeRemaining,
1344
+ * (remaining, prev) => console.log(`Time: ${prev} → ${remaining}`),
1345
+ * );
1346
+ * ```
543
1347
  */
1348
+ watchChampSelect(selector, callback, equalityFn) {
1349
+ return this.preGameStore.watch(selector, callback, equalityFn);
1350
+ }
1351
+ // ===========================================================================
1352
+ // URLs
1353
+ // ===========================================================================
1354
+ /** Get the base HTTP URL for API requests. */
544
1355
  getApiUrl() {
545
1356
  const protocol = this.config.useHttps ? "https" : "http";
546
1357
  return `${protocol}://${this.config.host}:${this.config.port}${this.config.apiRoute}`;
547
1358
  }
548
- /**
549
- * Get the base URL for cache requests
550
- */
1359
+ /** Get the base URL for cache requests (optionally resolve a path). */
551
1360
  getCacheUrl(path) {
552
1361
  const protocol = this.config.useHttps ? "https" : "http";
553
1362
  const baseUrl = `${protocol}://${this.config.host}:${this.config.port}${this.config.cacheRoute}`;
@@ -569,11 +1378,11 @@ var LeagueBroadcastClient = class {
569
1378
  }
570
1379
  return `${baseUrl}/${cleanPath}`;
571
1380
  }
572
- /**
573
- * Setup message handler for WebSocket messages
574
- */
575
- setupMessageHandler() {
576
- this.ws.onMessage((messageData) => {
1381
+ // ===========================================================================
1382
+ // Private in-game message handling
1383
+ // ===========================================================================
1384
+ setupIngameMessageHandler() {
1385
+ this.ingameWs.onMessage((messageData) => {
577
1386
  switch (messageData.type) {
578
1387
  case "ingame-state-update":
579
1388
  this.handleStateUpdate(messageData.state, messageData.events);
@@ -587,84 +1396,210 @@ var LeagueBroadcastClient = class {
587
1396
  }
588
1397
  });
589
1398
  }
590
- /**
591
- * Handle state update from backend
592
- */
593
1399
  handleStateUpdate(state, events) {
594
- const nextData = Object.assign(new ingameFrontendData(), state);
1400
+ const nextData = {
1401
+ gameTime: 0,
1402
+ playbackSpeed: 0,
1403
+ gameVersion: "",
1404
+ gameStatus: 0 /* OutOfGame */,
1405
+ ...state
1406
+ };
595
1407
  this.gameData = structuralShare(this.gameData, nextData);
596
1408
  if (!state.gameTime || state.gameTime === 0) {
597
1409
  this.handleGameStatusUpdate(0 /* OutOfGame */, false);
598
1410
  }
599
- this.store._setGameData(this.gameData);
1411
+ this.ingameStore._setGameData(this.gameData);
600
1412
  this.stateUpdateHandlers.forEach((handler) => handler(this.gameData));
601
1413
  this.handleGameEvents(events);
602
1414
  }
603
- /**
604
- * Handle game status update
605
- */
606
1415
  handleGameStatusUpdate(gameStatus, isTestingEnvironment = false) {
607
- this.isTestingEnvironment = isTestingEnvironment;
1416
+ this._isTestingEnvironment = isTestingEnvironment;
608
1417
  if (gameStatus === 0 /* OutOfGame */ && this.gameState !== 0 /* OutOfGame */) {
609
1418
  this.endGame();
610
1419
  return;
611
1420
  }
612
1421
  this.gameState = gameStatus;
613
- this.store._setGameState(gameStatus);
1422
+ this.ingameStore._setGameState(gameStatus);
614
1423
  this.gameStatusHandlers.forEach(
615
1424
  (handler) => handler(gameStatus, isTestingEnvironment)
616
1425
  );
617
1426
  }
618
- /**
619
- * Handle game events
620
- */
621
1427
  handleGameEvents(events) {
622
- if (!events) {
623
- return;
624
- }
625
- if (events.player && this.eventHandlers.onPlayerEvent) {
1428
+ if (!events) return;
1429
+ if (events.player && this.ingameEventHandlers.onPlayerEvent) {
626
1430
  events.player.forEach(
627
- (event) => this.eventHandlers.onPlayerEvent(event)
1431
+ (event) => this.ingameEventHandlers.onPlayerEvent(event)
628
1432
  );
629
1433
  }
630
- if (events.team && this.eventHandlers.onTeamEvent) {
631
- events.team.forEach((event) => this.eventHandlers.onTeamEvent(event));
1434
+ if (events.team && this.ingameEventHandlers.onTeamEvent) {
1435
+ events.team.forEach(
1436
+ (event) => this.ingameEventHandlers.onTeamEvent(event)
1437
+ );
632
1438
  }
633
- if (events.objective && this.eventHandlers.onObjectiveEvent) {
1439
+ if (events.objective && this.ingameEventHandlers.onObjectiveEvent) {
634
1440
  events.objective.forEach(
635
- (event) => this.eventHandlers.onObjectiveEvent(event)
1441
+ (event) => this.ingameEventHandlers.onObjectiveEvent(event)
636
1442
  );
637
1443
  }
638
- if (events.firstTower !== void 0 && this.eventHandlers.onFirstTowerEvent) {
639
- this.eventHandlers.onFirstTowerEvent(events.firstTower);
1444
+ if (events.firstTower !== void 0 && this.ingameEventHandlers.onFirstTowerEvent) {
1445
+ this.ingameEventHandlers.onFirstTowerEvent(events.firstTower);
640
1446
  }
641
- if (events.announcements && this.eventHandlers.onAnnouncementEvent) {
1447
+ if (events.announcements && this.ingameEventHandlers.onAnnouncementEvent) {
642
1448
  events.announcements.forEach(
643
- (event) => this.eventHandlers.onAnnouncementEvent(event)
1449
+ (event) => this.ingameEventHandlers.onAnnouncementEvent(event)
644
1450
  );
645
1451
  }
646
- if (events.killFeed && this.eventHandlers.onKillFeedEvent) {
1452
+ if (events.killFeed && this.ingameEventHandlers.onKillFeedEvent) {
647
1453
  events.killFeed.forEach(
648
- (event) => this.eventHandlers.onKillFeedEvent(event)
1454
+ (event) => this.ingameEventHandlers.onKillFeedEvent(event)
649
1455
  );
650
1456
  }
651
1457
  }
652
- /**
653
- * End the game and reset state
654
- */
655
1458
  endGame() {
656
1459
  console.log("[LeagueBroadcastClient] Game ended, resetting data");
657
1460
  this.gameData = new ingameFrontendData();
658
1461
  this.gameState = 0 /* OutOfGame */;
659
- this.isTestingEnvironment = false;
660
- this.store._reset(this.gameData, 0 /* OutOfGame */);
1462
+ this._isTestingEnvironment = false;
1463
+ this.ingameStore._reset(this.gameData, 0 /* OutOfGame */);
661
1464
  this.gameStatusHandlers.forEach(
662
1465
  (handler) => handler(0 /* OutOfGame */, false)
663
1466
  );
664
1467
  this.stateUpdateHandlers.forEach((handler) => handler(this.gameData));
665
1468
  }
1469
+ // ===========================================================================
1470
+ // Private — pre-game message handling
1471
+ // ===========================================================================
1472
+ setupPreGameMessageHandler() {
1473
+ this.preGameWs.onMessage((messageData) => {
1474
+ switch (messageData.type) {
1475
+ case "champion-select-state-update":
1476
+ this.handleChampSelectStateUpdate(messageData.state);
1477
+ break;
1478
+ case "champion-select-action":
1479
+ this.handleChampSelectAction(messageData.action);
1480
+ break;
1481
+ case "frontend-route-update":
1482
+ this.handleRouteUpdate(messageData.uri);
1483
+ break;
1484
+ }
1485
+ });
1486
+ }
1487
+ handleChampSelectStateUpdate(state) {
1488
+ const nextData = {
1489
+ isActive: false,
1490
+ isConnected: false,
1491
+ isTestingEnvironment: false,
1492
+ blueTeam: {},
1493
+ redTeam: {},
1494
+ metaData: {},
1495
+ timer: {},
1496
+ ...state
1497
+ };
1498
+ this.champSelectData = structuralShare(this.champSelectData, nextData);
1499
+ if (nextData.isActive && !this.champSelectWasActive) {
1500
+ this.champSelectWasActive = true;
1501
+ this.champSelectEventHandlers.onChampSelectStart?.();
1502
+ } else if (!nextData.isActive && this.champSelectWasActive) {
1503
+ this.champSelectWasActive = false;
1504
+ this.endChampSelect();
1505
+ return;
1506
+ }
1507
+ this.preGameStore._setChampSelectData(this.champSelectData);
1508
+ this.champSelectUpdateHandlers.forEach(
1509
+ (handler) => handler(this.champSelectData)
1510
+ );
1511
+ }
1512
+ handleChampSelectAction(action) {
1513
+ this.champSelectEventHandlers.onAction?.(action);
1514
+ }
1515
+ handleRouteUpdate(uri) {
1516
+ this.champSelectEventHandlers.onRouteUpdate?.(uri);
1517
+ }
1518
+ endChampSelect() {
1519
+ console.log("[LeagueBroadcastClient] Champ select ended, resetting data");
1520
+ this.champSelectData = new champSelectStateData();
1521
+ this.preGameStore._reset(this.champSelectData);
1522
+ this.champSelectEventHandlers.onChampSelectEnd?.();
1523
+ this.champSelectUpdateHandlers.forEach(
1524
+ (handler) => handler(this.champSelectData)
1525
+ );
1526
+ }
666
1527
  };
667
1528
 
668
- export { GameState, GameStateStore, LeagueBroadcastClient, WebSocketManager, shallowEqual };
1529
+ // types/pregame/pickbanphase.ts
1530
+ var PickBanPhase = /* @__PURE__ */ ((PickBanPhase2) => {
1531
+ PickBanPhase2[PickBanPhase2["BEGIN"] = 0] = "BEGIN";
1532
+ PickBanPhase2[PickBanPhase2["BAN1"] = 1] = "BAN1";
1533
+ PickBanPhase2[PickBanPhase2["BAN2"] = 2] = "BAN2";
1534
+ PickBanPhase2[PickBanPhase2["PICK1"] = 3] = "PICK1";
1535
+ PickBanPhase2[PickBanPhase2["PICK2"] = 4] = "PICK2";
1536
+ PickBanPhase2[PickBanPhase2["END"] = 5] = "END";
1537
+ PickBanPhase2[PickBanPhase2["WAIT"] = 6] = "WAIT";
1538
+ return PickBanPhase2;
1539
+ })(PickBanPhase || {});
1540
+
1541
+ // types/pregame/actiontype.ts
1542
+ var ActionType = /* @__PURE__ */ ((ActionType2) => {
1543
+ ActionType2[ActionType2["TEN_BANS_REVEAL"] = 0] = "TEN_BANS_REVEAL";
1544
+ ActionType2[ActionType2["PHASE_TRANSITION"] = 1] = "PHASE_TRANSITION";
1545
+ ActionType2[ActionType2["PICK"] = 2] = "PICK";
1546
+ ActionType2[ActionType2["BAN"] = 3] = "BAN";
1547
+ return ActionType2;
1548
+ })(ActionType || {});
1549
+
1550
+ // types/pregame/actionsubtype.ts
1551
+ var ActionSubType = /* @__PURE__ */ ((ActionSubType2) => {
1552
+ ActionSubType2[ActionSubType2["START"] = 0] = "START";
1553
+ ActionSubType2[ActionSubType2["HOVER"] = 1] = "HOVER";
1554
+ ActionSubType2[ActionSubType2["LOCK"] = 2] = "LOCK";
1555
+ return ActionSubType2;
1556
+ })(ActionSubType || {});
1557
+
1558
+ // types/pregame/timelineactiontype.ts
1559
+ var TimeLineActionType = /* @__PURE__ */ ((TimeLineActionType2) => {
1560
+ TimeLineActionType2[TimeLineActionType2["HoverPick"] = 0] = "HoverPick";
1561
+ TimeLineActionType2[TimeLineActionType2["Pick"] = 1] = "Pick";
1562
+ TimeLineActionType2[TimeLineActionType2["Ban"] = 2] = "Ban";
1563
+ return TimeLineActionType2;
1564
+ })(TimeLineActionType || {});
1565
+
1566
+ // types/shared/bestoftype.ts
1567
+ var BestOfType = /* @__PURE__ */ ((BestOfType2) => {
1568
+ BestOfType2[BestOfType2["BestOf1"] = 1] = "BestOf1";
1569
+ BestOfType2[BestOfType2["BestOf2"] = 2] = "BestOf2";
1570
+ BestOfType2[BestOfType2["BestOf3"] = 3] = "BestOf3";
1571
+ BestOfType2[BestOfType2["BestOf5"] = 5] = "BestOf5";
1572
+ BestOfType2[BestOfType2["BestOf7"] = 7] = "BestOf7";
1573
+ return BestOfType2;
1574
+ })(BestOfType || {});
1575
+
1576
+ // types/shared/matchruleset.ts
1577
+ var MatchRuleSet = /* @__PURE__ */ ((MatchRuleSet2) => {
1578
+ MatchRuleSet2[MatchRuleSet2["Standard"] = 0] = "Standard";
1579
+ MatchRuleSet2[MatchRuleSet2["PartialFearless"] = 1] = "PartialFearless";
1580
+ MatchRuleSet2[MatchRuleSet2["Fearless"] = 2] = "Fearless";
1581
+ return MatchRuleSet2;
1582
+ })(MatchRuleSet || {});
1583
+
1584
+ // src/util/ingameScoreboardBottomPlayerDataUtils.ts
1585
+ function getSortedInventory(playerData) {
1586
+ if (!playerData.items) return Array(6).fill({ id: 0 });
1587
+ const items = playerData.items?.filter((item) => item.slot < 6) ?? [];
1588
+ const regularItems = items.sort(
1589
+ (a, b) => (a?.cost ?? 0) - (b?.cost ?? 0)
1590
+ );
1591
+ while (regularItems.length < 6) {
1592
+ regularItems.unshift(void 0);
1593
+ }
1594
+ return regularItems ?? [];
1595
+ }
1596
+ function getTrinket(playerData) {
1597
+ return playerData.items?.find((item) => item.slot === 6);
1598
+ }
1599
+ function getRoleQuest(playerData) {
1600
+ return playerData.items?.find((item) => item.slot === 8);
1601
+ }
1602
+
1603
+ export { ActionSubType, ActionType, ApiClient, ApiError, BestOfType, ChampSelectStateStore, GameApi, GameState, GameStateApi, GameStateStore, IngameApi, LeagueBroadcastClient, MatchApi, MatchRuleSet, PickBanPhase, PreGameApi, RestApi, SeasonApi, TimeLineActionType, WebSocketManager, getRoleQuest, getSortedInventory, getTrinket, shallowEqual };
669
1604
  //# sourceMappingURL=index.js.map
670
1605
  //# sourceMappingURL=index.js.map