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,184 @@
|
|
|
1
|
+
import { Endpoint } from '#src/http-client.mjs';
|
|
2
|
+
/** "<path>/<id>/now" when no season is given, else "<path>/<id>/<season>/<gameType>". */
|
|
3
|
+
function edgeResource(path, id, { season, gameType = 2 }) {
|
|
4
|
+
const base = id === undefined ? path : `${path}/${id}`;
|
|
5
|
+
if (season === undefined || season === null) {
|
|
6
|
+
return `${base}/now`;
|
|
7
|
+
}
|
|
8
|
+
return `${base}/${season}/${gameType}`;
|
|
9
|
+
}
|
|
10
|
+
async function getEdge(ctx, path, id, params) {
|
|
11
|
+
return (await ctx.get(Endpoint.API_WEB_V1, edgeResource(path, id, params))).json();
|
|
12
|
+
}
|
|
13
|
+
// ========================
|
|
14
|
+
// SKATER ENDPOINTS
|
|
15
|
+
// ========================
|
|
16
|
+
/**
|
|
17
|
+
* Get NHL EDGE skater detail statistics for a specific player.
|
|
18
|
+
*
|
|
19
|
+
* @example await client.edge.skaterDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
20
|
+
*/
|
|
21
|
+
export const skaterDetail = async (ctx, params) => getEdge(ctx, 'edge/skater-detail', params.playerId, params);
|
|
22
|
+
/**
|
|
23
|
+
* Get NHL EDGE shot speed details for a specific skater.
|
|
24
|
+
*
|
|
25
|
+
* @example await client.edge.skaterShotSpeedDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
26
|
+
*/
|
|
27
|
+
export const skaterShotSpeedDetail = async (ctx, params) => getEdge(ctx, 'edge/skater-shot-speed-detail', params.playerId, params);
|
|
28
|
+
/**
|
|
29
|
+
* Get NHL EDGE skating speed details for a specific skater.
|
|
30
|
+
*
|
|
31
|
+
* @example await client.edge.skaterSkatingSpeedDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
32
|
+
*/
|
|
33
|
+
export const skaterSkatingSpeedDetail = async (ctx, params) => getEdge(ctx, 'edge/skater-skating-speed-detail', params.playerId, params);
|
|
34
|
+
/**
|
|
35
|
+
* Get NHL EDGE shot location details for a specific skater.
|
|
36
|
+
*
|
|
37
|
+
* @example await client.edge.skaterShotLocationDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
38
|
+
*/
|
|
39
|
+
export const skaterShotLocationDetail = async (ctx, params) => getEdge(ctx, 'edge/skater-shot-location-detail', params.playerId, params);
|
|
40
|
+
/**
|
|
41
|
+
* Get NHL EDGE skating distance details for a specific skater.
|
|
42
|
+
*
|
|
43
|
+
* @example await client.edge.skaterSkatingDistanceDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
44
|
+
*/
|
|
45
|
+
export const skaterSkatingDistanceDetail = async (ctx, params) => getEdge(ctx, 'edge/skater-skating-distance-detail', params.playerId, params);
|
|
46
|
+
/**
|
|
47
|
+
* Get NHL EDGE comparison statistics for a specific skater.
|
|
48
|
+
*
|
|
49
|
+
* @example await client.edge.skaterComparison({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
50
|
+
*/
|
|
51
|
+
export const skaterComparison = async (ctx, params) => getEdge(ctx, 'edge/skater-comparison', params.playerId, params);
|
|
52
|
+
/**
|
|
53
|
+
* Get NHL EDGE zone time details for a specific skater.
|
|
54
|
+
*
|
|
55
|
+
* @example await client.edge.skaterZoneTime({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
56
|
+
*/
|
|
57
|
+
export const skaterZoneTime = async (ctx, params) => getEdge(ctx, 'edge/skater-zone-time', params.playerId, params);
|
|
58
|
+
/**
|
|
59
|
+
* Get NHL EDGE skater landing page data.
|
|
60
|
+
*
|
|
61
|
+
* @example await client.edge.skaterLanding({ season: '20232024' })
|
|
62
|
+
*/
|
|
63
|
+
export const skaterLanding = async (ctx, params = {}) => getEdge(ctx, 'edge/skater-landing', undefined, params);
|
|
64
|
+
/**
|
|
65
|
+
* Get NHL CAT (Catch All Tracking) EDGE skater details.
|
|
66
|
+
*
|
|
67
|
+
* @example await client.edge.catSkaterDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
68
|
+
*/
|
|
69
|
+
export const catSkaterDetail = async (ctx, params) => getEdge(ctx, 'cat/edge/skater-detail', params.playerId, params);
|
|
70
|
+
// ========================
|
|
71
|
+
// GOALIE ENDPOINTS
|
|
72
|
+
// ========================
|
|
73
|
+
/**
|
|
74
|
+
* Get NHL EDGE goalie detail statistics for a specific player.
|
|
75
|
+
*
|
|
76
|
+
* @example await client.edge.goalieDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
77
|
+
*/
|
|
78
|
+
export const goalieDetail = async (ctx, params) => getEdge(ctx, 'edge/goalie-detail', params.playerId, params);
|
|
79
|
+
/**
|
|
80
|
+
* Get NHL EDGE shot location details for a specific goalie.
|
|
81
|
+
*
|
|
82
|
+
* @example await client.edge.goalieShotLocationDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
83
|
+
*/
|
|
84
|
+
export const goalieShotLocationDetail = async (ctx, params) => getEdge(ctx, 'edge/goalie-shot-location-detail', params.playerId, params);
|
|
85
|
+
/**
|
|
86
|
+
* Get NHL EDGE 5v5 performance details for a specific goalie.
|
|
87
|
+
*
|
|
88
|
+
* @example await client.edge.goalie5v5Detail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
89
|
+
*/
|
|
90
|
+
export const goalie5v5Detail = async (ctx, params) => getEdge(ctx, 'edge/goalie-5v5-detail', params.playerId, params);
|
|
91
|
+
/**
|
|
92
|
+
* Get NHL EDGE comparison statistics for a specific goalie.
|
|
93
|
+
*
|
|
94
|
+
* @example await client.edge.goalieComparison({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
95
|
+
*/
|
|
96
|
+
export const goalieComparison = async (ctx, params) => getEdge(ctx, 'edge/goalie-comparison', params.playerId, params);
|
|
97
|
+
/**
|
|
98
|
+
* Get NHL EDGE save percentage details for a specific goalie.
|
|
99
|
+
*
|
|
100
|
+
* @example await client.edge.goalieSavePercentageDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
101
|
+
*/
|
|
102
|
+
export const goalieSavePercentageDetail = async (ctx, params) => getEdge(ctx, 'edge/goalie-save-percentage-detail', params.playerId, params);
|
|
103
|
+
/**
|
|
104
|
+
* Get NHL EDGE goalie landing page data.
|
|
105
|
+
*
|
|
106
|
+
* @example await client.edge.goalieLanding({ season: '20232024' })
|
|
107
|
+
*/
|
|
108
|
+
export const goalieLanding = async (ctx, params = {}) => getEdge(ctx, 'edge/goalie-landing', undefined, params);
|
|
109
|
+
/**
|
|
110
|
+
* Get NHL CAT (Catch All Tracking) EDGE goalie details.
|
|
111
|
+
*
|
|
112
|
+
* @example await client.edge.catGoalieDetail({ playerId: 8478402, season: '20232024', gameType: 2 })
|
|
113
|
+
*/
|
|
114
|
+
export const catGoalieDetail = async (ctx, params) => getEdge(ctx, 'cat/edge/goalie-detail', params.playerId, params);
|
|
115
|
+
// ========================
|
|
116
|
+
// TEAM ENDPOINTS
|
|
117
|
+
// ========================
|
|
118
|
+
/**
|
|
119
|
+
* Get NHL EDGE team detail statistics for a specific team.
|
|
120
|
+
*
|
|
121
|
+
* @example await client.edge.teamDetail({ teamId: 10 })
|
|
122
|
+
*/
|
|
123
|
+
export const teamDetail = async (ctx, params) => getEdge(ctx, 'edge/team-detail', params.teamId, params);
|
|
124
|
+
/**
|
|
125
|
+
* Get NHL EDGE skating distance details for a specific team.
|
|
126
|
+
*
|
|
127
|
+
* @example await client.edge.teamSkatingDistanceDetail({ teamId: 10 })
|
|
128
|
+
*/
|
|
129
|
+
export const teamSkatingDistanceDetail = async (ctx, params) => getEdge(ctx, 'edge/team-skating-distance-detail', params.teamId, params);
|
|
130
|
+
/**
|
|
131
|
+
* Get NHL EDGE zone time details for a specific team.
|
|
132
|
+
*
|
|
133
|
+
* @example await client.edge.teamZoneTimeDetails({ teamId: 10 })
|
|
134
|
+
*/
|
|
135
|
+
export const teamZoneTimeDetails = async (ctx, params) => getEdge(ctx, 'edge/team-zone-time-details', params.teamId, params);
|
|
136
|
+
/**
|
|
137
|
+
* Get NHL EDGE shot location details for a specific team.
|
|
138
|
+
*
|
|
139
|
+
* @example await client.edge.teamShotLocationDetail({ teamId: 10 })
|
|
140
|
+
*/
|
|
141
|
+
export const teamShotLocationDetail = async (ctx, params) => getEdge(ctx, 'edge/team-shot-location-detail', params.teamId, params);
|
|
142
|
+
/**
|
|
143
|
+
* Get NHL EDGE team landing page data.
|
|
144
|
+
*
|
|
145
|
+
* @example await client.edge.teamLanding({ season: '20232024' })
|
|
146
|
+
*/
|
|
147
|
+
export const teamLanding = async (ctx, params = {}) => getEdge(ctx, 'edge/team-landing', undefined, params);
|
|
148
|
+
/**
|
|
149
|
+
* Get NHL EDGE shot speed details for a specific team.
|
|
150
|
+
*
|
|
151
|
+
* @example await client.edge.teamShotSpeedDetail({ teamId: 10 })
|
|
152
|
+
*/
|
|
153
|
+
export const teamShotSpeedDetail = async (ctx, params) => getEdge(ctx, 'edge/team-shot-speed-detail', params.teamId, params);
|
|
154
|
+
/**
|
|
155
|
+
* Get NHL EDGE skating speed details for a specific team.
|
|
156
|
+
*
|
|
157
|
+
* @example await client.edge.teamSkatingSpeedDetail({ teamId: 10 })
|
|
158
|
+
*/
|
|
159
|
+
export const teamSkatingSpeedDetail = async (ctx, params) => getEdge(ctx, 'edge/team-skating-speed-detail', params.teamId, params);
|
|
160
|
+
export const edgeApi = {
|
|
161
|
+
skaterDetail,
|
|
162
|
+
skaterShotSpeedDetail,
|
|
163
|
+
skaterSkatingSpeedDetail,
|
|
164
|
+
skaterShotLocationDetail,
|
|
165
|
+
skaterSkatingDistanceDetail,
|
|
166
|
+
skaterComparison,
|
|
167
|
+
skaterZoneTime,
|
|
168
|
+
skaterLanding,
|
|
169
|
+
catSkaterDetail,
|
|
170
|
+
goalieDetail,
|
|
171
|
+
goalieShotLocationDetail,
|
|
172
|
+
goalie5v5Detail,
|
|
173
|
+
goalieComparison,
|
|
174
|
+
goalieSavePercentageDetail,
|
|
175
|
+
goalieLanding,
|
|
176
|
+
catGoalieDetail,
|
|
177
|
+
teamDetail,
|
|
178
|
+
teamSkatingDistanceDetail,
|
|
179
|
+
teamZoneTimeDetails,
|
|
180
|
+
teamShotLocationDetail,
|
|
181
|
+
teamLanding,
|
|
182
|
+
teamShotSpeedDetail,
|
|
183
|
+
teamSkatingSpeedDetail,
|
|
184
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Context } from '#src/context.mjs';
|
|
2
|
+
import type { Boxscore, DailyScores, GameLanding, GameStory, PlayByPlay, RightRail, ShiftChart } from '#src/types/index.mjs';
|
|
3
|
+
import type { Id } from '#src/utils.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Get the full boxscore for a specific NHL game, including team scores,
|
|
6
|
+
* shots on goal, and per-player stats.
|
|
7
|
+
*
|
|
8
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
9
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/boxscore
|
|
10
|
+
*/
|
|
11
|
+
export declare const boxscore: (ctx: Context, { gameId }: {
|
|
12
|
+
gameId: Id;
|
|
13
|
+
}) => Promise<Boxscore>;
|
|
14
|
+
/**
|
|
15
|
+
* Get the full play-by-play feed for a specific NHL game, containing every
|
|
16
|
+
* recorded event (shots, hits, faceoffs, goals, penalties...).
|
|
17
|
+
*
|
|
18
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
19
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/play-by-play
|
|
20
|
+
*/
|
|
21
|
+
export declare const playByPlay: (ctx: Context, { gameId }: {
|
|
22
|
+
gameId: Id;
|
|
23
|
+
}) => Promise<PlayByPlay>;
|
|
24
|
+
/**
|
|
25
|
+
* Get the landing-page summary for a specific NHL game, including scoring by
|
|
26
|
+
* period, three stars and penalties.
|
|
27
|
+
*
|
|
28
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
29
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/landing
|
|
30
|
+
*/
|
|
31
|
+
export declare const matchUp: (ctx: Context, { gameId }: {
|
|
32
|
+
gameId: Id;
|
|
33
|
+
}) => Promise<GameLanding>;
|
|
34
|
+
/**
|
|
35
|
+
* Get scores and game states for all NHL games on a given date. Returns the
|
|
36
|
+
* current day's scores when no date is supplied.
|
|
37
|
+
*
|
|
38
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
39
|
+
* @example https://api-web.nhle.com/v1/score/2023-10-15
|
|
40
|
+
*/
|
|
41
|
+
export declare const dailyScores: (ctx: Context, { date }?: {
|
|
42
|
+
date?: string;
|
|
43
|
+
}) => Promise<DailyScores>;
|
|
44
|
+
/**
|
|
45
|
+
* Get individual player shift data for a specific game, including start/end
|
|
46
|
+
* times and durations.
|
|
47
|
+
*
|
|
48
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
49
|
+
* @param params.excludes Fields to exclude from the response. Defaults to ["eventDetails"].
|
|
50
|
+
* @example https://api.nhle.com/stats/rest/en/shiftcharts?cayenneExp=gameId=2023020280 and ...
|
|
51
|
+
*/
|
|
52
|
+
export declare const shiftChartData: (ctx: Context, { gameId, excludes }: {
|
|
53
|
+
gameId: Id;
|
|
54
|
+
excludes?: string[];
|
|
55
|
+
}) => Promise<ShiftChart>;
|
|
56
|
+
/**
|
|
57
|
+
* Get the season-series record and contextual stats for a specific game,
|
|
58
|
+
* including team season stats and last games.
|
|
59
|
+
*
|
|
60
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
61
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/right-rail
|
|
62
|
+
*/
|
|
63
|
+
export declare const seasonSeriesMatchup: (ctx: Context, { gameId }: {
|
|
64
|
+
gameId: Id;
|
|
65
|
+
}) => Promise<RightRail>;
|
|
66
|
+
/**
|
|
67
|
+
* Get the narrative game story for a specific game, including scoring
|
|
68
|
+
* summaries, three stars and team game stats.
|
|
69
|
+
*
|
|
70
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
71
|
+
* @example https://api-web.nhle.com/v1/wsc/game-story/2023020280
|
|
72
|
+
*/
|
|
73
|
+
export declare const gameStory: (ctx: Context, { gameId }: {
|
|
74
|
+
gameId: Id;
|
|
75
|
+
}) => Promise<GameStory>;
|
|
76
|
+
export declare const gameCenterApi: {
|
|
77
|
+
readonly boxscore: typeof boxscore;
|
|
78
|
+
readonly playByPlay: typeof playByPlay;
|
|
79
|
+
readonly matchUp: typeof matchUp;
|
|
80
|
+
readonly dailyScores: typeof dailyScores;
|
|
81
|
+
readonly shiftChartData: typeof shiftChartData;
|
|
82
|
+
readonly seasonSeriesMatchup: typeof seasonSeriesMatchup;
|
|
83
|
+
readonly gameStory: typeof gameStory;
|
|
84
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Endpoint } from '#src/http-client.mjs';
|
|
2
|
+
async function getWeb(ctx, resource) {
|
|
3
|
+
return (await ctx.get(Endpoint.API_WEB_V1, resource)).json();
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Get the full boxscore for a specific NHL game, including team scores,
|
|
7
|
+
* shots on goal, and per-player stats.
|
|
8
|
+
*
|
|
9
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
10
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/boxscore
|
|
11
|
+
*/
|
|
12
|
+
export const boxscore = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/boxscore`);
|
|
13
|
+
/**
|
|
14
|
+
* Get the full play-by-play feed for a specific NHL game, containing every
|
|
15
|
+
* recorded event (shots, hits, faceoffs, goals, penalties...).
|
|
16
|
+
*
|
|
17
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
18
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/play-by-play
|
|
19
|
+
*/
|
|
20
|
+
export const playByPlay = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/play-by-play`);
|
|
21
|
+
/**
|
|
22
|
+
* Get the landing-page summary for a specific NHL game, including scoring by
|
|
23
|
+
* period, three stars and penalties.
|
|
24
|
+
*
|
|
25
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
26
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/landing
|
|
27
|
+
*/
|
|
28
|
+
export const matchUp = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/landing`);
|
|
29
|
+
/**
|
|
30
|
+
* Get scores and game states for all NHL games on a given date. Returns the
|
|
31
|
+
* current day's scores when no date is supplied.
|
|
32
|
+
*
|
|
33
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
34
|
+
* @example https://api-web.nhle.com/v1/score/2023-10-15
|
|
35
|
+
*/
|
|
36
|
+
export const dailyScores = async (ctx, { date } = {}) => getWeb(ctx, `score/${date ? date : 'now'}`);
|
|
37
|
+
/**
|
|
38
|
+
* Get individual player shift data for a specific game, including start/end
|
|
39
|
+
* times and durations.
|
|
40
|
+
*
|
|
41
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
42
|
+
* @param params.excludes Fields to exclude from the response. Defaults to ["eventDetails"].
|
|
43
|
+
* @example https://api.nhle.com/stats/rest/en/shiftcharts?cayenneExp=gameId=2023020280 and ...
|
|
44
|
+
*/
|
|
45
|
+
export const shiftChartData = async (ctx, { gameId, excludes = ['eventDetails'] }) => {
|
|
46
|
+
const excludeP = excludes.join(',');
|
|
47
|
+
const exprP = `gameId=${gameId} and ((duration != '00:00' and typeCode = 517) or typeCode != 517 )`;
|
|
48
|
+
return (await ctx.get(Endpoint.API_STATS, `en/shiftcharts?cayenneExp=${exprP}&exclude=${excludeP}`)).json();
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Get the season-series record and contextual stats for a specific game,
|
|
52
|
+
* including team season stats and last games.
|
|
53
|
+
*
|
|
54
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
55
|
+
* @example https://api-web.nhle.com/v1/gamecenter/2023020280/right-rail
|
|
56
|
+
*/
|
|
57
|
+
export const seasonSeriesMatchup = async (ctx, { gameId }) => getWeb(ctx, `gamecenter/${gameId}/right-rail`);
|
|
58
|
+
/**
|
|
59
|
+
* Get the narrative game story for a specific game, including scoring
|
|
60
|
+
* summaries, three stars and team game stats.
|
|
61
|
+
*
|
|
62
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
63
|
+
* @example https://api-web.nhle.com/v1/wsc/game-story/2023020280
|
|
64
|
+
*/
|
|
65
|
+
export const gameStory = async (ctx, { gameId }) => getWeb(ctx, `wsc/game-story/${gameId}`);
|
|
66
|
+
export const gameCenterApi = {
|
|
67
|
+
boxscore,
|
|
68
|
+
playByPlay,
|
|
69
|
+
matchUp,
|
|
70
|
+
dailyScores,
|
|
71
|
+
shiftChartData,
|
|
72
|
+
seasonSeriesMatchup,
|
|
73
|
+
gameStory,
|
|
74
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Context } from '#src/context.mjs';
|
|
2
|
+
import type { AllPlayersEntry, PlayerSummaryStatistics } from '#src/types/index.mjs';
|
|
3
|
+
import type { Id } from '#src/utils.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Gets all game IDs for a specified season by querying every team's
|
|
6
|
+
* schedule. Games appear once per participating team, so ids may repeat.
|
|
7
|
+
*
|
|
8
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
9
|
+
* @param params.gameTypes Only include these game types (1=Preseason, 2=Regular, 3=Playoffs). Defaults to all.
|
|
10
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
|
|
11
|
+
* @example await client.helpers.gameIdsBySeason({ season: '20232024', gameTypes: [2] })
|
|
12
|
+
*/
|
|
13
|
+
export declare const gameIdsBySeason: (ctx: Context, { season, gameTypes, apiSleepRate, }: {
|
|
14
|
+
season: Id;
|
|
15
|
+
gameTypes?: number[];
|
|
16
|
+
apiSleepRate?: number;
|
|
17
|
+
}) => Promise<number[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Gets every rostered player across all NHL teams for a given season. Each
|
|
20
|
+
* player gets a `team` abbreviation and flattened `firstName` / `lastName`.
|
|
21
|
+
*
|
|
22
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
23
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 0.5.
|
|
24
|
+
* @example await client.helpers.allPlayers({ season: '20232024' })
|
|
25
|
+
*/
|
|
26
|
+
export declare const allPlayers: (ctx: Context, { season, apiSleepRate }: {
|
|
27
|
+
season: Id;
|
|
28
|
+
apiSleepRate?: number;
|
|
29
|
+
}) => Promise<AllPlayersEntry[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Gets summary statistics for every skater in a given season, merged with
|
|
32
|
+
* the roster info from `allPlayers` (stat fields win on key collisions).
|
|
33
|
+
* Stat entries without a matching rostered player are included as-is.
|
|
34
|
+
*
|
|
35
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
36
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
|
|
37
|
+
* @example await client.helpers.allPlayersSummaryStatistics({ season: '20232024' })
|
|
38
|
+
*/
|
|
39
|
+
export declare const allPlayersSummaryStatistics: (ctx: Context, { season, apiSleepRate }: {
|
|
40
|
+
season: Id;
|
|
41
|
+
apiSleepRate?: number;
|
|
42
|
+
}) => Promise<PlayerSummaryStatistics[]>;
|
|
43
|
+
export declare const helpersApi: {
|
|
44
|
+
readonly gameIdsBySeason: typeof gameIdsBySeason;
|
|
45
|
+
readonly allPlayers: typeof allPlayers;
|
|
46
|
+
readonly allPlayersSummaryStatistics: typeof allPlayersSummaryStatistics;
|
|
47
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { buildQuery } from '#src/api/query/builder.mjs';
|
|
2
|
+
import { filter } from '#src/api/query/filters.mjs';
|
|
3
|
+
import { teamSeasonSchedule } from '#src/api/schedule.mjs';
|
|
4
|
+
import { skaterStatsWithQueryContext } from '#src/api/stats.mjs';
|
|
5
|
+
import { teams as fetchTeams, teamRoster } from '#src/api/teams.mjs';
|
|
6
|
+
/**
|
|
7
|
+
* Gets all game IDs for a specified season by querying every team's
|
|
8
|
+
* schedule. Games appear once per participating team, so ids may repeat.
|
|
9
|
+
*
|
|
10
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
11
|
+
* @param params.gameTypes Only include these game types (1=Preseason, 2=Regular, 3=Playoffs). Defaults to all.
|
|
12
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
|
|
13
|
+
* @example await client.helpers.gameIdsBySeason({ season: '20232024', gameTypes: [2] })
|
|
14
|
+
*/
|
|
15
|
+
export const gameIdsBySeason = async (ctx, { season, gameTypes, apiSleepRate = 1, }) => {
|
|
16
|
+
const teams = await fetchTeams(ctx);
|
|
17
|
+
const gameIds = [];
|
|
18
|
+
for (const team of teams) {
|
|
19
|
+
const teamAbbr = team.abbr ?? '';
|
|
20
|
+
if (!teamAbbr) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
await ctx.sleep(apiSleepRate);
|
|
24
|
+
const schedule = await teamSeasonSchedule(ctx, { teamAbbr, season });
|
|
25
|
+
const games = schedule.games ?? [];
|
|
26
|
+
for (const game of games) {
|
|
27
|
+
const gameType = game.gameType;
|
|
28
|
+
const gameId = game.id;
|
|
29
|
+
if (gameId &&
|
|
30
|
+
(!gameTypes || gameTypes.length === 0 || gameTypes.includes(gameType))) {
|
|
31
|
+
gameIds.push(gameId);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return gameIds;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Gets every rostered player across all NHL teams for a given season. Each
|
|
39
|
+
* player gets a `team` abbreviation and flattened `firstName` / `lastName`.
|
|
40
|
+
*
|
|
41
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
42
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 0.5.
|
|
43
|
+
* @example await client.helpers.allPlayers({ season: '20232024' })
|
|
44
|
+
*/
|
|
45
|
+
export const allPlayers = async (ctx, { season, apiSleepRate = 0.5 }) => {
|
|
46
|
+
const teams = await fetchTeams(ctx);
|
|
47
|
+
console.error('Fetching all player base stats. This may take a while...');
|
|
48
|
+
const outData = [];
|
|
49
|
+
for (const team of teams) {
|
|
50
|
+
await ctx.sleep(apiSleepRate);
|
|
51
|
+
const players = await teamRoster(ctx, { teamAbbr: team.abbr, season });
|
|
52
|
+
for (const player of [
|
|
53
|
+
...players.forwards,
|
|
54
|
+
...players.defensemen,
|
|
55
|
+
...players.goalies,
|
|
56
|
+
]) {
|
|
57
|
+
outData.push({
|
|
58
|
+
...player,
|
|
59
|
+
team: team.abbr,
|
|
60
|
+
firstName: player.firstName.default,
|
|
61
|
+
lastName: player.lastName.default,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return outData;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Gets summary statistics for every skater in a given season, merged with
|
|
69
|
+
* the roster info from `allPlayers` (stat fields win on key collisions).
|
|
70
|
+
* Stat entries without a matching rostered player are included as-is.
|
|
71
|
+
*
|
|
72
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
73
|
+
* @param params.apiSleepRate Seconds to sleep between team requests. Defaults to 1.
|
|
74
|
+
* @example await client.helpers.allPlayersSummaryStatistics({ season: '20232024' })
|
|
75
|
+
*/
|
|
76
|
+
export const allPlayersSummaryStatistics = async (ctx, { season, apiSleepRate = 1 }) => {
|
|
77
|
+
console.error('WARNING: This method will take a while to run. In the event of rate limiting, you may need to increase the api_sleep_rate.');
|
|
78
|
+
const players = await allPlayers(ctx, { season, apiSleepRate });
|
|
79
|
+
const teams = await fetchTeams(ctx);
|
|
80
|
+
const outData = [];
|
|
81
|
+
for (const team of teams) {
|
|
82
|
+
await ctx.sleep(apiSleepRate);
|
|
83
|
+
const context = buildQuery([
|
|
84
|
+
filter.franchise(team.franchise_id),
|
|
85
|
+
filter.season(season, season),
|
|
86
|
+
]);
|
|
87
|
+
const data = await skaterStatsWithQueryContext(ctx, {
|
|
88
|
+
reportType: 'summary',
|
|
89
|
+
queryContext: context,
|
|
90
|
+
aggregate: true,
|
|
91
|
+
});
|
|
92
|
+
outData.push(...(data.data ?? []));
|
|
93
|
+
}
|
|
94
|
+
const playerById = new Map(players.map((player) => [player.id, player]));
|
|
95
|
+
return outData.map((statEntry) => {
|
|
96
|
+
const player = statEntry.playerId
|
|
97
|
+
? playerById.get(statEntry.playerId)
|
|
98
|
+
: undefined;
|
|
99
|
+
return player ? { ...player, ...statEntry } : statEntry;
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
export const helpersApi = {
|
|
103
|
+
gameIdsBySeason,
|
|
104
|
+
allPlayers,
|
|
105
|
+
allPlayersSummaryStatistics,
|
|
106
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Context } from '#src/context.mjs';
|
|
2
|
+
import type { Country, DraftYear, GlossaryEntry, SeasonRules, StatsConfig } from '#src/types/index.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* Gets the full NHL glossary of statistical terms and abbreviations.
|
|
5
|
+
*
|
|
6
|
+
* @example https://api.nhle.com/stats/rest/en/glossary?sort=fullName
|
|
7
|
+
*/
|
|
8
|
+
export declare const glossary: (ctx: Context) => Promise<GlossaryEntry[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Gets the stats API configuration, including available report types and
|
|
11
|
+
* filters.
|
|
12
|
+
*
|
|
13
|
+
* @example https://api.nhle.com/stats/rest/en/config
|
|
14
|
+
*/
|
|
15
|
+
export declare const config: (ctx: Context) => Promise<StatsConfig>;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the list of countries recognized by the NHL.
|
|
18
|
+
*
|
|
19
|
+
* @example https://api.nhle.com/stats/rest/en/country
|
|
20
|
+
*/
|
|
21
|
+
export declare const countries: (ctx: Context) => Promise<Country[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Gets rules and metadata for every NHL season on record.
|
|
24
|
+
*
|
|
25
|
+
* @example https://api.nhle.com/stats/rest/en/season
|
|
26
|
+
*/
|
|
27
|
+
export declare const seasonSpecificRulesAndInfo: (ctx: Context) => Promise<SeasonRules[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the number of rounds for each NHL draft year.
|
|
30
|
+
*
|
|
31
|
+
* @example https://api.nhle.com/stats/rest/en/draft
|
|
32
|
+
*/
|
|
33
|
+
export declare const draftYearAndRounds: (ctx: Context) => Promise<DraftYear[]>;
|
|
34
|
+
export declare const miscApi: {
|
|
35
|
+
readonly glossary: typeof glossary;
|
|
36
|
+
readonly config: typeof config;
|
|
37
|
+
readonly countries: typeof countries;
|
|
38
|
+
readonly seasonSpecificRulesAndInfo: typeof seasonSpecificRulesAndInfo;
|
|
39
|
+
readonly draftYearAndRounds: typeof draftYearAndRounds;
|
|
40
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Endpoint } from '#src/http-client.mjs';
|
|
2
|
+
async function getData(ctx, resource) {
|
|
3
|
+
const response = await (await ctx.get(Endpoint.API_CORE, resource)).json();
|
|
4
|
+
return response.data ?? [];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Gets the full NHL glossary of statistical terms and abbreviations.
|
|
8
|
+
*
|
|
9
|
+
* @example https://api.nhle.com/stats/rest/en/glossary?sort=fullName
|
|
10
|
+
*/
|
|
11
|
+
export const glossary = async (ctx) => getData(ctx, 'stats/rest/en/glossary?sort=fullName');
|
|
12
|
+
/**
|
|
13
|
+
* Gets the stats API configuration, including available report types and
|
|
14
|
+
* filters.
|
|
15
|
+
*
|
|
16
|
+
* @example https://api.nhle.com/stats/rest/en/config
|
|
17
|
+
*/
|
|
18
|
+
export const config = async (ctx) => (await ctx.get(Endpoint.API_CORE, 'stats/rest/en/config')).json();
|
|
19
|
+
/**
|
|
20
|
+
* Gets the list of countries recognized by the NHL.
|
|
21
|
+
*
|
|
22
|
+
* @example https://api.nhle.com/stats/rest/en/country
|
|
23
|
+
*/
|
|
24
|
+
export const countries = async (ctx) => getData(ctx, 'stats/rest/en/country');
|
|
25
|
+
/**
|
|
26
|
+
* Gets rules and metadata for every NHL season on record.
|
|
27
|
+
*
|
|
28
|
+
* @example https://api.nhle.com/stats/rest/en/season
|
|
29
|
+
*/
|
|
30
|
+
export const seasonSpecificRulesAndInfo = async (ctx) => getData(ctx, 'stats/rest/en/season');
|
|
31
|
+
/**
|
|
32
|
+
* Gets the number of rounds for each NHL draft year.
|
|
33
|
+
*
|
|
34
|
+
* @example https://api.nhle.com/stats/rest/en/draft
|
|
35
|
+
*/
|
|
36
|
+
export const draftYearAndRounds = async (ctx) => getData(ctx, 'stats/rest/en/draft');
|
|
37
|
+
export const miscApi = {
|
|
38
|
+
glossary,
|
|
39
|
+
config,
|
|
40
|
+
countries,
|
|
41
|
+
seasonSpecificRulesAndInfo,
|
|
42
|
+
draftYearAndRounds,
|
|
43
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Context } from '#src/context.mjs';
|
|
2
|
+
import type { Prospects, Roster } from '#src/types/index.mjs';
|
|
3
|
+
import type { Id } from '#src/utils.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Gets prospects for a specific team, grouped by position.
|
|
6
|
+
*
|
|
7
|
+
* @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
|
|
8
|
+
* @example https://api-web.nhle.com/v1/prospects/BUF
|
|
9
|
+
*/
|
|
10
|
+
export declare const prospectsByTeam: (ctx: Context, { teamAbbr }: {
|
|
11
|
+
teamAbbr: string;
|
|
12
|
+
}) => Promise<Prospects>;
|
|
13
|
+
/**
|
|
14
|
+
* Gets the roster for a given team and season, grouped by position
|
|
15
|
+
* (forwards, defensemen, goalies). Same data as `teams.teamRoster`.
|
|
16
|
+
*
|
|
17
|
+
* @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
|
|
18
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
19
|
+
* @example https://api-web.nhle.com/v1/roster/BUF/20232024
|
|
20
|
+
*/
|
|
21
|
+
export declare const playersByTeam: (ctx: Context, { teamAbbr, season }: {
|
|
22
|
+
teamAbbr: string;
|
|
23
|
+
season: Id;
|
|
24
|
+
}) => Promise<Roster>;
|
|
25
|
+
export declare const playersApi: {
|
|
26
|
+
readonly prospectsByTeam: typeof prospectsByTeam;
|
|
27
|
+
readonly playersByTeam: typeof playersByTeam;
|
|
28
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Endpoint } from '#src/http-client.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Gets prospects for a specific team, grouped by position.
|
|
4
|
+
*
|
|
5
|
+
* @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
|
|
6
|
+
* @example https://api-web.nhle.com/v1/prospects/BUF
|
|
7
|
+
*/
|
|
8
|
+
export const prospectsByTeam = async (ctx, { teamAbbr }) => (await ctx.get(Endpoint.API_WEB_V1, `prospects/${teamAbbr}`)).json();
|
|
9
|
+
/**
|
|
10
|
+
* Gets the roster for a given team and season, grouped by position
|
|
11
|
+
* (forwards, defensemen, goalies). Same data as `teams.teamRoster`.
|
|
12
|
+
*
|
|
13
|
+
* @param params.teamAbbr Team abbreviation, e.g. BUF, TOR
|
|
14
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
15
|
+
* @example https://api-web.nhle.com/v1/roster/BUF/20232024
|
|
16
|
+
*/
|
|
17
|
+
export const playersByTeam = async (ctx, { teamAbbr, season }) => (await ctx.get(Endpoint.API_WEB_V1, `roster/${teamAbbr}/${season}`)).json();
|
|
18
|
+
export const playersApi = { prospectsByTeam, playersByTeam };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Filter } from '#src/api/query/filters.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* A container for query information and validation state: the constructed
|
|
4
|
+
* query string, the original filters, any validation errors and a base fact
|
|
5
|
+
* query (defaults to "gamesPlayed>=1").
|
|
6
|
+
*/
|
|
7
|
+
export interface QueryContext {
|
|
8
|
+
readonly query: string;
|
|
9
|
+
readonly filters: readonly Filter[];
|
|
10
|
+
readonly errors: readonly string[];
|
|
11
|
+
readonly factQuery: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds and validates a query string from a list of filters. Invalid
|
|
15
|
+
* filters are skipped and their errors collected; valid filters are joined
|
|
16
|
+
* with " and ".
|
|
17
|
+
*/
|
|
18
|
+
/** Fact filter `buildQuery` applies unless told otherwise. */
|
|
19
|
+
export declare const DEFAULT_FACT_QUERY = "gamesPlayed>=1";
|
|
20
|
+
export declare function buildQuery(filters: readonly Filter[], factQuery?: string): QueryContext;
|
|
21
|
+
/** True if there are no validation errors. */
|
|
22
|
+
export declare function isValidQuery(context: QueryContext): boolean;
|