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
@@ -1,7 +1,7 @@
1
1
  import { type QueryContext } from '#src/api/query/builder.mjs';
2
2
  import { type SortExpr } from '#src/api/query/sorting/sorting-options.mjs';
3
3
  import type { Context } from '#src/context.mjs';
4
- import type { ClubStatsSeason, GameLogEntry, GoalieReportRows, PlayerLanding, SkaterReportRows, StatsApiPage, TeamSummaryRow } from '#src/types/index.mjs';
4
+ import type { ClubStats, ClubStatsSeason, GameLogEntry, GoalieLeaderCategory, GoalieLeaderRows, GoalieMilestone, GoalieReportRows, GoalieStatsLeaders, OpenUnion, PlayerLanding, SkaterLeaderCategory, SkaterLeaderRows, SkaterMilestone, SkaterReportRows, SkaterStatsLeaders, StatsApiPage, TeamSummaryRow } from '#src/types/index.mjs';
5
5
  import type { Id } from '#src/utils.mjs';
6
6
  export interface TeamSummaryParams {
7
7
  /** Start season in YYYYYYYY format, e.g. 20202021 */
@@ -81,44 +81,87 @@ export interface GoalieStatsSummaryParams<Report extends keyof GoalieReportRows
81
81
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
82
82
  * @example https://api-web.nhle.com/v1/club-stats-season/TOR
83
83
  */
84
- export declare const gametypesPerSeasonDirectoryByTeam: (ctx: Context, { teamAbbr }: {
84
+ export declare function gametypesPerSeasonDirectoryByTeam(ctx: Context, { teamAbbr }: {
85
85
  teamAbbr: string;
86
- }) => Promise<ClubStatsSeason[]>;
86
+ }): Promise<ClubStatsSeason[]>;
87
87
  /**
88
88
  * Gets a player's career statistics and biographical information.
89
89
  *
90
90
  * @param params.playerId NHL player id, e.g. 8481528
91
91
  * @example https://api-web.nhle.com/v1/player/8481528/landing
92
92
  */
93
- export declare const playerCareerStats: (ctx: Context, { playerId }: {
93
+ export declare function playerCareerStats(ctx: Context, { playerId }: {
94
94
  playerId: Id;
95
- }) => Promise<PlayerLanding>;
95
+ }): Promise<PlayerLanding>;
96
96
  /**
97
- * Gets a player's game log for a specific season and game type.
97
+ * Gets a player's game log for a season and game type.
98
98
  *
99
99
  * @param params.playerId NHL player id, e.g. 8481528
100
- * @param params.seasonId Season in YYYYYYYY format, e.g. 20232024
101
- * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
100
+ * @param params.seasonId Season in YYYYYYYY format, e.g. 20232024. Defaults to the current season ("now").
101
+ * @param params.gameType 1=Preseason, 2=Regular season (default), 3=Playoffs. Ignored when `seasonId` is omitted.
102
102
  * @example https://api-web.nhle.com/v1/player/8481528/game-log/20232024/2
103
103
  */
104
- export declare const playerGameLog: (ctx: Context, { playerId, seasonId, gameType, }: {
104
+ export declare function playerGameLog(ctx: Context, { playerId, seasonId, gameType, }: {
105
105
  playerId: Id;
106
- seasonId: Id;
107
- gameType: number;
108
- }) => Promise<GameLogEntry[]>;
106
+ seasonId?: Id;
107
+ gameType?: number;
108
+ }): Promise<GameLogEntry[]>;
109
+ export interface StatsLeadersParams<Category extends string> {
110
+ /** Season in YYYYYYYY format, e.g. 20232024. Defaults to the current season ("current"). */
111
+ season?: Id;
112
+ /** 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted. */
113
+ gameType?: number;
114
+ /** Categories to include. Defaults to every category. An unknown category is a 400. */
115
+ categories?: readonly Category[];
116
+ /** Rows per category. The API defaults to 5; -1 returns every player. */
117
+ limit?: number;
118
+ }
119
+ /**
120
+ * Gets the skater stats leaders for a season, keyed by category.
121
+ *
122
+ * @param params.season Season in YYYYYYYY format. Defaults to the current season.
123
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
124
+ * @param params.categories Categories to include, e.g. ['goals', 'points']. Defaults to all.
125
+ * @param params.limit Rows per category. The API defaults to 5; -1 returns every player.
126
+ * @example https://api-web.nhle.com/v1/skater-stats-leaders/20232024/2?categories=goals,points&limit=10
127
+ */
128
+ export declare function skaterStatsLeaders(ctx: Context, params?: StatsLeadersParams<OpenUnion<SkaterLeaderCategory>>): Promise<SkaterStatsLeaders>;
129
+ /**
130
+ * Gets the goalie stats leaders for a season, keyed by category.
131
+ *
132
+ * @param params.season Season in YYYYYYYY format. Defaults to the current season.
133
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
134
+ * @param params.categories Categories to include, e.g. ['wins', 'savePctg']. Defaults to all.
135
+ * @param params.limit Rows per category. The API defaults to 5; -1 returns every goalie.
136
+ * @example https://api-web.nhle.com/v1/goalie-stats-leaders/20232024/2?categories=wins&limit=10
137
+ */
138
+ export declare function goalieStatsLeaders(ctx: Context, params?: StatsLeadersParams<OpenUnion<GoalieLeaderCategory>>): Promise<GoalieStatsLeaders>;
139
+ /**
140
+ * Gets a team's skater and goalie stats for a season and game type.
141
+ *
142
+ * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
143
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to the current season ("now").
144
+ * @param params.gameType 2=Regular season (default), 3=Playoffs. Ignored when `season` is omitted.
145
+ * @example https://api-web.nhle.com/v1/club-stats/TOR/20232024/2
146
+ */
147
+ export declare function clubStats(ctx: Context, { teamAbbr, season, gameType, }: {
148
+ teamAbbr: string;
149
+ season?: Id;
150
+ gameType?: number;
151
+ }): Promise<ClubStats>;
109
152
  /**
110
153
  * Retrieves team summary statistics across one or more seasons.
111
154
  *
112
155
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
113
156
  */
114
- export declare const teamSummary: (ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams) => Promise<TeamSummaryRow[]>;
157
+ export declare function teamSummary(ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams): Promise<TeamSummaryRow[]>;
115
158
  /**
116
159
  * Gets simplified skater statistics summary for specified seasons and
117
160
  * franchises.
118
161
  *
119
162
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
120
163
  */
121
- export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams) => Promise<SkaterReportRows['summary'][]>;
164
+ export declare function skaterStatsSummary(ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams): Promise<SkaterReportRows['summary'][]>;
122
165
  /**
123
166
  * Retrieves skater statistics using a query context and specified report
124
167
  * type. Returns the full response (`{ data, total }`).
@@ -134,20 +177,66 @@ export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason
134
177
  * ]);
135
178
  * await client.stats.skaterStatsWithQueryContext({ queryContext: context, reportType: 'summary' });
136
179
  */
137
- export declare const skaterStatsWithQueryContext: <Report extends keyof SkaterReportRows>(ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams<Report>) => Promise<StatsApiPage<SkaterReportRows[Report]>>;
180
+ export declare function skaterStatsWithQueryContext<Report extends keyof SkaterReportRows>(ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams<Report>): Promise<StatsApiPage<SkaterReportRows[Report]>>;
138
181
  /**
139
182
  * Retrieves goalie statistics with various filtering and aggregation
140
183
  * options.
141
184
  *
142
185
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
143
186
  */
144
- export declare const goalieStatsSummary: <Report extends keyof GoalieReportRows = 'summary'>(ctx: Context, { startSeason, endSeason, statsType, gameTypeId, franchiseId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: GoalieStatsSummaryParams<Report>) => Promise<GoalieReportRows[Report][]>;
187
+ export declare function goalieStatsSummary<Report extends keyof GoalieReportRows = 'summary'>(ctx: Context, { startSeason, endSeason, statsType, gameTypeId, franchiseId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: GoalieStatsSummaryParams<Report>): Promise<GoalieReportRows[Report][]>;
188
+ export interface StatsApiLeadersParams<Attribute extends string> {
189
+ /** Stat to rank by. An unknown attribute is a 500, not a 404. */
190
+ attribute: Attribute;
191
+ /** Season in YYYYYYYY format, e.g. 20232024. Defaults to every season on record. */
192
+ season?: Id;
193
+ }
194
+ /**
195
+ * Gets the top 10 single-season skater records for an attribute, e.g.
196
+ * Gretzky's 215 points, or the top 10 of one season.
197
+ *
198
+ * @param params.attribute points, goals, assists or gamesPlayed (case-sensitive)
199
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to every season.
200
+ * @example https://api.nhle.com/stats/rest/en/leaders/skaters/points?cayenneExp=season=20232024
201
+ */
202
+ export declare function skaterLeaders<Attribute extends keyof SkaterLeaderRows>(ctx: Context, params: StatsApiLeadersParams<Attribute>): Promise<SkaterLeaderRows[Attribute][]>;
203
+ /**
204
+ * Gets the top 10 single-season goalie records for an attribute, or the top
205
+ * 10 of one season. There is no minimum games played, so `gaa` / `savePctg`
206
+ * leaders are goalies with a few minutes.
207
+ *
208
+ * @param params.attribute gaa, savePctg, shutouts, timeOnIce or gamesPlayed (case-sensitive)
209
+ * @param params.season Season in YYYYYYYY format, e.g. 20232024. Defaults to every season.
210
+ * @example https://api.nhle.com/stats/rest/en/leaders/goalies/gaa?cayenneExp=season=20232024
211
+ */
212
+ export declare function goalieLeaders<Attribute extends keyof GoalieLeaderRows>(ctx: Context, params: StatsApiLeadersParams<Attribute>): Promise<GoalieLeaderRows[Attribute][]>;
213
+ /**
214
+ * Gets the career milestones active skaters are closing in on (e.g. 200
215
+ * assists, 50 playoff points).
216
+ *
217
+ * @example https://api.nhle.com/stats/rest/en/milestones/skaters
218
+ */
219
+ export declare function skaterMilestones(ctx: Context): Promise<SkaterMilestone[]>;
220
+ /**
221
+ * Gets the career milestones active goalies are closing in on (e.g. 30
222
+ * shutouts, 50 playoff games).
223
+ *
224
+ * @example https://api.nhle.com/stats/rest/en/milestones/goalies
225
+ */
226
+ export declare function goalieMilestones(ctx: Context): Promise<GoalieMilestone[]>;
145
227
  export declare const statsApi: {
146
228
  readonly gametypesPerSeasonDirectoryByTeam: typeof gametypesPerSeasonDirectoryByTeam;
147
229
  readonly playerCareerStats: typeof playerCareerStats;
148
230
  readonly playerGameLog: typeof playerGameLog;
231
+ readonly skaterStatsLeaders: typeof skaterStatsLeaders;
232
+ readonly goalieStatsLeaders: typeof goalieStatsLeaders;
233
+ readonly clubStats: typeof clubStats;
149
234
  readonly teamSummary: typeof teamSummary;
150
235
  readonly skaterStatsSummary: typeof skaterStatsSummary;
151
236
  readonly skaterStatsWithQueryContext: typeof skaterStatsWithQueryContext;
152
237
  readonly goalieStatsSummary: typeof goalieStatsSummary;
238
+ readonly skaterLeaders: typeof skaterLeaders;
239
+ readonly goalieLeaders: typeof goalieLeaders;
240
+ readonly skaterMilestones: typeof skaterMilestones;
241
+ readonly goalieMilestones: typeof goalieMilestones;
153
242
  };
@@ -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',
@@ -13,46 +23,85 @@ const REPORTS_WITHOUT_GAMES_PLAYED = [
13
23
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
14
24
  * @example https://api-web.nhle.com/v1/club-stats-season/TOR
15
25
  */
16
- export const gametypesPerSeasonDirectoryByTeam = async (ctx, { teamAbbr }) => (await ctx.get(Endpoint.API_WEB_V1, `club-stats-season/${teamAbbr}`)).json();
26
+ export async function gametypesPerSeasonDirectoryByTeam(ctx, { teamAbbr }) {
27
+ return (await ctx.get(Endpoint.API_WEB_V1, `club-stats-season/${teamAbbr}`)).json();
28
+ }
17
29
  /**
18
30
  * Gets a player's career statistics and biographical information.
19
31
  *
20
32
  * @param params.playerId NHL player id, e.g. 8481528
21
33
  * @example https://api-web.nhle.com/v1/player/8481528/landing
22
34
  */
23
- export const playerCareerStats = async (ctx, { playerId }) => (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/landing`)).json();
35
+ export async function playerCareerStats(ctx, { playerId }) {
36
+ return (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/landing`)).json();
37
+ }
24
38
  /**
25
- * 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.
26
40
  *
27
41
  * @param params.playerId NHL player id, e.g. 8481528
28
- * @param params.seasonId Season in YYYYYYYY format, e.g. 20232024
29
- * @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.
30
44
  * @example https://api-web.nhle.com/v1/player/8481528/game-log/20232024/2
31
45
  */
32
- export const playerGameLog = async (ctx, { playerId, seasonId, gameType, }) => {
33
- 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();
34
48
  return data.gameLog ?? [];
35
- };
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
+ }
36
95
  /**
37
96
  * Retrieves team summary statistics across one or more seasons.
38
97
  *
39
98
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
40
99
  */
41
- export const teamSummary = async (ctx, { startSeason, endSeason, gameTypeId = 2, isGame = false, isAggregate = false, sortExpr, start = 0, limit = 50, factCayenneExp = 'gamesPlayed>1', defaultCayenneExp, }) => {
42
- const effectiveSortExpr = sortExpr && sortExpr.length > 0
43
- ? sortExpr
44
- : [
45
- { property: 'points', direction: 'DESC' },
46
- { property: 'wins', direction: 'DESC' },
47
- // aggregated rows span seasons, so they have no teamId
48
- {
49
- property: isAggregate ? 'franchiseId' : 'teamId',
50
- direction: 'ASC',
51
- },
52
- ];
100
+ export async function teamSummary(ctx, { startSeason, endSeason, gameTypeId = 2, isGame = false, isAggregate = false, sortExpr, start = 0, limit = 50, factCayenneExp = 'gamesPlayed>1', defaultCayenneExp, }) {
101
+ const effectiveSortExpr = defaultSortForTeamSummary(sortExpr, isAggregate);
53
102
  const effectiveCayenneExp = defaultCayenneExp ??
54
103
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
55
- const qParams = {
104
+ const queryParams = {
56
105
  isAggregate,
57
106
  isGame,
58
107
  start,
@@ -61,29 +110,23 @@ export const teamSummary = async (ctx, { startSeason, endSeason, gameTypeId = 2,
61
110
  sort: JSON.stringify(effectiveSortExpr),
62
111
  cayenneExp: effectiveCayenneExp,
63
112
  };
64
- 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();
65
114
  return response.data;
66
- };
115
+ }
67
116
  /**
68
117
  * Gets simplified skater statistics summary for specified seasons and
69
118
  * franchises.
70
119
  *
71
120
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
72
121
  */
73
- export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchiseId, gameTypeId = 2, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp = 'gamesPlayed>=1', defaultCayenneExp, }) => {
74
- const effectiveSortExpr = sortExpr && sortExpr.length > 0
75
- ? sortExpr
76
- : [
77
- { property: 'points', direction: 'DESC' },
78
- { property: 'gamesPlayed', direction: 'ASC' },
79
- { property: 'playerId', direction: 'ASC' },
80
- ];
122
+ export async function skaterStatsSummary(ctx, { startSeason, endSeason, franchiseId, gameTypeId = 2, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp = 'gamesPlayed>=1', defaultCayenneExp, }) {
123
+ const effectiveSortExpr = defaultSortForSkaterStatsSummary(sortExpr);
81
124
  const baseCayenneExp = defaultCayenneExp ??
82
125
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
83
126
  const effectiveCayenneExp = !defaultCayenneExp && franchiseId
84
127
  ? `franchiseId=${franchiseId} and ${baseCayenneExp}`
85
128
  : baseCayenneExp;
86
- const qParams = {
129
+ const queryParams = {
87
130
  isAggregate: aggregate,
88
131
  isGame: false,
89
132
  start,
@@ -92,9 +135,9 @@ export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchis
92
135
  sort: JSON.stringify(effectiveSortExpr),
93
136
  cayenneExp: effectiveCayenneExp,
94
137
  };
95
- 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();
96
139
  return response.data;
97
- };
140
+ }
98
141
  /**
99
142
  * Retrieves skater statistics using a query context and specified report
100
143
  * type. Returns the full response (`{ data, total }`).
@@ -110,7 +153,7 @@ export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchis
110
153
  * ]);
111
154
  * await client.stats.skaterStatsWithQueryContext({ queryContext: context, reportType: 'summary' });
112
155
  */
113
- export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportType, sortExpr, aggregate = false, start = 0, limit = 25, }) => {
156
+ export async function skaterStatsWithQueryContext(ctx, { queryContext, reportType, sortExpr, aggregate = false, start = 0, limit = 25, }) {
114
157
  const effectiveSortExpr = sortExpr && sortExpr.length > 0
115
158
  ? sortExpr
116
159
  : defaultSortForReport(reportType);
@@ -127,14 +170,14 @@ export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportTyp
127
170
  cayenneExp: queryContext.query,
128
171
  };
129
172
  return (await ctx.get(Endpoint.API_STATS, `en/skater/${reportType}`, qParams)).json();
130
- };
173
+ }
131
174
  /**
132
175
  * Retrieves goalie statistics with various filtering and aggregation
133
176
  * options.
134
177
  *
135
178
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
136
179
  */
137
- export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsType, gameTypeId = 2, franchiseId, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp, defaultCayenneExp, }) => {
180
+ export async function goalieStatsSummary(ctx, { startSeason, endSeason, statsType, gameTypeId = 2, franchiseId, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp, defaultCayenneExp, }) {
138
181
  const report = statsType ?? 'summary';
139
182
  const effectiveEndSeason = endSeason === undefined || endSeason === null ? startSeason : endSeason;
140
183
  const effectiveSortExpr = sortExpr && sortExpr.length > 0 ? sortExpr : goalieStatsSorts(report);
@@ -143,7 +186,7 @@ export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsTyp
143
186
  const effectiveCayenneExp = franchiseId
144
187
  ? `franchiseId=${franchiseId} and ${baseCayenneExp}`
145
188
  : baseCayenneExp;
146
- const qParams = {
189
+ const queryParams = {
147
190
  isAggregate: aggregate,
148
191
  isGame: false,
149
192
  start,
@@ -152,15 +195,76 @@ export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsTyp
152
195
  sort: JSON.stringify(effectiveSortExpr),
153
196
  cayenneExp: effectiveCayenneExp,
154
197
  };
155
- 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();
156
199
  return response.data ?? [];
157
- };
200
+ }
201
+ async function getStatsData(ctx, resource, queryParams) {
202
+ const response = await (await ctx.get(Endpoint.API_STATS, resource, queryParams)).json();
203
+ return response.data ?? [];
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
+ }
158
255
  export const statsApi = {
159
256
  gametypesPerSeasonDirectoryByTeam,
160
257
  playerCareerStats,
161
258
  playerGameLog,
259
+ skaterStatsLeaders,
260
+ goalieStatsLeaders,
261
+ clubStats,
162
262
  teamSummary,
163
263
  skaterStatsSummary,
164
264
  skaterStatsWithQueryContext,
165
265
  goalieStatsSummary,
266
+ skaterLeaders,
267
+ goalieLeaders,
268
+ skaterMilestones,
269
+ goalieMilestones,
166
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: {
@@ -32,28 +32,68 @@ export declare function withFranchiseIds(teams: readonly Team[], franchises: rea
32
32
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
33
33
  * @example await client.teams.teams()
34
34
  */
35
- export declare const teams: (ctx: Context, { date }?: {
35
+ export declare function teams(ctx: Context, { date }?: {
36
36
  date?: string;
37
- }) => Promise<Team[]>;
37
+ }): Promise<Team[]>;
38
38
  /**
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
- export declare const teamRoster: (ctx: Context, { teamAbbr, season }: {
46
+ export declare function teamRoster(ctx: Context, { teamAbbr, season }: {
46
47
  teamAbbr: string;
47
- season: Id;
48
- }) => Promise<Roster>;
48
+ season?: Id;
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
- export declare const franchises: (ctx: Context) => Promise<Franchise[]>;
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
  };
@@ -5,7 +5,9 @@ async function fetchStandingsData(ctx, date) {
5
5
  }
6
6
  /** Converts a raw standings entry into a `Team`. */
7
7
  export function toTeam(teamData) {
8
- const nestedDefault = (key) => teamData[key]?.default ?? '';
8
+ function nestedDefault(key) {
9
+ return teamData[key]?.default ?? '';
10
+ }
9
11
  return {
10
12
  conference: {
11
13
  abbr: teamData.conferenceAbbrev ?? '',
@@ -66,26 +68,76 @@ export function withFranchiseIds(teams, franchises) {
66
68
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
67
69
  * @example await client.teams.teams()
68
70
  */
69
- export const teams = async (ctx, { date = 'now' } = {}) => {
71
+ export async function teams(ctx, { date = 'now' } = {}) {
70
72
  const standingsData = await fetchStandingsData(ctx, date);
71
73
  const franchiseData = await franchises(ctx);
72
74
  return withFranchiseIds(standingsData.map(toTeam), franchiseData);
73
- };
75
+ }
74
76
  /**
75
77
  * Get the roster for the given team and season.
76
78
  *
77
79
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
78
- * @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).
79
82
  * @example https://api-web.nhle.com/v1/roster/BUF/20232024
80
83
  */
81
- export const teamRoster = async (ctx, { teamAbbr, season }) => (await ctx.get(Endpoint.API_WEB_V1, `roster/${teamAbbr}/${season}`)).json();
84
+ export async function teamRoster(ctx, { teamAbbr, season }) {
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();
104
+ }
82
105
  /**
83
106
  * Get a list of all past and current NHL franchises.
84
107
  *
85
108
  * @example https://api.nhle.com/stats/rest/en/franchise
86
109
  */
87
- export const franchises = async (ctx) => {
110
+ export async function franchises(ctx) {
88
111
  const response = await (await ctx.get(Endpoint.API_STATS, 'en/franchise')).json();
89
112
  return response.data ?? [];
113
+ }
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,
90
143
  };
91
- export const teamsApi = { teams, teamRoster, franchises };
@@ -1,7 +1,7 @@
1
1
  import { styleText } from 'node:util';
2
2
  export type Style = Parameters<typeof styleText>[0];
3
- export declare const toStdout: (format: Style) => (text: string) => string;
4
- export declare const toStderr: (format: Style) => (text: string) => string;
3
+ export declare function toStdout(format: Style): (text: string) => string;
4
+ export declare function toStderr(format: Style): (text: string) => string;
5
5
  export declare const colors: {
6
6
  dim: (text: string) => string;
7
7
  pass: (text: string) => string;