nhl-api-ts 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +31 -6
  2. package/dist/api/edge.d.mts +25 -24
  3. package/dist/api/edge.mjs +69 -23
  4. package/dist/api/game-center.d.mts +16 -15
  5. package/dist/api/game-center.mjs +20 -8
  6. package/dist/api/helpers.d.mts +8 -7
  7. package/dist/api/helpers.mjs +6 -6
  8. package/dist/api/misc.d.mts +6 -6
  9. package/dist/api/misc.mjs +15 -5
  10. package/dist/api/players.d.mts +6 -5
  11. package/dist/api/players.mjs +6 -2
  12. package/dist/api/query/builder.d.mts +2 -0
  13. package/dist/api/query/builder.mjs +3 -1
  14. package/dist/api/query/index.d.mts +2 -2
  15. package/dist/api/query/index.mjs +1 -1
  16. package/dist/api/query/sorting/goalie-sorts.d.mts +55 -0
  17. package/dist/api/query/sorting/goalie-sorts.mjs +43 -48
  18. package/dist/api/query/sorting/sorting-options.d.mts +125 -0
  19. package/dist/api/query/sorting/sorting-options.mjs +3 -2
  20. package/dist/api/schedule.d.mts +22 -21
  21. package/dist/api/schedule.mjs +26 -14
  22. package/dist/api/standings.d.mts +5 -4
  23. package/dist/api/standings.mjs +4 -4
  24. package/dist/api/stats.d.mts +22 -17
  25. package/dist/api/stats.mjs +38 -16
  26. package/dist/api/teams.d.mts +9 -8
  27. package/dist/api/teams.mjs +10 -6
  28. package/dist/cli/colors.d.mts +2 -2
  29. package/dist/cli/colors.mjs +6 -2
  30. package/dist/cli/commands.mjs +36 -26
  31. package/dist/cli/run.mjs +7 -5
  32. package/dist/http-client.mjs +2 -2
  33. package/dist/index.d.mts +2 -1
  34. package/dist/nhl-client.d.mts +14 -10
  35. package/dist/nhl-client.mjs +9 -7
  36. package/dist/types/common.d.mts +80 -0
  37. package/dist/types/common.mjs +2 -0
  38. package/dist/types/edge.d.mts +1024 -0
  39. package/dist/types/edge.mjs +1 -0
  40. package/dist/types/game-center.d.mts +1137 -0
  41. package/dist/types/game-center.mjs +1 -0
  42. package/dist/types/helpers.d.mts +17 -0
  43. package/dist/types/helpers.mjs +1 -0
  44. package/dist/types/index.d.mts +10 -0
  45. package/dist/types/index.mjs +1 -0
  46. package/dist/types/misc.d.mts +68 -0
  47. package/dist/types/misc.mjs +2 -0
  48. package/dist/types/players.d.mts +41 -0
  49. package/dist/types/players.mjs +1 -0
  50. package/dist/types/schedule.d.mts +428 -0
  51. package/dist/types/schedule.mjs +1 -0
  52. package/dist/types/standings.d.mts +103 -0
  53. package/dist/types/standings.mjs +1 -0
  54. package/dist/types/stats.d.mts +1082 -0
  55. package/dist/types/stats.mjs +1 -0
  56. package/dist/types/teams.d.mts +29 -0
  57. package/dist/types/teams.mjs +1 -0
  58. package/dist/utils.d.mts +1 -2
  59. package/dist/utils.mjs +3 -1
  60. package/package.json +7 -20
  61. package/dist/api/query/errors.d.mts +0 -3
  62. package/dist/api/query/errors.mjs +0 -6
  63. package/dist/api/query/filters/base.d.mts +0 -4
  64. package/dist/api/query/filters/base.mjs +0 -2
  65. package/dist/api/query/filters/decision.d.mts +0 -13
  66. package/dist/api/query/filters/decision.mjs +0 -26
  67. package/dist/api/query/filters/draft.d.mts +0 -15
  68. package/dist/api/query/filters/draft.mjs +0 -27
  69. package/dist/api/query/filters/experience.d.mts +0 -9
  70. package/dist/api/query/filters/experience.mjs +0 -17
  71. package/dist/api/query/filters/franchise.d.mts +0 -9
  72. package/dist/api/query/filters/franchise.mjs +0 -15
  73. package/dist/api/query/filters/game-type.d.mts +0 -10
  74. package/dist/api/query/filters/game-type.mjs +0 -16
  75. package/dist/api/query/filters/goalie-sorts.d.mts +0 -3
  76. package/dist/api/query/filters/goalie-sorts.mjs +0 -55
  77. package/dist/api/query/filters/home-road.d.mts +0 -9
  78. package/dist/api/query/filters/home-road.mjs +0 -16
  79. package/dist/api/query/filters/index.d.mts +0 -14
  80. package/dist/api/query/filters/index.mjs +0 -14
  81. package/dist/api/query/filters/nationality.d.mts +0 -12
  82. package/dist/api/query/filters/nationality.mjs +0 -19
  83. package/dist/api/query/filters/opponent.d.mts +0 -10
  84. package/dist/api/query/filters/opponent.mjs +0 -16
  85. package/dist/api/query/filters/position.d.mts +0 -16
  86. package/dist/api/query/filters/position.mjs +0 -28
  87. package/dist/api/query/filters/season.d.mts +0 -14
  88. package/dist/api/query/filters/season.mjs +0 -24
  89. package/dist/api/query/filters/shoot-catch.d.mts +0 -9
  90. package/dist/api/query/filters/shoot-catch.mjs +0 -16
  91. package/dist/api/query/filters/status.d.mts +0 -20
  92. package/dist/api/query/filters/status.mjs +0 -28
  93. package/dist/logging.d.mts +0 -14
  94. package/dist/logging.mjs +0 -13
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { CalendarSchedule, ClubScheduleGame, OddsPartner, PlayoffBracket, PlayoffCarousel, PlayoffSeriesSchedule, ScheduleGame, TeamSeasonSchedule, WeeklySchedule } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  /**
4
5
  * Parses and normalizes a YYYY-MM-DD date: single-digit months/days are
5
6
  * accepted ("2024-10-9" -> "2024-10-09") and impossible dates are rejected.
@@ -9,8 +10,8 @@ export interface DailySchedule {
9
10
  nextStartDate: string | null;
10
11
  previousStartDate: string | null;
11
12
  date: string;
12
- oddsPartners: JsonObject[] | null;
13
- games?: JsonObject[];
13
+ oddsPartners: OddsPartner[] | null;
14
+ games?: ScheduleGame[];
14
15
  numberOfGames?: number;
15
16
  }
16
17
  /**
@@ -20,18 +21,18 @@ export interface DailySchedule {
20
21
  * @throws RangeError If the date is not a valid YYYY-MM-DD date
21
22
  * @example await client.schedule.dailySchedule({ date: '2024-10-09' })
22
23
  */
23
- export declare const dailySchedule: (ctx: Context, { date }?: {
24
+ export declare function dailySchedule(ctx: Context, { date }?: {
24
25
  date?: string;
25
- }) => Promise<DailySchedule>;
26
+ }): Promise<DailySchedule>;
26
27
  /**
27
28
  * Gets NHL schedule for a week starting from the specified date.
28
29
  *
29
30
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
30
31
  * @example https://api-web.nhle.com/v1/schedule/2024-10-09
31
32
  */
32
- export declare const weeklySchedule: (ctx: Context, { date }?: {
33
+ export declare function weeklySchedule(ctx: Context, { date }?: {
33
34
  date?: string;
34
- }) => Promise<JsonObject>;
35
+ }): Promise<WeeklySchedule>;
35
36
  /**
36
37
  * Gets monthly schedule for a specified team.
37
38
  *
@@ -39,10 +40,10 @@ export declare const weeklySchedule: (ctx: Context, { date }?: {
39
40
  * @param params.month Month in YYYY-MM format. Defaults to "now".
40
41
  * @example https://api-web.nhle.com/v1/club-schedule/BUF/month/2023-11
41
42
  */
42
- export declare const teamMonthlySchedule: (ctx: Context, { teamAbbr, month }: {
43
+ export declare function teamMonthlySchedule(ctx: Context, { teamAbbr, month }: {
43
44
  teamAbbr: string;
44
45
  month?: string;
45
- }) => Promise<JsonObject[]>;
46
+ }): Promise<ClubScheduleGame[]>;
46
47
  /**
47
48
  * Gets weekly schedule for a specified team.
48
49
  *
@@ -50,10 +51,10 @@ export declare const teamMonthlySchedule: (ctx: Context, { teamAbbr, month }: {
50
51
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
51
52
  * @example https://api-web.nhle.com/v1/club-schedule/BUF/week/2024-02-10
52
53
  */
53
- export declare const teamWeeklySchedule: (ctx: Context, { teamAbbr, date }: {
54
+ export declare function teamWeeklySchedule(ctx: Context, { teamAbbr, date }: {
54
55
  teamAbbr: string;
55
56
  date?: string;
56
- }) => Promise<JsonObject[]>;
57
+ }): Promise<ClubScheduleGame[]>;
57
58
  /**
58
59
  * Gets the full season schedule for a specified team.
59
60
  *
@@ -61,28 +62,28 @@ export declare const teamWeeklySchedule: (ctx: Context, { teamAbbr, date }: {
61
62
  * @param params.season Season in YYYYYYYY format, e.g. 20232024
62
63
  * @example https://api-web.nhle.com/v1/club-schedule-season/BUF/20232024
63
64
  */
64
- export declare const teamSeasonSchedule: (ctx: Context, { teamAbbr, season }: {
65
+ export declare function teamSeasonSchedule(ctx: Context, { teamAbbr, season }: {
65
66
  teamAbbr: string;
66
67
  season: Id;
67
- }) => Promise<JsonObject>;
68
+ }): Promise<TeamSeasonSchedule>;
68
69
  /**
69
70
  * Gets the schedule in calendar format for a specified date.
70
71
  *
71
72
  * @param params.date Date in YYYY-MM-DD format
72
73
  * @example https://api-web.nhle.com/v1/schedule-calendar/2023-11-08
73
74
  */
74
- export declare const calendarSchedule: (ctx: Context, { date }: {
75
+ export declare function calendarSchedule(ctx: Context, { date }: {
75
76
  date: string;
76
- }) => Promise<JsonObject>;
77
+ }): Promise<CalendarSchedule>;
77
78
  /**
78
79
  * Gets all playoff series information up to the current round.
79
80
  *
80
81
  * @param params.season Season in YYYYYYYY format, e.g. 20232024
81
82
  * @example https://api-web.nhle.com/v1/playoff-series/carousel/20232024
82
83
  */
83
- export declare const playoffCarousel: (ctx: Context, { season }: {
84
+ export declare function playoffCarousel(ctx: Context, { season }: {
84
85
  season: Id;
85
- }) => Promise<JsonObject>;
86
+ }): Promise<PlayoffCarousel>;
86
87
  /**
87
88
  * Returns the schedule and results for a specified playoff series matchup.
88
89
  *
@@ -90,19 +91,19 @@ export declare const playoffCarousel: (ctx: Context, { season }: {
90
91
  * @param params.series Series letter, e.g. "a" (first round) through "o" (final)
91
92
  * @example https://api-web.nhle.com/v1/schedule/playoff-series/20232024/a
92
93
  */
93
- export declare const playoffSeriesSchedule: (ctx: Context, { season, series }: {
94
+ export declare function playoffSeriesSchedule(ctx: Context, { season, series }: {
94
95
  season: Id;
95
96
  series: string;
96
- }) => Promise<JsonObject>;
97
+ }): Promise<PlayoffSeriesSchedule>;
97
98
  /**
98
99
  * Returns the full playoff bracket for a given year.
99
100
  *
100
101
  * @param params.year Year the playoffs took place, e.g. 2024
101
102
  * @example https://api-web.nhle.com/v1/playoff-bracket/2024
102
103
  */
103
- export declare const playoffBracket: (ctx: Context, { year }: {
104
+ export declare function playoffBracket(ctx: Context, { year }: {
104
105
  year: Id;
105
- }) => Promise<JsonObject>;
106
+ }): Promise<PlayoffBracket>;
106
107
  export declare const scheduleApi: {
107
108
  readonly dailySchedule: typeof dailySchedule;
108
109
  readonly weeklySchedule: typeof weeklySchedule;
@@ -1,5 +1,7 @@
1
1
  import { Endpoint } from '#src/http-client.mjs';
2
- const pad = (value, width = 2) => String(value).padStart(width, '0');
2
+ function pad(value, width = 2) {
3
+ return String(value).padStart(width, '0');
4
+ }
3
5
  /** Today's date (local time) as YYYY-MM-DD. */
4
6
  function today() {
5
7
  const now = new Date();
@@ -29,7 +31,7 @@ export function normalizeDate(date) {
29
31
  * @throws RangeError If the date is not a valid YYYY-MM-DD date
30
32
  * @example await client.schedule.dailySchedule({ date: '2024-10-09' })
31
33
  */
32
- export const dailySchedule = async (ctx, { date } = {}) => {
34
+ export async function dailySchedule(ctx, { date } = {}) {
33
35
  const resolvedDate = date ? normalizeDate(date) : today();
34
36
  const scheduleData = await (await ctx.get(Endpoint.API_WEB_V1, `schedule/${resolvedDate}`)).json();
35
37
  const responsePayload = {
@@ -46,17 +48,17 @@ export const dailySchedule = async (ctx, { date } = {}) => {
46
48
  responsePayload.numberOfGames = games.length;
47
49
  }
48
50
  return responsePayload;
49
- };
51
+ }
50
52
  /**
51
53
  * Gets NHL schedule for a week starting from the specified date.
52
54
  *
53
55
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
54
56
  * @example https://api-web.nhle.com/v1/schedule/2024-10-09
55
57
  */
56
- export const weeklySchedule = async (ctx, { date } = {}) => {
58
+ export async function weeklySchedule(ctx, { date } = {}) {
57
59
  const res = date ? date : 'now';
58
60
  return (await ctx.get(Endpoint.API_WEB_V1, `schedule/${res}`)).json();
59
- };
61
+ }
60
62
  /**
61
63
  * Gets monthly schedule for a specified team.
62
64
  *
@@ -64,11 +66,11 @@ export const weeklySchedule = async (ctx, { date } = {}) => {
64
66
  * @param params.month Month in YYYY-MM format. Defaults to "now".
65
67
  * @example https://api-web.nhle.com/v1/club-schedule/BUF/month/2023-11
66
68
  */
67
- export const teamMonthlySchedule = async (ctx, { teamAbbr, month }) => {
69
+ export async function teamMonthlySchedule(ctx, { teamAbbr, month }) {
68
70
  const resource = `club-schedule/${teamAbbr}/month/${month ? month : 'now'}`;
69
71
  const response = await (await ctx.get(Endpoint.API_WEB_V1, resource)).json();
70
72
  return response.games ?? [];
71
- };
73
+ }
72
74
  /**
73
75
  * Gets weekly schedule for a specified team.
74
76
  *
@@ -76,11 +78,11 @@ export const teamMonthlySchedule = async (ctx, { teamAbbr, month }) => {
76
78
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
77
79
  * @example https://api-web.nhle.com/v1/club-schedule/BUF/week/2024-02-10
78
80
  */
79
- export const teamWeeklySchedule = async (ctx, { teamAbbr, date }) => {
81
+ export async function teamWeeklySchedule(ctx, { teamAbbr, date }) {
80
82
  const resource = `club-schedule/${teamAbbr}/week/${date ? date : 'now'}`;
81
83
  const response = await (await ctx.get(Endpoint.API_WEB_V1, resource)).json();
82
84
  return response.games ?? [];
83
- };
85
+ }
84
86
  /**
85
87
  * Gets the full season schedule for a specified team.
86
88
  *
@@ -88,21 +90,27 @@ export const teamWeeklySchedule = async (ctx, { teamAbbr, date }) => {
88
90
  * @param params.season Season in YYYYYYYY format, e.g. 20232024
89
91
  * @example https://api-web.nhle.com/v1/club-schedule-season/BUF/20232024
90
92
  */
91
- export const teamSeasonSchedule = async (ctx, { teamAbbr, season }) => (await ctx.get(Endpoint.API_WEB_V1, `club-schedule-season/${teamAbbr}/${season}`)).json();
93
+ export async function teamSeasonSchedule(ctx, { teamAbbr, season }) {
94
+ return (await ctx.get(Endpoint.API_WEB_V1, `club-schedule-season/${teamAbbr}/${season}`)).json();
95
+ }
92
96
  /**
93
97
  * Gets the schedule in calendar format for a specified date.
94
98
  *
95
99
  * @param params.date Date in YYYY-MM-DD format
96
100
  * @example https://api-web.nhle.com/v1/schedule-calendar/2023-11-08
97
101
  */
98
- export const calendarSchedule = async (ctx, { date }) => (await ctx.get(Endpoint.API_WEB_V1, `schedule-calendar/${date}`)).json();
102
+ export async function calendarSchedule(ctx, { date }) {
103
+ return (await ctx.get(Endpoint.API_WEB_V1, `schedule-calendar/${date}`)).json();
104
+ }
99
105
  /**
100
106
  * Gets all playoff series information up to the current round.
101
107
  *
102
108
  * @param params.season Season in YYYYYYYY format, e.g. 20232024
103
109
  * @example https://api-web.nhle.com/v1/playoff-series/carousel/20232024
104
110
  */
105
- export const playoffCarousel = async (ctx, { season }) => (await ctx.get(Endpoint.API_WEB_V1, `playoff-series/carousel/${season}`)).json();
111
+ export async function playoffCarousel(ctx, { season }) {
112
+ return (await ctx.get(Endpoint.API_WEB_V1, `playoff-series/carousel/${season}`)).json();
113
+ }
106
114
  /**
107
115
  * Returns the schedule and results for a specified playoff series matchup.
108
116
  *
@@ -110,14 +118,18 @@ export const playoffCarousel = async (ctx, { season }) => (await ctx.get(Endpoin
110
118
  * @param params.series Series letter, e.g. "a" (first round) through "o" (final)
111
119
  * @example https://api-web.nhle.com/v1/schedule/playoff-series/20232024/a
112
120
  */
113
- export const playoffSeriesSchedule = async (ctx, { season, series }) => (await ctx.get(Endpoint.API_WEB_V1, `schedule/playoff-series/${season}/${series}`)).json();
121
+ export async function playoffSeriesSchedule(ctx, { season, series }) {
122
+ return (await ctx.get(Endpoint.API_WEB_V1, `schedule/playoff-series/${season}/${series}`)).json();
123
+ }
114
124
  /**
115
125
  * Returns the full playoff bracket for a given year.
116
126
  *
117
127
  * @param params.year Year the playoffs took place, e.g. 2024
118
128
  * @example https://api-web.nhle.com/v1/playoff-bracket/2024
119
129
  */
120
- export const playoffBracket = async (ctx, { year }) => (await ctx.get(Endpoint.API_WEB_V1, `playoff-bracket/${year}`)).json();
130
+ export async function playoffBracket(ctx, { year }) {
131
+ return (await ctx.get(Endpoint.API_WEB_V1, `playoff-bracket/${year}`)).json();
132
+ }
121
133
  export const scheduleApi = {
122
134
  dailySchedule,
123
135
  weeklySchedule,
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { LeagueStandings, StandingsSeason } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  /**
4
5
  * Gets NHL league standings for a specific date or season.
5
6
  *
@@ -11,17 +12,17 @@ import type { Id, JsonObject } from '#src/utils.mjs';
11
12
  * @throws RangeError If the season id is not found in the standings manifest
12
13
  * @example await client.standings.leagueStandings({ season: '20222023' })
13
14
  */
14
- export declare const leagueStandings: (ctx: Context, { date, season }?: {
15
+ export declare function leagueStandings(ctx: Context, { date, season }?: {
15
16
  date?: string;
16
17
  season?: Id;
17
- }) => Promise<JsonObject>;
18
+ }): Promise<LeagueStandings>;
18
19
  /**
19
20
  * Gets metadata for every historical NHL season: start/end dates and which
20
21
  * standings rules (conferences, divisions, wildcard, ties...) were in use.
21
22
  *
22
23
  * @example https://api-web.nhle.com/v1/standings-season
23
24
  */
24
- export declare const seasonStandingManifest: (ctx: Context) => Promise<JsonObject[]>;
25
+ export declare function seasonStandingManifest(ctx: Context): Promise<StandingsSeason[]>;
25
26
  export declare const standingsApi: {
26
27
  readonly leagueStandings: typeof leagueStandings;
27
28
  readonly seasonStandingManifest: typeof seasonStandingManifest;
@@ -10,7 +10,7 @@ import { Endpoint } from '#src/http-client.mjs';
10
10
  * @throws RangeError If the season id is not found in the standings manifest
11
11
  * @example await client.standings.leagueStandings({ season: '20222023' })
12
12
  */
13
- export const leagueStandings = async (ctx, { date, season } = {}) => {
13
+ export async function leagueStandings(ctx, { date, season } = {}) {
14
14
  if (season) {
15
15
  const seasons = await seasonStandingManifest(ctx);
16
16
  const seasonData = seasons.find((seasonEntry) => seasonEntry.id === Number(season));
@@ -21,17 +21,17 @@ export const leagueStandings = async (ctx, { date, season } = {}) => {
21
21
  }
22
22
  const res = date ? date : 'now';
23
23
  return (await ctx.get(Endpoint.API_WEB_V1, `standings/${res}`)).json();
24
- };
24
+ }
25
25
  /**
26
26
  * Gets metadata for every historical NHL season: start/end dates and which
27
27
  * standings rules (conferences, divisions, wildcard, ties...) were in use.
28
28
  *
29
29
  * @example https://api-web.nhle.com/v1/standings-season
30
30
  */
31
- export const seasonStandingManifest = async (ctx) => {
31
+ export async function seasonStandingManifest(ctx) {
32
32
  const response = await (await ctx.get(Endpoint.API_WEB_V1, 'standings-season')).json();
33
33
  return response.seasons ?? [];
34
- };
34
+ }
35
35
  export const standingsApi = {
36
36
  leagueStandings,
37
37
  seasonStandingManifest,
@@ -1,7 +1,8 @@
1
- import type { QueryContext } from '#src/api/query/builder.mjs';
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 { Id, JsonObject } from '#src/utils.mjs';
4
+ import type { ClubStatsSeason, GameLogEntry, GoalieReportRows, PlayerLanding, SkaterReportRows, StatsApiPage, TeamSummaryRow } from '#src/types/index.mjs';
5
+ import type { Id } from '#src/utils.mjs';
5
6
  export interface TeamSummaryParams {
6
7
  /** Start season in YYYYYYYY format, e.g. 20202021 */
7
8
  startSeason: Id;
@@ -13,7 +14,7 @@ export interface TeamSummaryParams {
13
14
  isGame?: boolean;
14
15
  /** Aggregate stats across the selected seasons. Defaults to false. */
15
16
  isAggregate?: boolean;
16
- /** Custom sort. Defaults to points DESC, wins DESC, teamId ASC. */
17
+ /** Custom sort. Defaults to points DESC, wins DESC, teamId ASC (franchiseId ASC when aggregating). */
17
18
  sortExpr?: SortExpr[];
18
19
  /** Pagination offset. Defaults to 0. */
19
20
  start?: number;
@@ -40,7 +41,7 @@ export interface SkaterStatsSummaryParams {
40
41
  factCayenneExp?: string;
41
42
  defaultCayenneExp?: string;
42
43
  }
43
- export interface SkaterStatsWithQueryContextParams {
44
+ export interface SkaterStatsWithQueryContextParams<Report extends keyof SkaterReportRows = keyof SkaterReportRows> {
44
45
  /** Built with `buildQuery(filters)`. */
45
46
  queryContext: QueryContext;
46
47
  /**
@@ -49,14 +50,14 @@ export interface SkaterStatsWithQueryContextParams {
49
50
  * powerplay, puckPossessions, summaryshooting, percentages, scoringRates,
50
51
  * scoringpergame, shootout, shottype, timeonice
51
52
  */
52
- reportType: string;
53
+ reportType: Report;
53
54
  /** Custom sort. Defaults to the report type's default sort. */
54
55
  sortExpr?: SortExpr[];
55
56
  aggregate?: boolean;
56
57
  start?: number;
57
58
  limit?: number;
58
59
  }
59
- export interface GoalieStatsSummaryParams {
60
+ export interface GoalieStatsSummaryParams<Report extends keyof GoalieReportRows = keyof GoalieReportRows> {
60
61
  startSeason: Id;
61
62
  /** Defaults to `startSeason`. */
62
63
  endSeason?: Id;
@@ -64,7 +65,7 @@ export interface GoalieStatsSummaryParams {
64
65
  * Report type: summary (default), advanced, bios, daysrest, penaltyShots,
65
66
  * savesByStrength, shootout, startedVsRelieved
66
67
  */
67
- statsType?: string;
68
+ statsType?: Report;
68
69
  gameTypeId?: number;
69
70
  franchiseId?: Id;
70
71
  aggregate?: boolean;
@@ -80,18 +81,18 @@ export interface GoalieStatsSummaryParams {
80
81
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
81
82
  * @example https://api-web.nhle.com/v1/club-stats-season/TOR
82
83
  */
83
- export declare const gametypesPerSeasonDirectoryByTeam: (ctx: Context, { teamAbbr }: {
84
+ export declare function gametypesPerSeasonDirectoryByTeam(ctx: Context, { teamAbbr }: {
84
85
  teamAbbr: string;
85
- }) => Promise<JsonObject[]>;
86
+ }): Promise<ClubStatsSeason[]>;
86
87
  /**
87
88
  * Gets a player's career statistics and biographical information.
88
89
  *
89
90
  * @param params.playerId NHL player id, e.g. 8481528
90
91
  * @example https://api-web.nhle.com/v1/player/8481528/landing
91
92
  */
92
- export declare const playerCareerStats: (ctx: Context, { playerId }: {
93
+ export declare function playerCareerStats(ctx: Context, { playerId }: {
93
94
  playerId: Id;
94
- }) => Promise<JsonObject>;
95
+ }): Promise<PlayerLanding>;
95
96
  /**
96
97
  * Gets a player's game log for a specific season and game type.
97
98
  *
@@ -100,28 +101,32 @@ export declare const playerCareerStats: (ctx: Context, { playerId }: {
100
101
  * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
101
102
  * @example https://api-web.nhle.com/v1/player/8481528/game-log/20232024/2
102
103
  */
103
- export declare const playerGameLog: (ctx: Context, { playerId, seasonId, gameType, }: {
104
+ export declare function playerGameLog(ctx: Context, { playerId, seasonId, gameType, }: {
104
105
  playerId: Id;
105
106
  seasonId: Id;
106
107
  gameType: number;
107
- }) => Promise<JsonObject[]>;
108
+ }): Promise<GameLogEntry[]>;
108
109
  /**
109
110
  * Retrieves team summary statistics across one or more seasons.
110
111
  *
111
112
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
112
113
  */
113
- export declare const teamSummary: (ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams) => Promise<JsonObject[]>;
114
+ export declare function teamSummary(ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams): Promise<TeamSummaryRow[]>;
114
115
  /**
115
116
  * Gets simplified skater statistics summary for specified seasons and
116
117
  * franchises.
117
118
  *
118
119
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
119
120
  */
120
- export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams) => Promise<JsonObject[]>;
121
+ export declare function skaterStatsSummary(ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams): Promise<SkaterReportRows['summary'][]>;
121
122
  /**
122
123
  * Retrieves skater statistics using a query context and specified report
123
124
  * type. Returns the full response (`{ data, total }`).
124
125
  *
126
+ * The default fact filter (`gamesPlayed>=1`) is dropped for the `shootout` and
127
+ * `penaltyShots` reports, which have no `gamesPlayed` column. A fact filter
128
+ * you pass to `buildQuery` is sent as given.
129
+ *
125
130
  * @example
126
131
  * const context = buildQuery([
127
132
  * filter.season('20232024', '20232024'),
@@ -129,14 +134,14 @@ export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason
129
134
  * ]);
130
135
  * await client.stats.skaterStatsWithQueryContext({ queryContext: context, reportType: 'summary' });
131
136
  */
132
- export declare const skaterStatsWithQueryContext: (ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams) => Promise<JsonObject>;
137
+ export declare function skaterStatsWithQueryContext<Report extends keyof SkaterReportRows>(ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams<Report>): Promise<StatsApiPage<SkaterReportRows[Report]>>;
133
138
  /**
134
139
  * Retrieves goalie statistics with various filtering and aggregation
135
140
  * options.
136
141
  *
137
142
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
138
143
  */
139
- export declare const goalieStatsSummary: (ctx: Context, { startSeason, endSeason, statsType, gameTypeId, franchiseId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: GoalieStatsSummaryParams) => Promise<JsonObject[]>;
144
+ 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][]>;
140
145
  export declare const statsApi: {
141
146
  readonly gametypesPerSeasonDirectoryByTeam: typeof gametypesPerSeasonDirectoryByTeam;
142
147
  readonly playerCareerStats: typeof playerCareerStats;
@@ -1,20 +1,30 @@
1
+ import { DEFAULT_FACT_QUERY, } from '#src/api/query/builder.mjs';
1
2
  import { goalieStatsSorts } from '#src/api/query/sorting/goalie-sorts.mjs';
2
3
  import { defaultSortForReport, } from '#src/api/query/sorting/sorting-options.mjs';
3
4
  import { Endpoint } from '#src/http-client.mjs';
5
+ /** Skater reports whose rows have no `gamesPlayed`, so the API rejects the default fact filter. */
6
+ const REPORTS_WITHOUT_GAMES_PLAYED = [
7
+ 'shootout',
8
+ 'penaltyShots',
9
+ ];
4
10
  /**
5
11
  * Gets all game types played by a team throughout their history.
6
12
  *
7
13
  * @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
8
14
  * @example https://api-web.nhle.com/v1/club-stats-season/TOR
9
15
  */
10
- export const gametypesPerSeasonDirectoryByTeam = async (ctx, { teamAbbr }) => (await ctx.get(Endpoint.API_WEB_V1, `club-stats-season/${teamAbbr}`)).json();
16
+ export async function gametypesPerSeasonDirectoryByTeam(ctx, { teamAbbr }) {
17
+ return (await ctx.get(Endpoint.API_WEB_V1, `club-stats-season/${teamAbbr}`)).json();
18
+ }
11
19
  /**
12
20
  * Gets a player's career statistics and biographical information.
13
21
  *
14
22
  * @param params.playerId NHL player id, e.g. 8481528
15
23
  * @example https://api-web.nhle.com/v1/player/8481528/landing
16
24
  */
17
- export const playerCareerStats = async (ctx, { playerId }) => (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/landing`)).json();
25
+ export async function playerCareerStats(ctx, { playerId }) {
26
+ return (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/landing`)).json();
27
+ }
18
28
  /**
19
29
  * Gets a player's game log for a specific season and game type.
20
30
  *
@@ -23,22 +33,26 @@ export const playerCareerStats = async (ctx, { playerId }) => (await ctx.get(End
23
33
  * @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
24
34
  * @example https://api-web.nhle.com/v1/player/8481528/game-log/20232024/2
25
35
  */
26
- export const playerGameLog = async (ctx, { playerId, seasonId, gameType, }) => {
36
+ export async function playerGameLog(ctx, { playerId, seasonId, gameType, }) {
27
37
  const data = await (await ctx.get(Endpoint.API_WEB_V1, `player/${playerId}/game-log/${seasonId}/${gameType}`)).json();
28
38
  return data.gameLog ?? [];
29
- };
39
+ }
30
40
  /**
31
41
  * Retrieves team summary statistics across one or more seasons.
32
42
  *
33
43
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
34
44
  */
35
- export const teamSummary = async (ctx, { startSeason, endSeason, gameTypeId = 2, isGame = false, isAggregate = false, sortExpr, start = 0, limit = 50, factCayenneExp = 'gamesPlayed>1', defaultCayenneExp, }) => {
45
+ export async function teamSummary(ctx, { startSeason, endSeason, gameTypeId = 2, isGame = false, isAggregate = false, sortExpr, start = 0, limit = 50, factCayenneExp = 'gamesPlayed>1', defaultCayenneExp, }) {
36
46
  const effectiveSortExpr = sortExpr && sortExpr.length > 0
37
47
  ? sortExpr
38
48
  : [
39
49
  { property: 'points', direction: 'DESC' },
40
50
  { property: 'wins', direction: 'DESC' },
41
- { property: 'teamId', direction: 'ASC' },
51
+ // aggregated rows span seasons, so they have no teamId
52
+ {
53
+ property: isAggregate ? 'franchiseId' : 'teamId',
54
+ direction: 'ASC',
55
+ },
42
56
  ];
43
57
  const effectiveCayenneExp = defaultCayenneExp ??
44
58
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
@@ -53,14 +67,14 @@ export const teamSummary = async (ctx, { startSeason, endSeason, gameTypeId = 2,
53
67
  };
54
68
  const response = await (await ctx.get(Endpoint.API_STATS, 'en/team/summary', qParams)).json();
55
69
  return response.data;
56
- };
70
+ }
57
71
  /**
58
72
  * Gets simplified skater statistics summary for specified seasons and
59
73
  * franchises.
60
74
  *
61
75
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
62
76
  */
63
- export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchiseId, gameTypeId = 2, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp = 'gamesPlayed>=1', defaultCayenneExp, }) => {
77
+ export async function skaterStatsSummary(ctx, { startSeason, endSeason, franchiseId, gameTypeId = 2, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp = 'gamesPlayed>=1', defaultCayenneExp, }) {
64
78
  const effectiveSortExpr = sortExpr && sortExpr.length > 0
65
79
  ? sortExpr
66
80
  : [
@@ -84,11 +98,15 @@ export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchis
84
98
  };
85
99
  const response = await (await ctx.get(Endpoint.API_STATS, 'en/skater/summary', qParams)).json();
86
100
  return response.data;
87
- };
101
+ }
88
102
  /**
89
103
  * Retrieves skater statistics using a query context and specified report
90
104
  * type. Returns the full response (`{ data, total }`).
91
105
  *
106
+ * The default fact filter (`gamesPlayed>=1`) is dropped for the `shootout` and
107
+ * `penaltyShots` reports, which have no `gamesPlayed` column. A fact filter
108
+ * you pass to `buildQuery` is sent as given.
109
+ *
92
110
  * @example
93
111
  * const context = buildQuery([
94
112
  * filter.season('20232024', '20232024'),
@@ -96,7 +114,7 @@ export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchis
96
114
  * ]);
97
115
  * await client.stats.skaterStatsWithQueryContext({ queryContext: context, reportType: 'summary' });
98
116
  */
99
- export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportType, sortExpr, aggregate = false, start = 0, limit = 25, }) => {
117
+ export async function skaterStatsWithQueryContext(ctx, { queryContext, reportType, sortExpr, aggregate = false, start = 0, limit = 25, }) {
100
118
  const effectiveSortExpr = sortExpr && sortExpr.length > 0
101
119
  ? sortExpr
102
120
  : defaultSortForReport(reportType);
@@ -105,21 +123,25 @@ export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportTyp
105
123
  isGame: false,
106
124
  start,
107
125
  limit,
108
- factCayenneExp: queryContext.factQuery,
126
+ factCayenneExp: queryContext.factQuery === DEFAULT_FACT_QUERY &&
127
+ REPORTS_WITHOUT_GAMES_PLAYED.includes(reportType)
128
+ ? ''
129
+ : queryContext.factQuery,
109
130
  sort: JSON.stringify(effectiveSortExpr),
110
131
  cayenneExp: queryContext.query,
111
132
  };
112
133
  return (await ctx.get(Endpoint.API_STATS, `en/skater/${reportType}`, qParams)).json();
113
- };
134
+ }
114
135
  /**
115
136
  * Retrieves goalie statistics with various filtering and aggregation
116
137
  * options.
117
138
  *
118
139
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
119
140
  */
120
- export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsType = 'summary', gameTypeId = 2, franchiseId, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp, defaultCayenneExp, }) => {
141
+ export async function goalieStatsSummary(ctx, { startSeason, endSeason, statsType, gameTypeId = 2, franchiseId, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp, defaultCayenneExp, }) {
142
+ const report = statsType ?? 'summary';
121
143
  const effectiveEndSeason = endSeason === undefined || endSeason === null ? startSeason : endSeason;
122
- const effectiveSortExpr = sortExpr && sortExpr.length > 0 ? sortExpr : goalieStatsSorts(statsType);
144
+ const effectiveSortExpr = sortExpr && sortExpr.length > 0 ? sortExpr : goalieStatsSorts(report);
123
145
  const baseCayenneExp = defaultCayenneExp ??
124
146
  `gameTypeId=${gameTypeId} and seasonId<=${effectiveEndSeason} and seasonId>=${startSeason}`;
125
147
  const effectiveCayenneExp = franchiseId
@@ -134,9 +156,9 @@ export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsTyp
134
156
  sort: JSON.stringify(effectiveSortExpr),
135
157
  cayenneExp: effectiveCayenneExp,
136
158
  };
137
- const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${statsType}`, qParams)).json();
159
+ const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${report}`, qParams)).json();
138
160
  return response.data ?? [];
139
- };
161
+ }
140
162
  export const statsApi = {
141
163
  gametypesPerSeasonDirectoryByTeam,
142
164
  playerCareerStats,
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { Franchise, Roster, StandingsEntry } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  export interface Team {
4
5
  conference: {
5
6
  abbr: string;
@@ -16,12 +17,12 @@ export interface Team {
16
17
  franchise_id?: number;
17
18
  }
18
19
  /** Converts a raw standings entry into a `Team`. */
19
- export declare function toTeam(teamData: JsonObject): Team;
20
+ export declare function toTeam(teamData: Partial<StandingsEntry>): Team;
20
21
  /**
21
22
  * Adds a `franchise_id` to each team that has a matching franchise. Teams
22
23
  * without a match are returned unchanged (no `franchise_id` key).
23
24
  */
24
- export declare function withFranchiseIds(teams: readonly Team[], franchises: readonly JsonObject[]): Team[];
25
+ export declare function withFranchiseIds(teams: readonly Team[], franchises: readonly Pick<Franchise, 'id' | 'fullName'>[]): Team[];
25
26
  /**
26
27
  * Get a list of all NHL teams with conference, division, and franchise info.
27
28
  *
@@ -31,9 +32,9 @@ export declare function withFranchiseIds(teams: readonly Team[], franchises: rea
31
32
  * @param params.date Date in YYYY-MM-DD format. Defaults to "now".
32
33
  * @example await client.teams.teams()
33
34
  */
34
- export declare const teams: (ctx: Context, { date }?: {
35
+ export declare function teams(ctx: Context, { date }?: {
35
36
  date?: string;
36
- }) => Promise<Team[]>;
37
+ }): Promise<Team[]>;
37
38
  /**
38
39
  * Get the roster for the given team and season.
39
40
  *
@@ -41,16 +42,16 @@ export declare const teams: (ctx: Context, { date }?: {
41
42
  * @param params.season Season in YYYYYYYY format, e.g. 20232024
42
43
  * @example https://api-web.nhle.com/v1/roster/BUF/20232024
43
44
  */
44
- export declare const teamRoster: (ctx: Context, { teamAbbr, season }: {
45
+ export declare function teamRoster(ctx: Context, { teamAbbr, season }: {
45
46
  teamAbbr: string;
46
47
  season: Id;
47
- }) => Promise<JsonObject>;
48
+ }): Promise<Roster>;
48
49
  /**
49
50
  * Get a list of all past and current NHL franchises.
50
51
  *
51
52
  * @example https://api.nhle.com/stats/rest/en/franchise
52
53
  */
53
- export declare const franchises: (ctx: Context) => Promise<JsonObject[]>;
54
+ export declare function franchises(ctx: Context): Promise<Franchise[]>;
54
55
  export declare const teamsApi: {
55
56
  readonly teams: typeof teams;
56
57
  readonly teamRoster: typeof teamRoster;