nhl-api-ts 0.2.1 → 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 (40) hide show
  1. package/README.md +72 -5
  2. package/dist/api/draft.d.mts +61 -0
  3. package/dist/api/draft.mjs +68 -0
  4. package/dist/api/edge.d.mts +198 -1
  5. package/dist/api/edge.mjs +207 -4
  6. package/dist/api/game-center.d.mts +49 -1
  7. package/dist/api/game-center.mjs +47 -0
  8. package/dist/api/misc.d.mts +115 -1
  9. package/dist/api/misc.mjs +147 -2
  10. package/dist/api/players.d.mts +55 -3
  11. package/dist/api/players.mjs +80 -3
  12. package/dist/api/query/cayenne.d.mts +4 -0
  13. package/dist/api/query/cayenne.mjs +13 -0
  14. package/dist/api/query/sorting/sorting-options.d.mts +8 -0
  15. package/dist/api/query/sorting/sorting-options.mjs +30 -0
  16. package/dist/api/schedule.d.mts +19 -6
  17. package/dist/api/schedule.mjs +17 -5
  18. package/dist/api/stats.d.mts +95 -6
  19. package/dist/api/stats.mjs +130 -30
  20. package/dist/api/teams.d.mts +43 -3
  21. package/dist/api/teams.mjs +51 -3
  22. package/dist/cli/commands.mjs +487 -22
  23. package/dist/http-client.d.mts +2 -1
  24. package/dist/http-client.mjs +8 -1
  25. package/dist/index.d.mts +8 -2
  26. package/dist/index.mjs +3 -0
  27. package/dist/nhl-client.d.mts +69 -14
  28. package/dist/nhl-client.mjs +33 -12
  29. package/dist/types/draft.d.mts +97 -0
  30. package/dist/types/draft.mjs +1 -0
  31. package/dist/types/edge.d.mts +299 -3
  32. package/dist/types/game-center.d.mts +223 -8
  33. package/dist/types/index.d.mts +1 -0
  34. package/dist/types/misc.d.mts +101 -0
  35. package/dist/types/misc.mjs +0 -1
  36. package/dist/types/players.d.mts +22 -0
  37. package/dist/types/schedule.d.mts +16 -0
  38. package/dist/types/stats.d.mts +207 -1
  39. package/dist/types/teams.d.mts +29 -1
  40. package/package.json +1 -1
@@ -1,7 +1,17 @@
1
1
  import { DEFAULT_FACT_QUERY, } from '#src/api/query/builder.mjs';
2
2
  import { goalieStatsSorts } from '#src/api/query/sorting/goalie-sorts.mjs';
3
- import { defaultSortForReport, } from '#src/api/query/sorting/sorting-options.mjs';
3
+ import { defaultSortForReport, defaultSortForSkaterStatsSummary, defaultSortForTeamSummary, } from '#src/api/query/sorting/sorting-options.mjs';
4
4
  import { Endpoint } from '#src/http-client.mjs';
5
+ /**
6
+ * "<season>/<gameType>", or the API's current-season segment when no season is
7
+ * given. Most endpoints take `now`; the stats-leaders ones only take `current`.
8
+ */
9
+ function seasonGameTypeSegments(season, gameType, current) {
10
+ if (season === undefined || season === null) {
11
+ return current;
12
+ }
13
+ return `${season}/${gameType}`;
14
+ }
5
15
  /** Skater reports whose rows have no `gamesPlayed`, so the API rejects the default fact filter. */
6
16
  const REPORTS_WITHOUT_GAMES_PLAYED = [
7
17
  'shootout',
@@ -26,37 +36,72 @@ export async function playerCareerStats(ctx, { playerId }) {
26
36
  return (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/landing`)).json();
27
37
  }
28
38
  /**
29
- * Gets a player's game log for a specific season and game type.
39
+ * Gets a player's game log for a season and game type.
30
40
  *
31
41
  * @param params.playerId NHL player id, e.g. 8481528
32
- * @param params.seasonId Season in YYYYYYYY format, e.g. 20232024
33
- * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
42
+ * @param params.seasonId Season in YYYYYYYY format, e.g. 20232024. Defaults to the current season ("now").
43
+ * @param params.gameType 1=Preseason, 2=Regular season (default), 3=Playoffs. Ignored when `seasonId` is omitted.
34
44
  * @example https://api-web.nhle.com/v1/player/8481528/game-log/20232024/2
35
45
  */
36
- export async function playerGameLog(ctx, { playerId, seasonId, gameType, }) {
37
- const data = await (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/game-log/${seasonId}/${gameType}`)).json();
46
+ export async function playerGameLog(ctx, { playerId, seasonId, gameType = 2, }) {
47
+ const data = await (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/game-log/${seasonGameTypeSegments(seasonId, gameType, 'now')}`)).json();
38
48
  return data.gameLog ?? [];
39
49
  }
50
+ function statsLeadersQuery({ categories, limit, }) {
51
+ const query = {};
52
+ if (categories && categories.length > 0) {
53
+ query.categories = categories.join(',');
54
+ }
55
+ if (limit !== undefined) {
56
+ query.limit = limit;
57
+ }
58
+ return query;
59
+ }
60
+ /**
61
+ * Gets the skater stats leaders for a season, keyed by category.
62
+ *
63
+ * @param params.season Season in YYYYYYYY format. Defaults to the current season.
64
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
65
+ * @param params.categories Categories to include, e.g. ['goals', 'points']. Defaults to all.
66
+ * @param params.limit Rows per category. The API defaults to 5; -1 returns every player.
67
+ * @example https://api-web.nhle.com/v1/skater-stats-leaders/20232024/2?categories=goals,points&limit=10
68
+ */
69
+ export async function skaterStatsLeaders(ctx, params = {}) {
70
+ return (await ctx.get(Endpoint.API_WEB_V1, `skater-stats-leaders/${seasonGameTypeSegments(params.season, params.gameType ?? 2, 'current')}`, statsLeadersQuery(params))).json();
71
+ }
72
+ /**
73
+ * Gets the goalie stats leaders for a season, keyed by category.
74
+ *
75
+ * @param params.season Season in YYYYYYYY format. Defaults to the current season.
76
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
77
+ * @param params.categories Categories to include, e.g. ['wins', 'savePctg']. Defaults to all.
78
+ * @param params.limit Rows per category. The API defaults to 5; -1 returns every goalie.
79
+ * @example https://api-web.nhle.com/v1/goalie-stats-leaders/20232024/2?categories=wins&limit=10
80
+ */
81
+ export async function goalieStatsLeaders(ctx, params = {}) {
82
+ return (await ctx.get(Endpoint.API_WEB_V1, `goalie-stats-leaders/${seasonGameTypeSegments(params.season, params.gameType ?? 2, 'current')}`, statsLeadersQuery(params))).json();
83
+ }
84
+ /**
85
+ * Gets a team's skater and goalie stats for a season and game type.
86
+ *
87
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
88
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to the current season ("now").
89
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
90
+ * @example https://api-web.nhle.com/v1/club-stats/TOR/20232024/2
91
+ */
92
+ export async function clubStats(ctx, { teamAbbr, season, gameType = 2, }) {
93
+ return (await ctx.get(Endpoint.API_WEB_V1, `club-stats/${teamAbbr}/${seasonGameTypeSegments(season, gameType, 'now')}`)).json();
94
+ }
40
95
  /**
41
96
  * Retrieves team summary statistics across one or more seasons.
42
97
  *
43
98
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
44
99
  */
45
100
  export async function teamSummary(ctx, { startSeason, endSeason, gameTypeId = 2, isGame = false, isAggregate = false, sortExpr, start = 0, limit = 50, factCayenneExp = 'gamesPlayed>1', defaultCayenneExp, }) {
46
- const effectiveSortExpr = sortExpr && sortExpr.length > 0
47
- ? sortExpr
48
- : [
49
- { property: 'points', direction: 'DESC' },
50
- { property: 'wins', direction: 'DESC' },
51
- // aggregated rows span seasons, so they have no teamId
52
- {
53
- property: isAggregate ? 'franchiseId' : 'teamId',
54
- direction: 'ASC',
55
- },
56
- ];
101
+ const effectiveSortExpr = defaultSortForTeamSummary(sortExpr, isAggregate);
57
102
  const effectiveCayenneExp = defaultCayenneExp ??
58
103
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
59
- const qParams = {
104
+ const queryParams = {
60
105
  isAggregate,
61
106
  isGame,
62
107
  start,
@@ -65,7 +110,7 @@ export async function teamSummary(ctx, { startSeason, endSeason, gameTypeId = 2,
65
110
  sort: JSON.stringify(effectiveSortExpr),
66
111
  cayenneExp: effectiveCayenneExp,
67
112
  };
68
- const response = await (await ctx.get(Endpoint.API_STATS, 'en/team/summary', qParams)).json();
113
+ const response = await (await ctx.get(Endpoint.API_STATS, 'en/team/summary', queryParams)).json();
69
114
  return response.data;
70
115
  }
71
116
  /**
@@ -75,19 +120,13 @@ export async function teamSummary(ctx, { startSeason, endSeason, gameTypeId = 2,
75
120
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
76
121
  */
77
122
  export async function skaterStatsSummary(ctx, { startSeason, endSeason, franchiseId, gameTypeId = 2, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp = 'gamesPlayed>=1', defaultCayenneExp, }) {
78
- const effectiveSortExpr = sortExpr && sortExpr.length > 0
79
- ? sortExpr
80
- : [
81
- { property: 'points', direction: 'DESC' },
82
- { property: 'gamesPlayed', direction: 'ASC' },
83
- { property: 'playerId', direction: 'ASC' },
84
- ];
123
+ const effectiveSortExpr = defaultSortForSkaterStatsSummary(sortExpr);
85
124
  const baseCayenneExp = defaultCayenneExp ??
86
125
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
87
126
  const effectiveCayenneExp = !defaultCayenneExp && franchiseId
88
127
  ? `franchiseId=${franchiseId} and ${baseCayenneExp}`
89
128
  : baseCayenneExp;
90
- const qParams = {
129
+ const queryParams = {
91
130
  isAggregate: aggregate,
92
131
  isGame: false,
93
132
  start,
@@ -96,7 +135,7 @@ export async function skaterStatsSummary(ctx, { startSeason, endSeason, franchis
96
135
  sort: JSON.stringify(effectiveSortExpr),
97
136
  cayenneExp: effectiveCayenneExp,
98
137
  };
99
- const response = await (await ctx.get(Endpoint.API_STATS, 'en/skater/summary', qParams)).json();
138
+ const response = await (await ctx.get(Endpoint.API_STATS, 'en/skater/summary', queryParams)).json();
100
139
  return response.data;
101
140
  }
102
141
  /**
@@ -147,7 +186,7 @@ export async function goalieStatsSummary(ctx, { startSeason, endSeason, statsTyp
147
186
  const effectiveCayenneExp = franchiseId
148
187
  ? `franchiseId=${franchiseId} and ${baseCayenneExp}`
149
188
  : baseCayenneExp;
150
- const qParams = {
189
+ const queryParams = {
151
190
  isAggregate: aggregate,
152
191
  isGame: false,
153
192
  start,
@@ -156,15 +195,76 @@ export async function goalieStatsSummary(ctx, { startSeason, endSeason, statsTyp
156
195
  sort: JSON.stringify(effectiveSortExpr),
157
196
  cayenneExp: effectiveCayenneExp,
158
197
  };
159
- const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${report}`, qParams)).json();
198
+ const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${report}`, queryParams)).json();
199
+ return response.data ?? [];
200
+ }
201
+ async function getStatsData(ctx, resource, queryParams) {
202
+ const response = await (await ctx.get(Endpoint.API_STATS, resource, queryParams)).json();
160
203
  return response.data ?? [];
161
204
  }
205
+ /**
206
+ * The leaders endpoints only filter on `season` (`seasonId`, `gameTypeId` and
207
+ * the other report columns are a 400), so the SDK builds the filter itself.
208
+ */
209
+ function getStatsLeaders(ctx, group, { attribute, season }) {
210
+ return getStatsData(ctx, `en/leaders/${group}/${attribute}`, season === undefined || season === null
211
+ ? undefined
212
+ : { cayenneExp: `season=${season}` });
213
+ }
214
+ /**
215
+ * Gets the top 10 single-season skater records for an attribute, e.g.
216
+ * Gretzky's 215 points, or the top 10 of one season.
217
+ *
218
+ * @param params.attribute points, goals, assists or gamesPlayed (case-sensitive)
219
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to every season.
220
+ * @example https://api.nhle.com/stats/rest/en/leaders/skaters/points?cayenneExp=season=20232024
221
+ */
222
+ export async function skaterLeaders(ctx, params) {
223
+ return getStatsLeaders(ctx, 'skaters', params);
224
+ }
225
+ /**
226
+ * Gets the top 10 single-season goalie records for an attribute, or the top
227
+ * 10 of one season. There is no minimum games played, so `gaa` / `savePctg`
228
+ * leaders are goalies with a few minutes.
229
+ *
230
+ * @param params.attribute gaa, savePctg, shutouts, timeOnIce or gamesPlayed (case-sensitive)
231
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to every season.
232
+ * @example https://api.nhle.com/stats/rest/en/leaders/goalies/gaa?cayenneExp=season=20232024
233
+ */
234
+ export async function goalieLeaders(ctx, params) {
235
+ return getStatsLeaders(ctx, 'goalies', params);
236
+ }
237
+ /**
238
+ * Gets the career milestones active skaters are closing in on (e.g. 200
239
+ * assists, 50 playoff points).
240
+ *
241
+ * @example https://api.nhle.com/stats/rest/en/milestones/skaters
242
+ */
243
+ export async function skaterMilestones(ctx) {
244
+ return getStatsData(ctx, 'en/milestones/skaters');
245
+ }
246
+ /**
247
+ * Gets the career milestones active goalies are closing in on (e.g. 30
248
+ * shutouts, 50 playoff games).
249
+ *
250
+ * @example https://api.nhle.com/stats/rest/en/milestones/goalies
251
+ */
252
+ export async function goalieMilestones(ctx) {
253
+ return getStatsData(ctx, 'en/milestones/goalies');
254
+ }
162
255
  export const statsApi = {
163
256
  gametypesPerSeasonDirectoryByTeam,
164
257
  playerCareerStats,
165
258
  playerGameLog,
259
+ skaterStatsLeaders,
260
+ goalieStatsLeaders,
261
+ clubStats,
166
262
  teamSummary,
167
263
  skaterStatsSummary,
168
264
  skaterStatsWithQueryContext,
169
265
  goalieStatsSummary,
266
+ skaterLeaders,
267
+ goalieLeaders,
268
+ skaterMilestones,
269
+ goalieMilestones,
170
270
  };
@@ -1,5 +1,5 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Franchise, Roster, StandingsEntry } from '#src/types/index.mjs';
2
+ import type { Franchise, Roster, SeasonId, StandingsEntry, StatsTeam, TeamScoreboard } from '#src/types/index.mjs';
3
3
  import type { Id } from '#src/utils.mjs';
4
4
  export interface Team {
5
5
  conference: {
@@ -39,21 +39,61 @@ export declare function teams(ctx: Context, { date }?: {
39
39
  * Get the roster for the given team and season.
40
40
  *
41
41
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
42
- * @param params.season Season in YYYYYYYY format, e.g. 20232024
42
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to
43
+ * the current season (`current`; this endpoint has no `now` alias).
43
44
  * @example https://api-web.nhle.com/v1/roster/BUF/20232024
44
45
  */
45
46
  export declare function teamRoster(ctx: Context, { teamAbbr, season }: {
46
47
  teamAbbr: string;
47
- season: Id;
48
+ season?: Id;
48
49
  }): Promise<Roster>;
50
+ /**
51
+ * Get every season a team has a roster for.
52
+ *
53
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
54
+ * @example https://api-web.nhle.com/v1/roster-season/TOR
55
+ */
56
+ export declare function rosterSeasons(ctx: Context, { teamAbbr }: {
57
+ teamAbbr: string;
58
+ }): Promise<SeasonId[]>;
59
+ /**
60
+ * Get a team's recent and upcoming games, grouped by date.
61
+ *
62
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
63
+ * @example https://api-web.nhle.com/v1/scoreboard/TOR/now
64
+ */
65
+ export declare function teamScoreboard(ctx: Context, { teamAbbr }: {
66
+ teamAbbr: string;
67
+ }): Promise<TeamScoreboard>;
49
68
  /**
50
69
  * Get a list of all past and current NHL franchises.
51
70
  *
52
71
  * @example https://api.nhle.com/stats/rest/en/franchise
53
72
  */
54
73
  export declare function franchises(ctx: Context): Promise<Franchise[]>;
74
+ /**
75
+ * Get every team in the stats API, past and present (62 rows), with its
76
+ * franchise id and tricode. Unlike `teams()`, this is the raw stats API row.
77
+ *
78
+ * @example https://api.nhle.com/stats/rest/en/team
79
+ */
80
+ export declare function statsTeams(ctx: Context): Promise<StatsTeam[]>;
81
+ /**
82
+ * Get one team from the stats API by its team id. An unknown id throws
83
+ * `ResourceNotFoundException`.
84
+ *
85
+ * @param params.teamId NHL team id, e.g. 10
86
+ * @example https://api.nhle.com/stats/rest/en/team/id/10
87
+ */
88
+ export declare function teamById(ctx: Context, { teamId }: {
89
+ teamId: Id;
90
+ }): Promise<StatsTeam>;
55
91
  export declare const teamsApi: {
56
92
  readonly teams: typeof teams;
57
93
  readonly teamRoster: typeof teamRoster;
94
+ readonly rosterSeasons: typeof rosterSeasons;
95
+ readonly teamScoreboard: typeof teamScoreboard;
58
96
  readonly franchises: typeof franchises;
97
+ readonly statsTeams: typeof statsTeams;
98
+ readonly teamById: typeof teamById;
59
99
  };
@@ -77,11 +77,30 @@ export async function teams(ctx, { date = 'now' } = {}) {
77
77
  * Get the roster for the given team and season.
78
78
  *
79
79
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
80
- * @param params.season Season in YYYYYYYY format, e.g. 20232024
80
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to
81
+ * the current season (`current`; this endpoint has no `now` alias).
81
82
  * @example https://api-web.nhle.com/v1/roster/BUF/20232024
82
83
  */
83
84
  export async function teamRoster(ctx, { teamAbbr, season }) {
84
- return (await ctx.get(Endpoint.API_WEB_V1, `roster/${teamAbbr}/${season}`)).json();
85
+ return (await ctx.get(Endpoint.API_WEB_V1, `roster/${teamAbbr}/${season ?? 'current'}`)).json();
86
+ }
87
+ /**
88
+ * Get every season a team has a roster for.
89
+ *
90
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
91
+ * @example https://api-web.nhle.com/v1/roster-season/TOR
92
+ */
93
+ export async function rosterSeasons(ctx, { teamAbbr }) {
94
+ return (await ctx.get(Endpoint.API_WEB_V1, `roster-season/${teamAbbr}`)).json();
95
+ }
96
+ /**
97
+ * Get a team's recent and upcoming games, grouped by date.
98
+ *
99
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
100
+ * @example https://api-web.nhle.com/v1/scoreboard/TOR/now
101
+ */
102
+ export async function teamScoreboard(ctx, { teamAbbr }) {
103
+ return (await ctx.get(Endpoint.API_WEB_V1, `scoreboard/${teamAbbr}/now`)).json();
85
104
  }
86
105
  /**
87
106
  * Get a list of all past and current NHL franchises.
@@ -92,4 +111,33 @@ export async function franchises(ctx) {
92
111
  const response = await (await ctx.get(Endpoint.API_STATS, 'en/franchise')).json();
93
112
  return response.data ?? [];
94
113
  }
95
- export const teamsApi = { teams, teamRoster, franchises };
114
+ /**
115
+ * Get every team in the stats API, past and present (62 rows), with its
116
+ * franchise id and tricode. Unlike `teams()`, this is the raw stats API row.
117
+ *
118
+ * @example https://api.nhle.com/stats/rest/en/team
119
+ */
120
+ export async function statsTeams(ctx) {
121
+ const response = await (await ctx.get(Endpoint.API_STATS, 'en/team')).json();
122
+ return response.data ?? [];
123
+ }
124
+ /**
125
+ * Get one team from the stats API by its team id. An unknown id throws
126
+ * `ResourceNotFoundException`.
127
+ *
128
+ * @param params.teamId NHL team id, e.g. 10
129
+ * @example https://api.nhle.com/stats/rest/en/team/id/10
130
+ */
131
+ export async function teamById(ctx, { teamId }) {
132
+ const response = await (await ctx.get(Endpoint.API_STATS, `en/team/id/${teamId}`)).json();
133
+ return response.data[0];
134
+ }
135
+ export const teamsApi = {
136
+ teams,
137
+ teamRoster,
138
+ rosterSeasons,
139
+ teamScoreboard,
140
+ franchises,
141
+ statsTeams,
142
+ teamById,
143
+ };