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