nhl-api-ts 0.2.0 → 0.3.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.
Files changed (51) hide show
  1. package/README.md +81 -9
  2. package/dist/api/draft.d.mts +61 -0
  3. package/dist/api/draft.mjs +68 -0
  4. package/dist/api/edge.d.mts +221 -24
  5. package/dist/api/edge.mjs +276 -27
  6. package/dist/api/game-center.d.mts +63 -15
  7. package/dist/api/game-center.mjs +67 -8
  8. package/dist/api/helpers.d.mts +6 -6
  9. package/dist/api/helpers.mjs +6 -6
  10. package/dist/api/misc.d.mts +120 -6
  11. package/dist/api/misc.mjs +162 -7
  12. package/dist/api/players.d.mts +59 -7
  13. package/dist/api/players.mjs +85 -4
  14. package/dist/api/query/cayenne.d.mts +4 -0
  15. package/dist/api/query/cayenne.mjs +13 -0
  16. package/dist/api/query/sorting/sorting-options.d.mts +8 -0
  17. package/dist/api/query/sorting/sorting-options.mjs +30 -0
  18. package/dist/api/schedule.d.mts +36 -23
  19. package/dist/api/schedule.mjs +40 -16
  20. package/dist/api/standings.d.mts +3 -3
  21. package/dist/api/standings.mjs +4 -4
  22. package/dist/api/stats.d.mts +105 -16
  23. package/dist/api/stats.mjs +145 -41
  24. package/dist/api/teams.d.mts +48 -8
  25. package/dist/api/teams.mjs +59 -7
  26. package/dist/cli/colors.d.mts +2 -2
  27. package/dist/cli/colors.mjs +6 -2
  28. package/dist/cli/commands.mjs +521 -46
  29. package/dist/cli/run.mjs +7 -5
  30. package/dist/http-client.d.mts +2 -1
  31. package/dist/http-client.mjs +10 -3
  32. package/dist/index.d.mts +8 -2
  33. package/dist/index.mjs +3 -0
  34. package/dist/nhl-client.d.mts +70 -15
  35. package/dist/nhl-client.mjs +40 -17
  36. package/dist/types/common.d.mts +0 -1
  37. package/dist/types/draft.d.mts +97 -0
  38. package/dist/types/draft.mjs +1 -0
  39. package/dist/types/edge.d.mts +301 -5
  40. package/dist/types/game-center.d.mts +277 -119
  41. package/dist/types/index.d.mts +1 -0
  42. package/dist/types/misc.d.mts +101 -0
  43. package/dist/types/misc.mjs +0 -1
  44. package/dist/types/players.d.mts +23 -2
  45. package/dist/types/schedule.d.mts +50 -62
  46. package/dist/types/standings.d.mts +1 -2
  47. package/dist/types/stats.d.mts +313 -111
  48. package/dist/types/teams.d.mts +29 -1
  49. package/dist/utils.d.mts +1 -1
  50. package/dist/utils.mjs +3 -1
  51. package/package.json +7 -28
@@ -9,7 +9,9 @@ async function getWeb(ctx, resource) {
9
9
  * @param params.gameId Game id, e.g. 2023020280
10
10
  * @example https://api-web.nhle.com/v1/gamecenter/2023020280/boxscore
11
11
  */
12
- export const boxscore = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/boxscore`);
12
+ export async function boxscore(ctx, { gameId }) {
13
+ return getWeb(ctx, `gamecenter/${gameId}/boxscore`);
14
+ }
13
15
  /**
14
16
  * Get the full play-by-play feed for a specific NHL game, containing every
15
17
  * recorded event (shots, hits, faceoffs, goals, penalties...).
@@ -17,7 +19,9 @@ export const boxscore = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gam
17
19
  * @param params.gameId Game id, e.g. 2023020280
18
20
  * @example https://api-web.nhle.com/v1/gamecenter/2023020280/play-by-play
19
21
  */
20
- export const playByPlay = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/play-by-play`);
22
+ export async function playByPlay(ctx, { gameId }) {
23
+ return getWeb(ctx, `gamecenter/${gameId}/play-by-play`);
24
+ }
21
25
  /**
22
26
  * Get the landing-page summary for a specific NHL game, including scoring by
23
27
  * period, three stars and penalties.
@@ -25,7 +29,9 @@ export const playByPlay = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${g
25
29
  * @param params.gameId Game id, e.g. 2023020280
26
30
  * @example https://api-web.nhle.com/v1/gamecenter/2023020280/landing
27
31
  */
28
- export const matchUp = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/landing`);
32
+ export async function matchUp(ctx, { gameId }) {
33
+ return getWeb(ctx, `gamecenter/${gameId}/landing`);
34
+ }
29
35
  /**
30
36
  * Get scores and game states for all NHL games on a given date. Returns the
31
37
  * current day's scores when no date is supplied.
@@ -33,7 +39,9 @@ export const matchUp = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${game
33
39
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
34
40
  * @example https://api-web.nhle.com/v1/score/2023-10-15
35
41
  */
36
- export const dailyScores = async (ctx, { date } = {}) => getWeb(ctx, `score/${date ? date : 'now'}`);
42
+ export async function dailyScores(ctx, { date } = {}) {
43
+ return getWeb(ctx, `score/${date ? date : 'now'}`);
44
+ }
37
45
  /**
38
46
  * Get individual player shift data for a specific game, including start/end
39
47
  * times and durations.
@@ -42,11 +50,11 @@ export const dailyScores = async (ctx, { date } = {}) => getWeb(ctx, `score/${da
42
50
  * @param params.excludes Fields to exclude from the response. Defaults to ["eventDetails"].
43
51
  * @example https://api.nhle.com/stats/rest/en/shiftcharts?cayenneExp=gameId=2023020280 and ...
44
52
  */
45
- export const shiftChartData = async (ctx, { gameId, excludes = ['eventDetails'] }) => {
53
+ export async function shiftChartData(ctx, { gameId, excludes = ['eventDetails'] }) {
46
54
  const excludeP = excludes.join(',');
47
55
  const exprP = `gameId=${gameId} and ((duration != '00:00' and typeCode = 517) or typeCode != 517 )`;
48
56
  return (await ctx.get(Endpoint.API_STATS, `en/shiftcharts?cayenneExp=${exprP}&exclude=${excludeP}`)).json();
49
- };
57
+ }
50
58
  /**
51
59
  * Get the season-series record and contextual stats for a specific game,
52
60
  * including team season stats and last games.
@@ -54,7 +62,9 @@ export const shiftChartData = async (ctx, { gameId, excludes = ['eventDetails']
54
62
  * @param params.gameId Game id, e.g. 2023020280
55
63
  * @example https://api-web.nhle.com/v1/gamecenter/2023020280/right-rail
56
64
  */
57
- export const seasonSeriesMatchup = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/right-rail`);
65
+ export async function seasonSeriesMatchup(ctx, { gameId }) {
66
+ return getWeb(ctx, `gamecenter/${gameId}/right-rail`);
67
+ }
58
68
  /**
59
69
  * Get the narrative game story for a specific game, including scoring
60
70
  * summaries, three stars and team game stats.
@@ -62,7 +72,52 @@ export const seasonSeriesMatchup = async (ctx, { gameId }) => getWeb(ctx, `gamec
62
72
  * @param params.gameId Game id, e.g. 2023020280
63
73
  * @example https://api-web.nhle.com/v1/wsc/game-story/2023020280
64
74
  */
65
- export const gameStory = async (ctx, { gameId }) => getWeb(ctx, `wsc/game-story/${gameId}`);
75
+ export async function gameStory(ctx, { gameId }) {
76
+ return getWeb(ctx, `wsc/game-story/${gameId}`);
77
+ }
78
+ /**
79
+ * Get the league scoreboard: every game in the week around a date, grouped by
80
+ * date. Returns the week around today when no date is supplied.
81
+ *
82
+ * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
83
+ * @example https://api-web.nhle.com/v1/scoreboard/2023-10-15
84
+ */
85
+ export async function scoreboard(ctx, { date } = {}) {
86
+ return getWeb(ctx, `scoreboard/${date ?? 'now'}`);
87
+ }
88
+ /**
89
+ * Get the play-by-play feed nhl.com's game story widget uses. A bare array of
90
+ * plays, with a different play shape from `playByPlay`.
91
+ *
92
+ * @param params.gameId Game id, e.g. 2023020280
93
+ * @example https://api-web.nhle.com/v1/wsc/play-by-play/2023020280
94
+ */
95
+ export async function wscPlayByPlay(ctx, { gameId }) {
96
+ return getWeb(ctx, `wsc/play-by-play/${gameId}`);
97
+ }
98
+ /**
99
+ * Get the replay card for one play-by-play event: the game header, plus a
100
+ * `goal` object (scorer, assists, highlight clip and the `pptReplayUrl`
101
+ * puck-and-player-tracking link) when the event is a goal. Any event id works.
102
+ *
103
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
104
+ * @param params.gameId Game id, e.g. 2023020280
105
+ * @param params.eventNumber The play's `eventId` from `playByPlay`, e.g. 193
106
+ * @example https://api-web.nhle.com/v1/ppt-replay/2023020280/193
107
+ */
108
+ export async function playReplay(ctx, { gameId, eventNumber }) {
109
+ return getWeb(ctx, `ppt-replay/${gameId}/${eventNumber}`);
110
+ }
111
+ /**
112
+ * Get the metadata nhl.com uses to render a game page: the two teams, the
113
+ * season state and the game state.
114
+ *
115
+ * @param params.gameId Game id, e.g. 2023020280
116
+ * @example https://api-web.nhle.com/v1/meta/game/2023020280
117
+ */
118
+ export async function gameMeta(ctx, { gameId }) {
119
+ return getWeb(ctx, `meta/game/${gameId}`);
120
+ }
66
121
  export const gameCenterApi = {
67
122
  boxscore,
68
123
  playByPlay,
@@ -71,4 +126,8 @@ export const gameCenterApi = {
71
126
  shiftChartData,
72
127
  seasonSeriesMatchup,
73
128
  gameStory,
129
+ scoreboard,
130
+ wscPlayByPlay,
131
+ playReplay,
132
+ gameMeta,
74
133
  };
@@ -10,11 +10,11 @@ import type { Id } from '#src/utils.mjs';
10
10
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
11
11
  * @example await client.helpers.gameIdsBySeason({ season: '20232024', gameTypes: [2] })
12
12
  */
13
- export declare const gameIdsBySeason: (ctx: Context, { season, gameTypes, apiSleepRate, }: {
13
+ export declare function gameIdsBySeason(ctx: Context, { season, gameTypes, apiSleepRate, }: {
14
14
  season: Id;
15
15
  gameTypes?: number[];
16
16
  apiSleepRate?: number;
17
- }) => Promise<number[]>;
17
+ }): Promise<number[]>;
18
18
  /**
19
19
  * Gets every rostered player across all NHL teams for a given season. Each
20
20
  * player gets a `team` abbreviation and flattened `firstName` / `lastName`.
@@ -23,10 +23,10 @@ export declare const gameIdsBySeason: (ctx: Context, { season, gameTypes, apiSle
23
23
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 0.5.
24
24
  * @example await client.helpers.allPlayers({ season: '20232024' })
25
25
  */
26
- export declare const allPlayers: (ctx: Context, { season, apiSleepRate }: {
26
+ export declare function allPlayers(ctx: Context, { season, apiSleepRate }: {
27
27
  season: Id;
28
28
  apiSleepRate?: number;
29
- }) => Promise<AllPlayersEntry[]>;
29
+ }): Promise<AllPlayersEntry[]>;
30
30
  /**
31
31
  * Gets summary statistics for every skater in a given season, merged with
32
32
  * the roster info from `allPlayers` (stat fields win on key collisions).
@@ -36,10 +36,10 @@ export declare const allPlayers: (ctx: Context, { season, apiSleepRate }: {
36
36
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
37
37
  * @example await client.helpers.allPlayersSummaryStatistics({ season: '20232024' })
38
38
  */
39
- export declare const allPlayersSummaryStatistics: (ctx: Context, { season, apiSleepRate }: {
39
+ export declare function allPlayersSummaryStatistics(ctx: Context, { season, apiSleepRate }: {
40
40
  season: Id;
41
41
  apiSleepRate?: number;
42
- }) => Promise<PlayerSummaryStatistics[]>;
42
+ }): Promise<PlayerSummaryStatistics[]>;
43
43
  export declare const helpersApi: {
44
44
  readonly gameIdsBySeason: typeof gameIdsBySeason;
45
45
  readonly allPlayers: typeof allPlayers;
@@ -12,7 +12,7 @@ import { teams as fetchTeams, teamRoster } from '#src/api/teams.mjs';
12
12
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
13
13
  * @example await client.helpers.gameIdsBySeason({ season: '20232024', gameTypes: [2] })
14
14
  */
15
- export const gameIdsBySeason = async (ctx, { season, gameTypes, apiSleepRate = 1, }) => {
15
+ export async function gameIdsBySeason(ctx, { season, gameTypes, apiSleepRate = 1, }) {
16
16
  const teams = await fetchTeams(ctx);
17
17
  const gameIds = [];
18
18
  for (const team of teams) {
@@ -33,7 +33,7 @@ export const gameIdsBySeason = async (ctx, { season, gameTypes, apiSleepRate = 1
33
33
  }
34
34
  }
35
35
  return gameIds;
36
- };
36
+ }
37
37
  /**
38
38
  * Gets every rostered player across all NHL teams for a given season. Each
39
39
  * player gets a `team` abbreviation and flattened `firstName` / `lastName`.
@@ -42,7 +42,7 @@ export const gameIdsBySeason = async (ctx, { season, gameTypes, apiSleepRate = 1
42
42
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 0.5.
43
43
  * @example await client.helpers.allPlayers({ season: '20232024' })
44
44
  */
45
- export const allPlayers = async (ctx, { season, apiSleepRate = 0.5 }) => {
45
+ export async function allPlayers(ctx, { season, apiSleepRate = 0.5 }) {
46
46
  const teams = await fetchTeams(ctx);
47
47
  console.error('Fetching all player base stats. This may take a while...');
48
48
  const outData = [];
@@ -63,7 +63,7 @@ export const allPlayers = async (ctx, { season, apiSleepRate = 0.5 }) => {
63
63
  }
64
64
  }
65
65
  return outData;
66
- };
66
+ }
67
67
  /**
68
68
  * Gets summary statistics for every skater in a given season, merged with
69
69
  * the roster info from `allPlayers` (stat fields win on key collisions).
@@ -73,7 +73,7 @@ export const allPlayers = async (ctx, { season, apiSleepRate = 0.5 }) => {
73
73
  * @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
74
74
  * @example await client.helpers.allPlayersSummaryStatistics({ season: '20232024' })
75
75
  */
76
- export const allPlayersSummaryStatistics = async (ctx, { season, apiSleepRate = 1 }) => {
76
+ export async function allPlayersSummaryStatistics(ctx, { season, apiSleepRate = 1 }) {
77
77
  console.error('WARNING: This method will take a while to run. In the event of rate limiting, you may need to increase the api_sleep_rate.');
78
78
  const players = await allPlayers(ctx, { season, apiSleepRate });
79
79
  const teams = await fetchTeams(ctx);
@@ -98,7 +98,7 @@ export const allPlayersSummaryStatistics = async (ctx, { season, apiSleepRate =
98
98
  : undefined;
99
99
  return player ? { ...player, ...statEntry } : statEntry;
100
100
  });
101
- };
101
+ }
102
102
  export const helpersApi = {
103
103
  gameIdsBySeason,
104
104
  allPlayers,
@@ -1,40 +1,154 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Country, DraftYear, GlossaryEntry, SeasonRules, StatsConfig } from '#src/types/index.mjs';
2
+ import type { ComponentSeason, Country, DraftYear, GeoLocation, GlossaryEntry, Meta, PartnerGameOdds, PostalLookupTeam, SeasonId, SeasonRules, StatsConfig, StatsGame, TvSchedule } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  /**
4
5
  * Gets the full NHL glossary of statistical terms and abbreviations.
5
6
  *
6
7
  * @example https://api.nhle.com/stats/rest/en/glossary?sort=fullName
7
8
  */
8
- export declare const glossary: (ctx: Context) => Promise<GlossaryEntry[]>;
9
+ export declare function glossary(ctx: Context): Promise<GlossaryEntry[]>;
9
10
  /**
10
11
  * Gets the stats API configuration, including available report types and
11
12
  * filters.
12
13
  *
13
14
  * @example https://api.nhle.com/stats/rest/en/config
14
15
  */
15
- export declare const config: (ctx: Context) => Promise<StatsConfig>;
16
+ export declare function config(ctx: Context): Promise<StatsConfig>;
16
17
  /**
17
18
  * Gets the list of countries recognized by the NHL.
18
19
  *
19
20
  * @example https://api.nhle.com/stats/rest/en/country
20
21
  */
21
- export declare const countries: (ctx: Context) => Promise<Country[]>;
22
+ export declare function countries(ctx: Context): Promise<Country[]>;
22
23
  /**
23
24
  * Gets rules and metadata for every NHL season on record.
24
25
  *
25
26
  * @example https://api.nhle.com/stats/rest/en/season
26
27
  */
27
- export declare const seasonSpecificRulesAndInfo: (ctx: Context) => Promise<SeasonRules[]>;
28
+ export declare function seasonSpecificRulesAndInfo(ctx: Context): Promise<SeasonRules[]>;
28
29
  /**
29
30
  * Gets the number of rounds for each NHL draft year.
30
31
  *
31
32
  * @example https://api.nhle.com/stats/rest/en/draft
32
33
  */
33
- export declare const draftYearAndRounds: (ctx: Context) => Promise<DraftYear[]>;
34
+ export declare function draftYearAndRounds(ctx: Context): Promise<DraftYear[]>;
35
+ /**
36
+ * Gets the season and game type the stats API currently serves by default.
37
+ *
38
+ * @example https://api.nhle.com/stats/rest/en/componentSeason
39
+ */
40
+ export declare function componentSeasons(ctx: Context): Promise<ComponentSeason[]>;
41
+ export interface GamesParams {
42
+ /** Season in YYYYYYYY format, e.g. 20232024 (about 1,500 games). */
43
+ season?: Id;
44
+ /** 1=Preseason, 2=Regular season, 3=Playoffs. */
45
+ gameType?: number;
46
+ /** NHL team id, home or away, e.g. 10. */
47
+ teamId?: Id;
48
+ /** First game date, YYYY-MM-DD (inclusive). */
49
+ startDate?: string;
50
+ /** Last game date, YYYY-MM-DD (inclusive). */
51
+ endDate?: string;
52
+ /**
53
+ * Extra filter expression, joined to the others with `and`. Only the row
54
+ * fields (`season`, `gameType`, `gameDate`, `homeTeamId`, ...) can be
55
+ * filtered; report columns like `seasonId` are a 400.
56
+ */
57
+ cayenneExp?: string;
58
+ }
59
+ /**
60
+ * Gets games from the stats API. At least one filter is required:
61
+ * unfiltered, the API sends every game ever played (about 19 MB).
62
+ *
63
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024
64
+ * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
65
+ * @param params.teamId NHL team id, home or away, e.g. 10
66
+ * @param params.startDate First game date, YYYY-MM-DD
67
+ * @param params.endDate Last game date, YYYY-MM-DD
68
+ * @param params.cayenneExp Extra filter expression, e.g. "homeScore>=7"
69
+ * @throws RangeError When no filter is given, or a date is not YYYY-MM-DD
70
+ * @example await client.misc.games({ season: 20232024, teamId: 10, gameType: 3 })
71
+ */
72
+ export declare function games(ctx: Context, params: GamesParams): Promise<StatsGame[]>;
73
+ /**
74
+ * Gets the national TV schedule for the week around a date, grouped by date.
75
+ *
76
+ * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
77
+ * @example https://api-web.nhle.com/v1/network/tv-schedule/2023-10-15
78
+ */
79
+ export declare function tvSchedule(ctx: Context, { date }?: {
80
+ date?: string;
81
+ }): Promise<TvSchedule>;
82
+ /**
83
+ * Gets betting odds for today's games from the NHL's odds partner in a
84
+ * country.
85
+ *
86
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
87
+ * @param params.countryCode Two-letter country code, e.g. US, CA
88
+ * @example https://api-web.nhle.com/v1/partner-game/US/now
89
+ */
90
+ export declare function partnerGameOdds(ctx: Context, { countryCode }: {
91
+ countryCode: string;
92
+ }): Promise<PartnerGameOdds>;
93
+ /**
94
+ * Gets every NHL season id, oldest first.
95
+ *
96
+ * @example https://api-web.nhle.com/v1/season
97
+ */
98
+ export declare function seasonIds(ctx: Context): Promise<SeasonId[]>;
99
+ /**
100
+ * Gets display metadata (names, headshots, logos) for players and teams.
101
+ * Lists you leave out or pass empty come back empty.
102
+ *
103
+ * @param params.players Player ids, e.g. [8478402]
104
+ * @param params.teams Team abbreviations, e.g. ['TOR', 'BUF']
105
+ * @example https://api-web.nhle.com/v1/meta?players=8478402&teams=TOR,BUF
106
+ */
107
+ export declare function meta(ctx: Context, { players, teams }?: {
108
+ players?: Id[];
109
+ teams?: string[];
110
+ }): Promise<Meta>;
111
+ /**
112
+ * Gets the caller's country, looked up from their IP address. The answer
113
+ * depends on where the request comes from.
114
+ *
115
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
116
+ * @example https://api-web.nhle.com/v1/location
117
+ */
118
+ export declare function location(ctx: Context): Promise<GeoLocation>;
119
+ /**
120
+ * Gets the teams whose local broadcast market covers a postal code. Empty
121
+ * for codes outside every market.
122
+ *
123
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
124
+ * @param params.postalCode Postal or ZIP code, e.g. 90210 or "M5V 3L9"
125
+ * @example https://api-web.nhle.com/v1/postal-lookup/90210
126
+ */
127
+ export declare function postalLookup(ctx: Context, { postalCode }: {
128
+ postalCode: string;
129
+ }): Promise<PostalLookupTeam[]>;
130
+ /**
131
+ * Checks that the stats API is up. Resolves `true` on success; it never
132
+ * resolves `false`, since any failure throws an `NHLApiException` subclass
133
+ * (or a network error).
134
+ *
135
+ * @throws ServerErrorException When the stats API answers 5xx
136
+ * @example https://api.nhle.com/stats/rest/ping
137
+ */
138
+ export declare function ping(ctx: Context): Promise<true>;
34
139
  export declare const miscApi: {
35
140
  readonly glossary: typeof glossary;
36
141
  readonly config: typeof config;
37
142
  readonly countries: typeof countries;
38
143
  readonly seasonSpecificRulesAndInfo: typeof seasonSpecificRulesAndInfo;
39
144
  readonly draftYearAndRounds: typeof draftYearAndRounds;
145
+ readonly componentSeasons: typeof componentSeasons;
146
+ readonly games: typeof games;
147
+ readonly tvSchedule: typeof tvSchedule;
148
+ readonly partnerGameOdds: typeof partnerGameOdds;
149
+ readonly seasonIds: typeof seasonIds;
150
+ readonly meta: typeof meta;
151
+ readonly location: typeof location;
152
+ readonly postalLookup: typeof postalLookup;
153
+ readonly ping: typeof ping;
40
154
  };
package/dist/api/misc.mjs CHANGED
@@ -1,43 +1,198 @@
1
+ import { andClauses, cayenneString } from '#src/api/query/cayenne.mjs';
2
+ import { normalizeDate } from '#src/api/schedule.mjs';
1
3
  import { Endpoint } from '#src/http-client.mjs';
2
- async function getData(ctx, resource) {
3
- const response = await (await ctx.get(Endpoint.API_CORE, resource)).json();
4
+ async function getData(ctx, resource, queryParams) {
5
+ const response = await (await ctx.get(Endpoint.API_CORE, resource, queryParams)).json();
4
6
  return response.data ?? [];
5
7
  }
8
+ async function getWeb(ctx, resource) {
9
+ return (await ctx.get(Endpoint.API_WEB_V1, resource)).json();
10
+ }
6
11
  /**
7
12
  * Gets the full NHL glossary of statistical terms and abbreviations.
8
13
  *
9
14
  * @example https://api.nhle.com/stats/rest/en/glossary?sort=fullName
10
15
  */
11
- export const glossary = async (ctx) => getData(ctx, 'stats/rest/en/glossary?sort=fullName');
16
+ export async function glossary(ctx) {
17
+ return getData(ctx, 'stats/rest/en/glossary?sort=fullName');
18
+ }
12
19
  /**
13
20
  * Gets the stats API configuration, including available report types and
14
21
  * filters.
15
22
  *
16
23
  * @example https://api.nhle.com/stats/rest/en/config
17
24
  */
18
- export const config = async (ctx) => (await ctx.get(Endpoint.API_CORE, 'stats/rest/en/config')).json();
25
+ export async function config(ctx) {
26
+ return (await ctx.get(Endpoint.API_CORE, 'stats/rest/en/config')).json();
27
+ }
19
28
  /**
20
29
  * Gets the list of countries recognized by the NHL.
21
30
  *
22
31
  * @example https://api.nhle.com/stats/rest/en/country
23
32
  */
24
- export const countries = async (ctx) => getData(ctx, 'stats/rest/en/country');
33
+ export async function countries(ctx) {
34
+ return getData(ctx, 'stats/rest/en/country');
35
+ }
25
36
  /**
26
37
  * Gets rules and metadata for every NHL season on record.
27
38
  *
28
39
  * @example https://api.nhle.com/stats/rest/en/season
29
40
  */
30
- export const seasonSpecificRulesAndInfo = async (ctx) => getData(ctx, 'stats/rest/en/season');
41
+ export async function seasonSpecificRulesAndInfo(ctx) {
42
+ return getData(ctx, 'stats/rest/en/season');
43
+ }
31
44
  /**
32
45
  * Gets the number of rounds for each NHL draft year.
33
46
  *
34
47
  * @example https://api.nhle.com/stats/rest/en/draft
35
48
  */
36
- export const draftYearAndRounds = async (ctx) => getData(ctx, 'stats/rest/en/draft');
49
+ export async function draftYearAndRounds(ctx) {
50
+ return getData(ctx, 'stats/rest/en/draft');
51
+ }
52
+ /**
53
+ * Gets the season and game type the stats API currently serves by default.
54
+ *
55
+ * @example https://api.nhle.com/stats/rest/en/componentSeason
56
+ */
57
+ export async function componentSeasons(ctx) {
58
+ return getData(ctx, 'stats/rest/en/componentSeason');
59
+ }
60
+ function gamesClauses({ season, gameType, teamId, startDate, endDate, cayenneExp, }) {
61
+ const clauses = [];
62
+ if (season !== undefined && season !== null) {
63
+ clauses.push(`season=${season}`);
64
+ }
65
+ if (gameType !== undefined) {
66
+ clauses.push(`gameType=${gameType}`);
67
+ }
68
+ if (teamId !== undefined && teamId !== null) {
69
+ clauses.push(`homeTeamId=${teamId} or visitingTeamId=${teamId}`);
70
+ }
71
+ if (startDate !== undefined) {
72
+ clauses.push(`gameDate>=${cayenneString(normalizeDate(startDate))}`);
73
+ }
74
+ if (endDate !== undefined) {
75
+ clauses.push(`gameDate<=${cayenneString(normalizeDate(endDate))}`);
76
+ }
77
+ if (cayenneExp?.trim()) {
78
+ clauses.push(cayenneExp);
79
+ }
80
+ return clauses;
81
+ }
82
+ /**
83
+ * Gets games from the stats API. At least one filter is required:
84
+ * unfiltered, the API sends every game ever played (about 19 MB).
85
+ *
86
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024
87
+ * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
88
+ * @param params.teamId NHL team id, home or away, e.g. 10
89
+ * @param params.startDate First game date, YYYY-MM-DD
90
+ * @param params.endDate Last game date, YYYY-MM-DD
91
+ * @param params.cayenneExp Extra filter expression, e.g. "homeScore>=7"
92
+ * @throws RangeError When no filter is given, or a date is not YYYY-MM-DD
93
+ * @example await client.misc.games({ season: 20232024, teamId: 10, gameType: 3 })
94
+ */
95
+ export async function games(ctx, params) {
96
+ const clauses = gamesClauses(params);
97
+ if (clauses.length === 0) {
98
+ throw new RangeError('Missing filter. Pass season, gameType, teamId, a date or cayenneExp.');
99
+ }
100
+ return getData(ctx, 'stats/rest/en/game', {
101
+ cayenneExp: andClauses(clauses),
102
+ });
103
+ }
104
+ /**
105
+ * Gets the national TV schedule for the week around a date, grouped by date.
106
+ *
107
+ * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
108
+ * @example https://api-web.nhle.com/v1/network/tv-schedule/2023-10-15
109
+ */
110
+ export async function tvSchedule(ctx, { date } = {}) {
111
+ return getWeb(ctx, `network/tv-schedule/${date ?? 'now'}`);
112
+ }
113
+ /**
114
+ * Gets betting odds for today's games from the NHL's odds partner in a
115
+ * country.
116
+ *
117
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
118
+ * @param params.countryCode Two-letter country code, e.g. US, CA
119
+ * @example https://api-web.nhle.com/v1/partner-game/US/now
120
+ */
121
+ export async function partnerGameOdds(ctx, { countryCode }) {
122
+ return getWeb(ctx, `partner-game/${countryCode}/now`);
123
+ }
124
+ /**
125
+ * Gets every NHL season id, oldest first.
126
+ *
127
+ * @example https://api-web.nhle.com/v1/season
128
+ */
129
+ export async function seasonIds(ctx) {
130
+ return getWeb(ctx, 'season');
131
+ }
132
+ /**
133
+ * Gets display metadata (names, headshots, logos) for players and teams.
134
+ * Lists you leave out or pass empty come back empty.
135
+ *
136
+ * @param params.players Player ids, e.g. [8478402]
137
+ * @param params.teams Team abbreviations, e.g. ['TOR', 'BUF']
138
+ * @example https://api-web.nhle.com/v1/meta?players=8478402&teams=TOR,BUF
139
+ */
140
+ export async function meta(ctx, { players = [], teams = [] } = {}) {
141
+ const query = {};
142
+ if (players.length > 0) {
143
+ query.players = players.join(',');
144
+ }
145
+ if (teams.length > 0) {
146
+ query.teams = teams.join(',');
147
+ }
148
+ return (await ctx.get(Endpoint.API_WEB_V1, 'meta', query)).json();
149
+ }
150
+ /**
151
+ * Gets the caller's country, looked up from their IP address. The answer
152
+ * depends on where the request comes from.
153
+ *
154
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
155
+ * @example https://api-web.nhle.com/v1/location
156
+ */
157
+ export async function location(ctx) {
158
+ return getWeb(ctx, 'location');
159
+ }
160
+ /**
161
+ * Gets the teams whose local broadcast market covers a postal code. Empty
162
+ * for codes outside every market.
163
+ *
164
+ * @experimental Feeds an nhl.com widget; the shape may change without notice.
165
+ * @param params.postalCode Postal or ZIP code, e.g. 90210 or "M5V 3L9"
166
+ * @example https://api-web.nhle.com/v1/postal-lookup/90210
167
+ */
168
+ export async function postalLookup(ctx, { postalCode }) {
169
+ return getWeb(ctx, `postal-lookup/${encodeURIComponent(postalCode)}`);
170
+ }
171
+ /**
172
+ * Checks that the stats API is up. Resolves `true` on success; it never
173
+ * resolves `false`, since any failure throws an `NHLApiException` subclass
174
+ * (or a network error).
175
+ *
176
+ * @throws ServerErrorException When the stats API answers 5xx
177
+ * @example https://api.nhle.com/stats/rest/ping
178
+ */
179
+ export async function ping(ctx) {
180
+ await ctx.get(Endpoint.API_CORE, 'stats/rest/ping');
181
+ return true;
182
+ }
37
183
  export const miscApi = {
38
184
  glossary,
39
185
  config,
40
186
  countries,
41
187
  seasonSpecificRulesAndInfo,
42
188
  draftYearAndRounds,
189
+ componentSeasons,
190
+ games,
191
+ tvSchedule,
192
+ partnerGameOdds,
193
+ seasonIds,
194
+ meta,
195
+ location,
196
+ postalLookup,
197
+ ping,
43
198
  };
@@ -1,5 +1,6 @@
1
+ import { type PositionTypes } from '#src/api/query/filters.mjs';
1
2
  import type { Context } from '#src/context.mjs';
2
- import type { Prospects, Roster } from '#src/types/index.mjs';
3
+ import type { PlayerSpotlight, Prospects, Roster, StatsApiPage, StatsPlayer } from '#src/types/index.mjs';
3
4
  import type { Id } from '#src/utils.mjs';
4
5
  /**
5
6
  * Gets prospects for a specific team, grouped by position.
@@ -7,22 +8,73 @@ import type { Id } from '#src/utils.mjs';
7
8
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
8
9
  * @example https://api-web.nhle.com/v1/prospects/BUF
9
10
  */
10
- export declare const prospectsByTeam: (ctx: Context, { teamAbbr }: {
11
+ export declare function prospectsByTeam(ctx: Context, { teamAbbr }: {
11
12
  teamAbbr: string;
12
- }) => Promise<Prospects>;
13
+ }): Promise<Prospects>;
13
14
  /**
14
15
  * Gets the roster for a given team and season, grouped by position
15
16
  * (forwards, defensemen, goalies). Same data as `teams.teamRoster`.
16
17
  *
17
18
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
18
- * @param params.season Season in YYYYYYYY format, e.g. 20232024
19
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to
20
+ * the current season (`current`; this endpoint has no `now` alias).
19
21
  * @example https://api-web.nhle.com/v1/roster/BUF/20232024
20
22
  */
21
- export declare const playersByTeam: (ctx: Context, { teamAbbr, season }: {
23
+ export declare function playersByTeam(ctx: Context, { teamAbbr, season }: {
22
24
  teamAbbr: string;
23
- season: Id;
24
- }) => Promise<Roster>;
25
+ season?: Id;
26
+ }): Promise<Roster>;
27
+ /**
28
+ * Gets the players featured in the nhl.com player spotlight.
29
+ *
30
+ * @example https://api-web.nhle.com/v1/player-spotlight
31
+ */
32
+ export declare function playerSpotlight(ctx: Context): Promise<PlayerSpotlight[]>;
33
+ export interface PlayerSearchParams {
34
+ /** Case-insensitive part of the full name, e.g. "matth" or "Ryan O'Reilly". */
35
+ name?: string;
36
+ /** NHL team id of the player's current team, e.g. 10. */
37
+ teamId?: Id;
38
+ /** Position. `F` matches every forward (C, L, R). */
39
+ position?: PositionTypes | 'G';
40
+ /**
41
+ * Extra filter expression, joined to the others with `and`. Only the row
42
+ * fields (`id`, `firstName`, `lastName`, `fullName`, `currentTeamId`,
43
+ * `positionCode`, `sweaterNumber`) can be filtered; anything else is a 400.
44
+ */
45
+ cayenneExp?: string;
46
+ /** Field to sort by, e.g. "lastName". */
47
+ sort?: string;
48
+ /** Sort direction for `sort`. */
49
+ dir?: 'ASC' | 'DESC';
50
+ /** Pagination offset. The API returns at most 5 rows per request. */
51
+ start?: number;
52
+ /** Only return these fields. Rows then hold just these keys. */
53
+ include?: readonly string[];
54
+ /** Leave out these fields. */
55
+ exclude?: readonly string[];
56
+ }
57
+ /**
58
+ * Searches every player on record, past and present. Returns the full page
59
+ * (`{ data, total }`): the API sends **at most 5 rows** per request, whatever
60
+ * the limit, so page with `start` until you have `total` rows.
61
+ *
62
+ * @param params.name Case-insensitive part of the full name, e.g. "matth"
63
+ * @param params.teamId NHL team id of the current team, e.g. 10
64
+ * @param params.position C, L, R, D, G, or F for every forward
65
+ * @param params.cayenneExp Extra filter expression, e.g. "sweaterNumber=34"
66
+ * @param params.sort Field to sort by, e.g. "lastName"
67
+ * @param params.dir ASC or DESC
68
+ * @param params.start Pagination offset
69
+ * @param params.include Only return these fields, e.g. ['id', 'fullName']
70
+ * @param params.exclude Leave out these fields
71
+ * @throws RangeError When no filter is given (the API would return no rows)
72
+ * @example await client.players.playerSearch({ name: 'matthews', position: 'C' })
73
+ */
74
+ export declare function playerSearch(ctx: Context, params: PlayerSearchParams): Promise<StatsApiPage<StatsPlayer>>;
25
75
  export declare const playersApi: {
26
76
  readonly prospectsByTeam: typeof prospectsByTeam;
27
77
  readonly playersByTeam: typeof playersByTeam;
78
+ readonly playerSpotlight: typeof playerSpotlight;
79
+ readonly playerSearch: typeof playerSearch;
28
80
  };