nhl-api-ts 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -5
- package/dist/api/draft.d.mts +61 -0
- package/dist/api/draft.mjs +68 -0
- package/dist/api/edge.d.mts +198 -1
- package/dist/api/edge.mjs +207 -4
- package/dist/api/game-center.d.mts +49 -1
- package/dist/api/game-center.mjs +47 -0
- package/dist/api/misc.d.mts +115 -1
- package/dist/api/misc.mjs +147 -2
- package/dist/api/players.d.mts +55 -3
- package/dist/api/players.mjs +80 -3
- package/dist/api/query/cayenne.d.mts +4 -0
- package/dist/api/query/cayenne.mjs +13 -0
- package/dist/api/query/sorting/sorting-options.d.mts +8 -0
- package/dist/api/query/sorting/sorting-options.mjs +30 -0
- package/dist/api/schedule.d.mts +19 -6
- package/dist/api/schedule.mjs +17 -5
- package/dist/api/stats.d.mts +95 -6
- package/dist/api/stats.mjs +130 -30
- package/dist/api/teams.d.mts +43 -3
- package/dist/api/teams.mjs +51 -3
- package/dist/cli/commands.mjs +487 -22
- package/dist/http-client.d.mts +2 -1
- package/dist/http-client.mjs +8 -1
- package/dist/index.d.mts +8 -2
- package/dist/index.mjs +3 -0
- package/dist/nhl-client.d.mts +69 -14
- package/dist/nhl-client.mjs +33 -12
- package/dist/types/draft.d.mts +97 -0
- package/dist/types/draft.mjs +1 -0
- package/dist/types/edge.d.mts +299 -3
- package/dist/types/game-center.d.mts +223 -8
- package/dist/types/index.d.mts +1 -0
- package/dist/types/misc.d.mts +101 -0
- package/dist/types/misc.mjs +0 -1
- package/dist/types/players.d.mts +22 -0
- package/dist/types/schedule.d.mts +16 -0
- package/dist/types/stats.d.mts +207 -1
- package/dist/types/teams.d.mts +29 -1
- package/package.json +1 -1
package/dist/api/edge.mjs
CHANGED
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
import { Endpoint } from '#src/http-client.mjs';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/** Player positions of an EDGE top-10 leaderboard. */
|
|
3
|
+
export const EdgePositions = {
|
|
4
|
+
ALL: 'all',
|
|
5
|
+
FORWARDS: 'forwards',
|
|
6
|
+
DEFENSE: 'defense',
|
|
7
|
+
};
|
|
8
|
+
/** Game strengths of an EDGE top-10 leaderboard. */
|
|
9
|
+
export const EdgeStrengths = {
|
|
10
|
+
ALL: 'all',
|
|
11
|
+
EVEN: 'es',
|
|
12
|
+
POWER_PLAY: 'pp',
|
|
13
|
+
PENALTY_KILL: 'pk',
|
|
14
|
+
};
|
|
15
|
+
/** Rink zones; the `sortBy` of the zone time top-10s. */
|
|
16
|
+
export const EdgeZones = {
|
|
17
|
+
OFFENSIVE: 'offensive',
|
|
18
|
+
NEUTRAL: 'neutral',
|
|
19
|
+
DEFENSIVE: 'defensive',
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* "<path>/<segments...>/now" when no season is given, else
|
|
23
|
+
* "<path>/<segments...>/<season>/<gameType>".
|
|
24
|
+
*/
|
|
25
|
+
function edgeResource(path, segments, { season, gameType = 2 }) {
|
|
26
|
+
const base = [path, ...segments].join('/');
|
|
5
27
|
if (season === undefined || season === null) {
|
|
6
28
|
return `${base}/now`;
|
|
7
29
|
}
|
|
8
30
|
return `${base}/${season}/${gameType}`;
|
|
9
31
|
}
|
|
32
|
+
async function getEdgeSegments(ctx, path, segments, params) {
|
|
33
|
+
return (await ctx.get(Endpoint.API_WEB_V1, edgeResource(path, segments, params))).json();
|
|
34
|
+
}
|
|
10
35
|
async function getEdge(ctx, path, id, params) {
|
|
11
|
-
return (
|
|
36
|
+
return getEdgeSegments(ctx, path, id === undefined ? [] : [id], params);
|
|
12
37
|
}
|
|
13
38
|
// ========================
|
|
14
39
|
// SKATER ENDPOINTS
|
|
@@ -203,6 +228,169 @@ export async function teamShotSpeedDetail(ctx, params) {
|
|
|
203
228
|
export async function teamSkatingSpeedDetail(ctx, params) {
|
|
204
229
|
return getEdge(ctx, 'edge/team-skating-speed-detail', params.teamId, params);
|
|
205
230
|
}
|
|
231
|
+
// ========================
|
|
232
|
+
// LEADERBOARDS (TOP 10)
|
|
233
|
+
// ========================
|
|
234
|
+
/**
|
|
235
|
+
* Get the NHL EDGE top 10 skaters by skating distance.
|
|
236
|
+
*
|
|
237
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
238
|
+
* @param params.strength 'all' (default), 'es', 'pp' or 'pk'
|
|
239
|
+
* @param params.sortBy 'total', 'per-60', 'max-game' or 'max-period'
|
|
240
|
+
* @example https://api-web.nhle.com/v1/edge/skater-distance-top-10/all/all/total/20252026/2
|
|
241
|
+
*/
|
|
242
|
+
export async function skaterDistanceTop10(ctx, { positions = EdgePositions.ALL, strength = EdgeStrengths.ALL, sortBy, ...params }) {
|
|
243
|
+
return getEdgeSegments(ctx, 'edge/skater-distance-top-10', [positions, strength, sortBy], params);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get the NHL EDGE top 10 skaters by skating speed.
|
|
247
|
+
*
|
|
248
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
249
|
+
* @param params.sortBy 'max', 'over-22', '20-22' or '18-20' (bursts in mph)
|
|
250
|
+
* @example https://api-web.nhle.com/v1/edge/skater-speed-top-10/all/max/20252026/2
|
|
251
|
+
*/
|
|
252
|
+
export async function skaterSpeedTop10(ctx, { positions = EdgePositions.ALL, sortBy, ...params }) {
|
|
253
|
+
return getEdgeSegments(ctx, 'edge/skater-speed-top-10', [positions, sortBy], params);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get the NHL EDGE top 10 skaters by zone time.
|
|
257
|
+
*
|
|
258
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
259
|
+
* @param params.strength 'all' (default), 'es', 'pp' or 'pk'
|
|
260
|
+
* @param params.sortBy Zone: 'offensive', 'neutral' or 'defensive'. See `EdgeZones`.
|
|
261
|
+
* @example https://api-web.nhle.com/v1/edge/skater-zone-time-top-10/all/all/offensive/20252026/2
|
|
262
|
+
*/
|
|
263
|
+
export async function skaterZoneTimeTop10(ctx, { positions = EdgePositions.ALL, strength = EdgeStrengths.ALL, sortBy, ...params }) {
|
|
264
|
+
return getEdgeSegments(ctx, 'edge/skater-zone-time-top-10', [positions, strength, sortBy], params);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get the NHL EDGE top 10 skaters by shot speed.
|
|
268
|
+
*
|
|
269
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
270
|
+
* @param params.sortBy 'max', 'over-100', '90-99', '80-89' or '70-79' (attempts in mph)
|
|
271
|
+
* @example https://api-web.nhle.com/v1/edge/skater-shot-speed-top-10/all/max/20252026/2
|
|
272
|
+
*/
|
|
273
|
+
export async function skaterShotSpeedTop10(ctx, { positions = EdgePositions.ALL, sortBy, ...params }) {
|
|
274
|
+
return getEdgeSegments(ctx, 'edge/skater-shot-speed-top-10', [positions, sortBy], params);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get the NHL EDGE top 10 skaters by shot location. `sortBy` comes before
|
|
278
|
+
* `category` in the URL (the NHL-API-Reference has them the other way round,
|
|
279
|
+
* which 404s).
|
|
280
|
+
*
|
|
281
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'. 'F' / 'D' are a 404 here.
|
|
282
|
+
* @param params.sortBy 'sog', 'goals' or 'shooting-pctg'
|
|
283
|
+
* @param params.category 'all' (default), 'high', 'mid' or 'long'
|
|
284
|
+
* @example https://api-web.nhle.com/v1/edge/skater-shot-location-top-10/all/sog/all/20252026/2
|
|
285
|
+
*/
|
|
286
|
+
export async function skaterShotLocationTop10(ctx, { positions = EdgePositions.ALL, sortBy, category = 'all', ...params }) {
|
|
287
|
+
return getEdgeSegments(ctx, 'edge/skater-shot-location-top-10', [positions, sortBy, category], params);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get the NHL EDGE top 10 goalies by 5v5 performance.
|
|
291
|
+
*
|
|
292
|
+
* @param params.sortBy 'save-pctg', 'save-pctg-close', 'shots' or 'shots-per-60'
|
|
293
|
+
* @example https://api-web.nhle.com/v1/edge/goalie-5v5-top-10/save-pctg/20252026/2
|
|
294
|
+
*/
|
|
295
|
+
export async function goalie5v5Top10(ctx, { sortBy, ...params }) {
|
|
296
|
+
return getEdgeSegments(ctx, 'edge/goalie-5v5-top-10', [sortBy], params);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get the NHL EDGE top 10 goalies by shot location.
|
|
300
|
+
*
|
|
301
|
+
* @param params.sortBy 'save-pctg', 'saves', 'goals-against' or 'shots-against'
|
|
302
|
+
* @param params.category 'all' (default), 'high', 'mid' or 'long'
|
|
303
|
+
* @example https://api-web.nhle.com/v1/edge/goalie-shot-location-top-10/save-pctg/all/20252026/2
|
|
304
|
+
*/
|
|
305
|
+
export async function goalieShotLocationTop10(ctx, { sortBy, category = 'all', ...params }) {
|
|
306
|
+
return getEdgeSegments(ctx, 'edge/goalie-shot-location-top-10', [sortBy, category], params);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get the NHL EDGE top 10 goalies by games above a .900 save percentage.
|
|
310
|
+
*
|
|
311
|
+
* @param params.sortBy 'games' (count) or 'pctg' (share of games played)
|
|
312
|
+
* @example https://api-web.nhle.com/v1/edge/goalie-edge-save-pctg-top-10/games/20252026/2
|
|
313
|
+
*/
|
|
314
|
+
export async function goalieSavePercentageTop10(ctx, { sortBy, ...params }) {
|
|
315
|
+
return getEdgeSegments(ctx, 'edge/goalie-edge-save-pctg-top-10', [sortBy], params);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Get the NHL EDGE top 10 teams by skating distance.
|
|
319
|
+
*
|
|
320
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
321
|
+
* @param params.strength 'all' (default), 'es', 'pp' or 'pk'
|
|
322
|
+
* @param params.sortBy 'total', 'per-60', 'max-game' or 'max-period'
|
|
323
|
+
* @example https://api-web.nhle.com/v1/edge/team-skating-distance-top-10/all/all/total/20252026/2
|
|
324
|
+
*/
|
|
325
|
+
export async function teamSkatingDistanceTop10(ctx, { positions = EdgePositions.ALL, strength = EdgeStrengths.ALL, sortBy, ...params }) {
|
|
326
|
+
return getEdgeSegments(ctx, 'edge/team-skating-distance-top-10', [positions, strength, sortBy], params);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get the NHL EDGE top 10 teams by skating speed.
|
|
330
|
+
*
|
|
331
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
332
|
+
* @param params.sortBy 'max', 'over-22', '20-22' or '18-20' (bursts in mph)
|
|
333
|
+
* @example https://api-web.nhle.com/v1/edge/team-skating-speed-top-10/all/max/20252026/2
|
|
334
|
+
*/
|
|
335
|
+
export async function teamSkatingSpeedTop10(ctx, { positions = EdgePositions.ALL, sortBy, ...params }) {
|
|
336
|
+
return getEdgeSegments(ctx, 'edge/team-skating-speed-top-10', [positions, sortBy], params);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Get the NHL EDGE top 10 teams by zone time. There is no `positions` slot.
|
|
340
|
+
*
|
|
341
|
+
* @param params.strength 'all' (default), 'es', 'pp' or 'pk'
|
|
342
|
+
* @param params.sortBy Zone: 'offensive', 'neutral' or 'defensive'. See `EdgeZones`.
|
|
343
|
+
* @example https://api-web.nhle.com/v1/edge/team-zone-time-top-10/es/offensive/20242025/2
|
|
344
|
+
*/
|
|
345
|
+
export async function teamZoneTimeTop10(ctx, { strength = EdgeStrengths.ALL, sortBy, ...params }) {
|
|
346
|
+
return getEdgeSegments(ctx, 'edge/team-zone-time-top-10', [strength, sortBy], params);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get the NHL EDGE top 10 teams by shot speed.
|
|
350
|
+
*
|
|
351
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'
|
|
352
|
+
* @param params.sortBy 'max', 'over-100', '90-99', '80-89' or '70-79' (attempts in mph)
|
|
353
|
+
* @example https://api-web.nhle.com/v1/edge/team-shot-speed-top-10/all/max/20252026/2
|
|
354
|
+
*/
|
|
355
|
+
export async function teamShotSpeedTop10(ctx, { positions = EdgePositions.ALL, sortBy, ...params }) {
|
|
356
|
+
return getEdgeSegments(ctx, 'edge/team-shot-speed-top-10', [positions, sortBy], params);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get the NHL EDGE top 10 teams by shot location. `sortBy` comes before
|
|
360
|
+
* `category` in the URL (the NHL-API-Reference has them the other way round,
|
|
361
|
+
* which 404s).
|
|
362
|
+
*
|
|
363
|
+
* @param params.positions 'all' (default), 'forwards' or 'defense'. 'F' / 'D' are a 404 here.
|
|
364
|
+
* @param params.sortBy 'sog', 'goals' or 'shooting-pctg'
|
|
365
|
+
* @param params.category 'all' (default), 'high', 'mid' or 'long'
|
|
366
|
+
* @example https://api-web.nhle.com/v1/edge/team-shot-location-top-10/all/sog/all/20252026/2
|
|
367
|
+
*/
|
|
368
|
+
export async function teamShotLocationTop10(ctx, { positions = EdgePositions.ALL, sortBy, category = 'all', ...params }) {
|
|
369
|
+
return getEdgeSegments(ctx, 'edge/team-shot-location-top-10', [positions, sortBy, category], params);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get the NHL EDGE comparison statistics for a specific team.
|
|
373
|
+
*
|
|
374
|
+
* @param params.teamId NHL team id, e.g. 10
|
|
375
|
+
* @example await client.edge.teamComparison({ teamId: 10 })
|
|
376
|
+
*/
|
|
377
|
+
export async function teamComparison(ctx, params) {
|
|
378
|
+
return getEdge(ctx, 'edge/team-comparison', params.teamId, params);
|
|
379
|
+
}
|
|
380
|
+
// ========================
|
|
381
|
+
// LEAGUE ENDPOINTS
|
|
382
|
+
// ========================
|
|
383
|
+
/**
|
|
384
|
+
* Get the NHL EDGE "by the numbers" league highlights. Without a season this
|
|
385
|
+
* is the latest game night (`games`, `gameDate` and the nightly leaders);
|
|
386
|
+
* with a season it is the season bests (hardest shot, top speed, longest
|
|
387
|
+
* distance in a game).
|
|
388
|
+
*
|
|
389
|
+
* @example https://api-web.nhle.com/v1/edge/by-the-numbers/now
|
|
390
|
+
*/
|
|
391
|
+
export async function byTheNumbers(ctx, params = {}) {
|
|
392
|
+
return getEdge(ctx, 'edge/by-the-numbers', undefined, params);
|
|
393
|
+
}
|
|
206
394
|
export const edgeApi = {
|
|
207
395
|
skaterDetail,
|
|
208
396
|
skaterShotSpeedDetail,
|
|
@@ -227,4 +415,19 @@ export const edgeApi = {
|
|
|
227
415
|
teamLanding,
|
|
228
416
|
teamShotSpeedDetail,
|
|
229
417
|
teamSkatingSpeedDetail,
|
|
418
|
+
skaterDistanceTop10,
|
|
419
|
+
skaterSpeedTop10,
|
|
420
|
+
skaterZoneTimeTop10,
|
|
421
|
+
skaterShotSpeedTop10,
|
|
422
|
+
skaterShotLocationTop10,
|
|
423
|
+
goalie5v5Top10,
|
|
424
|
+
goalieShotLocationTop10,
|
|
425
|
+
goalieSavePercentageTop10,
|
|
426
|
+
teamSkatingDistanceTop10,
|
|
427
|
+
teamSkatingSpeedTop10,
|
|
428
|
+
teamZoneTimeTop10,
|
|
429
|
+
teamShotSpeedTop10,
|
|
430
|
+
teamShotLocationTop10,
|
|
431
|
+
teamComparison,
|
|
432
|
+
byTheNumbers,
|
|
230
433
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from '#src/context.mjs';
|
|
2
|
-
import type { Boxscore, DailyScores, GameLanding, GameStory, PlayByPlay, RightRail, ShiftChart } from '#src/types/index.mjs';
|
|
2
|
+
import type { Boxscore, DailyScores, GameLanding, GameMeta, GameStory, PlayByPlay, PlayReplay, RightRail, Scoreboard, ShiftChart, WscPlay } from '#src/types/index.mjs';
|
|
3
3
|
import type { Id } from '#src/utils.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Get the full boxscore for a specific NHL game, including team scores,
|
|
@@ -73,6 +73,50 @@ export declare function seasonSeriesMatchup(ctx: Context, { gameId }: {
|
|
|
73
73
|
export declare function gameStory(ctx: Context, { gameId }: {
|
|
74
74
|
gameId: Id;
|
|
75
75
|
}): Promise<GameStory>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the league scoreboard: every game in the week around a date, grouped by
|
|
78
|
+
* date. Returns the week around today when no date is supplied.
|
|
79
|
+
*
|
|
80
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
81
|
+
* @example https://api-web.nhle.com/v1/scoreboard/2023-10-15
|
|
82
|
+
*/
|
|
83
|
+
export declare function scoreboard(ctx: Context, { date }?: {
|
|
84
|
+
date?: string;
|
|
85
|
+
}): Promise<Scoreboard>;
|
|
86
|
+
/**
|
|
87
|
+
* Get the play-by-play feed nhl.com's game story widget uses. A bare array of
|
|
88
|
+
* plays, with a different play shape from `playByPlay`.
|
|
89
|
+
*
|
|
90
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
91
|
+
* @example https://api-web.nhle.com/v1/wsc/play-by-play/2023020280
|
|
92
|
+
*/
|
|
93
|
+
export declare function wscPlayByPlay(ctx: Context, { gameId }: {
|
|
94
|
+
gameId: Id;
|
|
95
|
+
}): Promise<WscPlay[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Get the replay card for one play-by-play event: the game header, plus a
|
|
98
|
+
* `goal` object (scorer, assists, highlight clip and the `pptReplayUrl`
|
|
99
|
+
* puck-and-player-tracking link) when the event is a goal. Any event id works.
|
|
100
|
+
*
|
|
101
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
102
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
103
|
+
* @param params.eventNumber The play's `eventId` from `playByPlay`, e.g. 193
|
|
104
|
+
* @example https://api-web.nhle.com/v1/ppt-replay/2023020280/193
|
|
105
|
+
*/
|
|
106
|
+
export declare function playReplay(ctx: Context, { gameId, eventNumber }: {
|
|
107
|
+
gameId: Id;
|
|
108
|
+
eventNumber: Id;
|
|
109
|
+
}): Promise<PlayReplay>;
|
|
110
|
+
/**
|
|
111
|
+
* Get the metadata nhl.com uses to render a game page: the two teams, the
|
|
112
|
+
* season state and the game state.
|
|
113
|
+
*
|
|
114
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
115
|
+
* @example https://api-web.nhle.com/v1/meta/game/2023020280
|
|
116
|
+
*/
|
|
117
|
+
export declare function gameMeta(ctx: Context, { gameId }: {
|
|
118
|
+
gameId: Id;
|
|
119
|
+
}): Promise<GameMeta>;
|
|
76
120
|
export declare const gameCenterApi: {
|
|
77
121
|
readonly boxscore: typeof boxscore;
|
|
78
122
|
readonly playByPlay: typeof playByPlay;
|
|
@@ -81,4 +125,8 @@ export declare const gameCenterApi: {
|
|
|
81
125
|
readonly shiftChartData: typeof shiftChartData;
|
|
82
126
|
readonly seasonSeriesMatchup: typeof seasonSeriesMatchup;
|
|
83
127
|
readonly gameStory: typeof gameStory;
|
|
128
|
+
readonly scoreboard: typeof scoreboard;
|
|
129
|
+
readonly wscPlayByPlay: typeof wscPlayByPlay;
|
|
130
|
+
readonly playReplay: typeof playReplay;
|
|
131
|
+
readonly gameMeta: typeof gameMeta;
|
|
84
132
|
};
|
package/dist/api/game-center.mjs
CHANGED
|
@@ -75,6 +75,49 @@ export async function seasonSeriesMatchup(ctx, { gameId }) {
|
|
|
75
75
|
export async function gameStory(ctx, { gameId }) {
|
|
76
76
|
return getWeb(ctx, `wsc/game-story/${gameId}`);
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the league scoreboard: every game in the week around a date, grouped by
|
|
80
|
+
* date. Returns the week around today when no date is supplied.
|
|
81
|
+
*
|
|
82
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
83
|
+
* @example https://api-web.nhle.com/v1/scoreboard/2023-10-15
|
|
84
|
+
*/
|
|
85
|
+
export async function scoreboard(ctx, { date } = {}) {
|
|
86
|
+
return getWeb(ctx, `scoreboard/${date ?? 'now'}`);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the play-by-play feed nhl.com's game story widget uses. A bare array of
|
|
90
|
+
* plays, with a different play shape from `playByPlay`.
|
|
91
|
+
*
|
|
92
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
93
|
+
* @example https://api-web.nhle.com/v1/wsc/play-by-play/2023020280
|
|
94
|
+
*/
|
|
95
|
+
export async function wscPlayByPlay(ctx, { gameId }) {
|
|
96
|
+
return getWeb(ctx, `wsc/play-by-play/${gameId}`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get the replay card for one play-by-play event: the game header, plus a
|
|
100
|
+
* `goal` object (scorer, assists, highlight clip and the `pptReplayUrl`
|
|
101
|
+
* puck-and-player-tracking link) when the event is a goal. Any event id works.
|
|
102
|
+
*
|
|
103
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
104
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
105
|
+
* @param params.eventNumber The play's `eventId` from `playByPlay`, e.g. 193
|
|
106
|
+
* @example https://api-web.nhle.com/v1/ppt-replay/2023020280/193
|
|
107
|
+
*/
|
|
108
|
+
export async function playReplay(ctx, { gameId, eventNumber }) {
|
|
109
|
+
return getWeb(ctx, `ppt-replay/${gameId}/${eventNumber}`);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get the metadata nhl.com uses to render a game page: the two teams, the
|
|
113
|
+
* season state and the game state.
|
|
114
|
+
*
|
|
115
|
+
* @param params.gameId Game id, e.g. 2023020280
|
|
116
|
+
* @example https://api-web.nhle.com/v1/meta/game/2023020280
|
|
117
|
+
*/
|
|
118
|
+
export async function gameMeta(ctx, { gameId }) {
|
|
119
|
+
return getWeb(ctx, `meta/game/${gameId}`);
|
|
120
|
+
}
|
|
78
121
|
export const gameCenterApi = {
|
|
79
122
|
boxscore,
|
|
80
123
|
playByPlay,
|
|
@@ -83,4 +126,8 @@ export const gameCenterApi = {
|
|
|
83
126
|
shiftChartData,
|
|
84
127
|
seasonSeriesMatchup,
|
|
85
128
|
gameStory,
|
|
129
|
+
scoreboard,
|
|
130
|
+
wscPlayByPlay,
|
|
131
|
+
playReplay,
|
|
132
|
+
gameMeta,
|
|
86
133
|
};
|
package/dist/api/misc.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Context } from '#src/context.mjs';
|
|
2
|
-
import type { Country, DraftYear, GlossaryEntry, SeasonRules, StatsConfig } from '#src/types/index.mjs';
|
|
2
|
+
import type { ComponentSeason, Country, DraftYear, GeoLocation, GlossaryEntry, Meta, PartnerGameOdds, PostalLookupTeam, SeasonId, SeasonRules, StatsConfig, StatsGame, TvSchedule } from '#src/types/index.mjs';
|
|
3
|
+
import type { Id } from '#src/utils.mjs';
|
|
3
4
|
/**
|
|
4
5
|
* Gets the full NHL glossary of statistical terms and abbreviations.
|
|
5
6
|
*
|
|
@@ -31,10 +32,123 @@ export declare function seasonSpecificRulesAndInfo(ctx: Context): Promise<Season
|
|
|
31
32
|
* @example https://api.nhle.com/stats/rest/en/draft
|
|
32
33
|
*/
|
|
33
34
|
export declare function draftYearAndRounds(ctx: Context): Promise<DraftYear[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Gets the season and game type the stats API currently serves by default.
|
|
37
|
+
*
|
|
38
|
+
* @example https://api.nhle.com/stats/rest/en/componentSeason
|
|
39
|
+
*/
|
|
40
|
+
export declare function componentSeasons(ctx: Context): Promise<ComponentSeason[]>;
|
|
41
|
+
export interface GamesParams {
|
|
42
|
+
/** Season in YYYYYYYY format, e.g. 20232024 (about 1,500 games). */
|
|
43
|
+
season?: Id;
|
|
44
|
+
/** 1=Preseason, 2=Regular season, 3=Playoffs. */
|
|
45
|
+
gameType?: number;
|
|
46
|
+
/** NHL team id, home or away, e.g. 10. */
|
|
47
|
+
teamId?: Id;
|
|
48
|
+
/** First game date, YYYY-MM-DD (inclusive). */
|
|
49
|
+
startDate?: string;
|
|
50
|
+
/** Last game date, YYYY-MM-DD (inclusive). */
|
|
51
|
+
endDate?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Extra filter expression, joined to the others with `and`. Only the row
|
|
54
|
+
* fields (`season`, `gameType`, `gameDate`, `homeTeamId`, ...) can be
|
|
55
|
+
* filtered; report columns like `seasonId` are a 400.
|
|
56
|
+
*/
|
|
57
|
+
cayenneExp?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets games from the stats API. At least one filter is required:
|
|
61
|
+
* unfiltered, the API sends every game ever played (about 19 MB).
|
|
62
|
+
*
|
|
63
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
64
|
+
* @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
|
|
65
|
+
* @param params.teamId NHL team id, home or away, e.g. 10
|
|
66
|
+
* @param params.startDate First game date, YYYY-MM-DD
|
|
67
|
+
* @param params.endDate Last game date, YYYY-MM-DD
|
|
68
|
+
* @param params.cayenneExp Extra filter expression, e.g. "homeScore>=7"
|
|
69
|
+
* @throws RangeError When no filter is given, or a date is not YYYY-MM-DD
|
|
70
|
+
* @example await client.misc.games({ season: 20232024, teamId: 10, gameType: 3 })
|
|
71
|
+
*/
|
|
72
|
+
export declare function games(ctx: Context, params: GamesParams): Promise<StatsGame[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Gets the national TV schedule for the week around a date, grouped by date.
|
|
75
|
+
*
|
|
76
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
77
|
+
* @example https://api-web.nhle.com/v1/network/tv-schedule/2023-10-15
|
|
78
|
+
*/
|
|
79
|
+
export declare function tvSchedule(ctx: Context, { date }?: {
|
|
80
|
+
date?: string;
|
|
81
|
+
}): Promise<TvSchedule>;
|
|
82
|
+
/**
|
|
83
|
+
* Gets betting odds for today's games from the NHL's odds partner in a
|
|
84
|
+
* country.
|
|
85
|
+
*
|
|
86
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
87
|
+
* @param params.countryCode Two-letter country code, e.g. US, CA
|
|
88
|
+
* @example https://api-web.nhle.com/v1/partner-game/US/now
|
|
89
|
+
*/
|
|
90
|
+
export declare function partnerGameOdds(ctx: Context, { countryCode }: {
|
|
91
|
+
countryCode: string;
|
|
92
|
+
}): Promise<PartnerGameOdds>;
|
|
93
|
+
/**
|
|
94
|
+
* Gets every NHL season id, oldest first.
|
|
95
|
+
*
|
|
96
|
+
* @example https://api-web.nhle.com/v1/season
|
|
97
|
+
*/
|
|
98
|
+
export declare function seasonIds(ctx: Context): Promise<SeasonId[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Gets display metadata (names, headshots, logos) for players and teams.
|
|
101
|
+
* Lists you leave out or pass empty come back empty.
|
|
102
|
+
*
|
|
103
|
+
* @param params.players Player ids, e.g. [8478402]
|
|
104
|
+
* @param params.teams Team abbreviations, e.g. ['TOR', 'BUF']
|
|
105
|
+
* @example https://api-web.nhle.com/v1/meta?players=8478402&teams=TOR,BUF
|
|
106
|
+
*/
|
|
107
|
+
export declare function meta(ctx: Context, { players, teams }?: {
|
|
108
|
+
players?: Id[];
|
|
109
|
+
teams?: string[];
|
|
110
|
+
}): Promise<Meta>;
|
|
111
|
+
/**
|
|
112
|
+
* Gets the caller's country, looked up from their IP address. The answer
|
|
113
|
+
* depends on where the request comes from.
|
|
114
|
+
*
|
|
115
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
116
|
+
* @example https://api-web.nhle.com/v1/location
|
|
117
|
+
*/
|
|
118
|
+
export declare function location(ctx: Context): Promise<GeoLocation>;
|
|
119
|
+
/**
|
|
120
|
+
* Gets the teams whose local broadcast market covers a postal code. Empty
|
|
121
|
+
* for codes outside every market.
|
|
122
|
+
*
|
|
123
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
124
|
+
* @param params.postalCode Postal or ZIP code, e.g. 90210 or "M5V 3L9"
|
|
125
|
+
* @example https://api-web.nhle.com/v1/postal-lookup/90210
|
|
126
|
+
*/
|
|
127
|
+
export declare function postalLookup(ctx: Context, { postalCode }: {
|
|
128
|
+
postalCode: string;
|
|
129
|
+
}): Promise<PostalLookupTeam[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Checks that the stats API is up. Resolves `true` on success; it never
|
|
132
|
+
* resolves `false`, since any failure throws an `NHLApiException` subclass
|
|
133
|
+
* (or a network error).
|
|
134
|
+
*
|
|
135
|
+
* @throws ServerErrorException When the stats API answers 5xx
|
|
136
|
+
* @example https://api.nhle.com/stats/rest/ping
|
|
137
|
+
*/
|
|
138
|
+
export declare function ping(ctx: Context): Promise<true>;
|
|
34
139
|
export declare const miscApi: {
|
|
35
140
|
readonly glossary: typeof glossary;
|
|
36
141
|
readonly config: typeof config;
|
|
37
142
|
readonly countries: typeof countries;
|
|
38
143
|
readonly seasonSpecificRulesAndInfo: typeof seasonSpecificRulesAndInfo;
|
|
39
144
|
readonly draftYearAndRounds: typeof draftYearAndRounds;
|
|
145
|
+
readonly componentSeasons: typeof componentSeasons;
|
|
146
|
+
readonly games: typeof games;
|
|
147
|
+
readonly tvSchedule: typeof tvSchedule;
|
|
148
|
+
readonly partnerGameOdds: typeof partnerGameOdds;
|
|
149
|
+
readonly seasonIds: typeof seasonIds;
|
|
150
|
+
readonly meta: typeof meta;
|
|
151
|
+
readonly location: typeof location;
|
|
152
|
+
readonly postalLookup: typeof postalLookup;
|
|
153
|
+
readonly ping: typeof ping;
|
|
40
154
|
};
|
package/dist/api/misc.mjs
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { andClauses, cayenneString } from '#src/api/query/cayenne.mjs';
|
|
2
|
+
import { normalizeDate } from '#src/api/schedule.mjs';
|
|
1
3
|
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
|
+
async function getData(ctx, resource, queryParams) {
|
|
5
|
+
const response = await (await ctx.get(Endpoint.API_CORE, resource, queryParams)).json();
|
|
4
6
|
return response.data ?? [];
|
|
5
7
|
}
|
|
8
|
+
async function getWeb(ctx, resource) {
|
|
9
|
+
return (await ctx.get(Endpoint.API_WEB_V1, resource)).json();
|
|
10
|
+
}
|
|
6
11
|
/**
|
|
7
12
|
* Gets the full NHL glossary of statistical terms and abbreviations.
|
|
8
13
|
*
|
|
@@ -44,10 +49,150 @@ export async function seasonSpecificRulesAndInfo(ctx) {
|
|
|
44
49
|
export async function draftYearAndRounds(ctx) {
|
|
45
50
|
return getData(ctx, 'stats/rest/en/draft');
|
|
46
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Gets the season and game type the stats API currently serves by default.
|
|
54
|
+
*
|
|
55
|
+
* @example https://api.nhle.com/stats/rest/en/componentSeason
|
|
56
|
+
*/
|
|
57
|
+
export async function componentSeasons(ctx) {
|
|
58
|
+
return getData(ctx, 'stats/rest/en/componentSeason');
|
|
59
|
+
}
|
|
60
|
+
function gamesClauses({ season, gameType, teamId, startDate, endDate, cayenneExp, }) {
|
|
61
|
+
const clauses = [];
|
|
62
|
+
if (season !== undefined && season !== null) {
|
|
63
|
+
clauses.push(`season=${season}`);
|
|
64
|
+
}
|
|
65
|
+
if (gameType !== undefined) {
|
|
66
|
+
clauses.push(`gameType=${gameType}`);
|
|
67
|
+
}
|
|
68
|
+
if (teamId !== undefined && teamId !== null) {
|
|
69
|
+
clauses.push(`homeTeamId=${teamId} or visitingTeamId=${teamId}`);
|
|
70
|
+
}
|
|
71
|
+
if (startDate !== undefined) {
|
|
72
|
+
clauses.push(`gameDate>=${cayenneString(normalizeDate(startDate))}`);
|
|
73
|
+
}
|
|
74
|
+
if (endDate !== undefined) {
|
|
75
|
+
clauses.push(`gameDate<=${cayenneString(normalizeDate(endDate))}`);
|
|
76
|
+
}
|
|
77
|
+
if (cayenneExp?.trim()) {
|
|
78
|
+
clauses.push(cayenneExp);
|
|
79
|
+
}
|
|
80
|
+
return clauses;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Gets games from the stats API. At least one filter is required:
|
|
84
|
+
* unfiltered, the API sends every game ever played (about 19 MB).
|
|
85
|
+
*
|
|
86
|
+
* @param params.season Season in YYYYYYYY format, e.g. 20232024
|
|
87
|
+
* @param params.gameType 1=Preseason, 2=Regular season, 3=Playoffs
|
|
88
|
+
* @param params.teamId NHL team id, home or away, e.g. 10
|
|
89
|
+
* @param params.startDate First game date, YYYY-MM-DD
|
|
90
|
+
* @param params.endDate Last game date, YYYY-MM-DD
|
|
91
|
+
* @param params.cayenneExp Extra filter expression, e.g. "homeScore>=7"
|
|
92
|
+
* @throws RangeError When no filter is given, or a date is not YYYY-MM-DD
|
|
93
|
+
* @example await client.misc.games({ season: 20232024, teamId: 10, gameType: 3 })
|
|
94
|
+
*/
|
|
95
|
+
export async function games(ctx, params) {
|
|
96
|
+
const clauses = gamesClauses(params);
|
|
97
|
+
if (clauses.length === 0) {
|
|
98
|
+
throw new RangeError('Missing filter. Pass season, gameType, teamId, a date or cayenneExp.');
|
|
99
|
+
}
|
|
100
|
+
return getData(ctx, 'stats/rest/en/game', {
|
|
101
|
+
cayenneExp: andClauses(clauses),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Gets the national TV schedule for the week around a date, grouped by date.
|
|
106
|
+
*
|
|
107
|
+
* @param params.date Date in YYYY-MM-DD format. Defaults to "now".
|
|
108
|
+
* @example https://api-web.nhle.com/v1/network/tv-schedule/2023-10-15
|
|
109
|
+
*/
|
|
110
|
+
export async function tvSchedule(ctx, { date } = {}) {
|
|
111
|
+
return getWeb(ctx, `network/tv-schedule/${date ?? 'now'}`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Gets betting odds for today's games from the NHL's odds partner in a
|
|
115
|
+
* country.
|
|
116
|
+
*
|
|
117
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
118
|
+
* @param params.countryCode Two-letter country code, e.g. US, CA
|
|
119
|
+
* @example https://api-web.nhle.com/v1/partner-game/US/now
|
|
120
|
+
*/
|
|
121
|
+
export async function partnerGameOdds(ctx, { countryCode }) {
|
|
122
|
+
return getWeb(ctx, `partner-game/${countryCode}/now`);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Gets every NHL season id, oldest first.
|
|
126
|
+
*
|
|
127
|
+
* @example https://api-web.nhle.com/v1/season
|
|
128
|
+
*/
|
|
129
|
+
export async function seasonIds(ctx) {
|
|
130
|
+
return getWeb(ctx, 'season');
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Gets display metadata (names, headshots, logos) for players and teams.
|
|
134
|
+
* Lists you leave out or pass empty come back empty.
|
|
135
|
+
*
|
|
136
|
+
* @param params.players Player ids, e.g. [8478402]
|
|
137
|
+
* @param params.teams Team abbreviations, e.g. ['TOR', 'BUF']
|
|
138
|
+
* @example https://api-web.nhle.com/v1/meta?players=8478402&teams=TOR,BUF
|
|
139
|
+
*/
|
|
140
|
+
export async function meta(ctx, { players = [], teams = [] } = {}) {
|
|
141
|
+
const query = {};
|
|
142
|
+
if (players.length > 0) {
|
|
143
|
+
query.players = players.join(',');
|
|
144
|
+
}
|
|
145
|
+
if (teams.length > 0) {
|
|
146
|
+
query.teams = teams.join(',');
|
|
147
|
+
}
|
|
148
|
+
return (await ctx.get(Endpoint.API_WEB_V1, 'meta', query)).json();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Gets the caller's country, looked up from their IP address. The answer
|
|
152
|
+
* depends on where the request comes from.
|
|
153
|
+
*
|
|
154
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
155
|
+
* @example https://api-web.nhle.com/v1/location
|
|
156
|
+
*/
|
|
157
|
+
export async function location(ctx) {
|
|
158
|
+
return getWeb(ctx, 'location');
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Gets the teams whose local broadcast market covers a postal code. Empty
|
|
162
|
+
* for codes outside every market.
|
|
163
|
+
*
|
|
164
|
+
* @experimental Feeds an nhl.com widget; the shape may change without notice.
|
|
165
|
+
* @param params.postalCode Postal or ZIP code, e.g. 90210 or "M5V 3L9"
|
|
166
|
+
* @example https://api-web.nhle.com/v1/postal-lookup/90210
|
|
167
|
+
*/
|
|
168
|
+
export async function postalLookup(ctx, { postalCode }) {
|
|
169
|
+
return getWeb(ctx, `postal-lookup/${encodeURIComponent(postalCode)}`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Checks that the stats API is up. Resolves `true` on success; it never
|
|
173
|
+
* resolves `false`, since any failure throws an `NHLApiException` subclass
|
|
174
|
+
* (or a network error).
|
|
175
|
+
*
|
|
176
|
+
* @throws ServerErrorException When the stats API answers 5xx
|
|
177
|
+
* @example https://api.nhle.com/stats/rest/ping
|
|
178
|
+
*/
|
|
179
|
+
export async function ping(ctx) {
|
|
180
|
+
await ctx.get(Endpoint.API_CORE, 'stats/rest/ping');
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
47
183
|
export const miscApi = {
|
|
48
184
|
glossary,
|
|
49
185
|
config,
|
|
50
186
|
countries,
|
|
51
187
|
seasonSpecificRulesAndInfo,
|
|
52
188
|
draftYearAndRounds,
|
|
189
|
+
componentSeasons,
|
|
190
|
+
games,
|
|
191
|
+
tvSchedule,
|
|
192
|
+
partnerGameOdds,
|
|
193
|
+
seasonIds,
|
|
194
|
+
meta,
|
|
195
|
+
location,
|
|
196
|
+
postalLookup,
|
|
197
|
+
ping,
|
|
53
198
|
};
|