nhl-api-ts 0.1.0 → 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.
Files changed (80) hide show
  1. package/README.md +22 -2
  2. package/dist/api/edge.d.mts +25 -24
  3. package/dist/api/game-center.d.mts +9 -8
  4. package/dist/api/helpers.d.mts +4 -3
  5. package/dist/api/misc.d.mts +6 -6
  6. package/dist/api/players.d.mts +4 -3
  7. package/dist/api/query/builder.d.mts +2 -0
  8. package/dist/api/query/builder.mjs +3 -1
  9. package/dist/api/query/index.d.mts +2 -2
  10. package/dist/api/query/index.mjs +1 -1
  11. package/dist/api/query/sorting/goalie-sorts.d.mts +55 -0
  12. package/dist/api/query/sorting/goalie-sorts.mjs +43 -48
  13. package/dist/api/query/sorting/sorting-options.d.mts +125 -0
  14. package/dist/api/query/sorting/sorting-options.mjs +3 -2
  15. package/dist/api/schedule.d.mts +12 -11
  16. package/dist/api/standings.d.mts +4 -3
  17. package/dist/api/stats.d.mts +19 -14
  18. package/dist/api/stats.mjs +23 -5
  19. package/dist/api/teams.d.mts +6 -5
  20. package/dist/index.d.mts +2 -1
  21. package/dist/nhl-client.d.mts +13 -9
  22. package/dist/nhl-client.mjs +1 -1
  23. package/dist/types/common.d.mts +81 -0
  24. package/dist/types/common.mjs +2 -0
  25. package/dist/types/edge.d.mts +1024 -0
  26. package/dist/types/edge.mjs +1 -0
  27. package/dist/types/game-center.d.mts +1194 -0
  28. package/dist/types/game-center.mjs +1 -0
  29. package/dist/types/helpers.d.mts +17 -0
  30. package/dist/types/helpers.mjs +1 -0
  31. package/dist/types/index.d.mts +10 -0
  32. package/dist/types/index.mjs +1 -0
  33. package/dist/types/misc.d.mts +68 -0
  34. package/dist/types/misc.mjs +2 -0
  35. package/dist/types/players.d.mts +42 -0
  36. package/dist/types/players.mjs +1 -0
  37. package/dist/types/schedule.d.mts +456 -0
  38. package/dist/types/schedule.mjs +1 -0
  39. package/dist/types/standings.d.mts +104 -0
  40. package/dist/types/standings.mjs +1 -0
  41. package/dist/types/stats.d.mts +1086 -0
  42. package/dist/types/stats.mjs +1 -0
  43. package/dist/types/teams.d.mts +29 -0
  44. package/dist/types/teams.mjs +1 -0
  45. package/dist/utils.d.mts +0 -1
  46. package/package.json +11 -3
  47. package/dist/api/query/errors.d.mts +0 -3
  48. package/dist/api/query/errors.mjs +0 -6
  49. package/dist/api/query/filters/base.d.mts +0 -4
  50. package/dist/api/query/filters/base.mjs +0 -2
  51. package/dist/api/query/filters/decision.d.mts +0 -13
  52. package/dist/api/query/filters/decision.mjs +0 -26
  53. package/dist/api/query/filters/draft.d.mts +0 -15
  54. package/dist/api/query/filters/draft.mjs +0 -27
  55. package/dist/api/query/filters/experience.d.mts +0 -9
  56. package/dist/api/query/filters/experience.mjs +0 -17
  57. package/dist/api/query/filters/franchise.d.mts +0 -9
  58. package/dist/api/query/filters/franchise.mjs +0 -15
  59. package/dist/api/query/filters/game-type.d.mts +0 -10
  60. package/dist/api/query/filters/game-type.mjs +0 -16
  61. package/dist/api/query/filters/goalie-sorts.d.mts +0 -3
  62. package/dist/api/query/filters/goalie-sorts.mjs +0 -55
  63. package/dist/api/query/filters/home-road.d.mts +0 -9
  64. package/dist/api/query/filters/home-road.mjs +0 -16
  65. package/dist/api/query/filters/index.d.mts +0 -14
  66. package/dist/api/query/filters/index.mjs +0 -14
  67. package/dist/api/query/filters/nationality.d.mts +0 -12
  68. package/dist/api/query/filters/nationality.mjs +0 -19
  69. package/dist/api/query/filters/opponent.d.mts +0 -10
  70. package/dist/api/query/filters/opponent.mjs +0 -16
  71. package/dist/api/query/filters/position.d.mts +0 -16
  72. package/dist/api/query/filters/position.mjs +0 -28
  73. package/dist/api/query/filters/season.d.mts +0 -14
  74. package/dist/api/query/filters/season.mjs +0 -24
  75. package/dist/api/query/filters/shoot-catch.d.mts +0 -9
  76. package/dist/api/query/filters/shoot-catch.mjs +0 -16
  77. package/dist/api/query/filters/status.d.mts +0 -20
  78. package/dist/api/query/filters/status.mjs +0 -28
  79. package/dist/logging.d.mts +0 -14
  80. package/dist/logging.mjs +0 -13
@@ -2,6 +2,130 @@ export interface SortExpr {
2
2
  property: string;
3
3
  direction: 'ASC' | 'DESC' | 'ASC_CI' | 'DESC_CI' | (string & {});
4
4
  }
5
+ declare const defaultSortingByReport: {
6
+ summary: SortExpr[];
7
+ bios: ({
8
+ property: string;
9
+ direction: "ASC_CI";
10
+ } | {
11
+ property: string;
12
+ direction: "ASC";
13
+ })[];
14
+ faceoffpercentages: ({
15
+ property: string;
16
+ direction: "DESC";
17
+ } | {
18
+ property: string;
19
+ direction: "ASC";
20
+ })[];
21
+ faceoffwins: ({
22
+ property: string;
23
+ direction: "DESC";
24
+ } | {
25
+ property: string;
26
+ direction: "ASC";
27
+ })[];
28
+ goalsForAgainst: ({
29
+ property: string;
30
+ direction: "DESC";
31
+ } | {
32
+ property: string;
33
+ direction: "ASC";
34
+ })[];
35
+ realtime: ({
36
+ property: string;
37
+ direction: "DESC";
38
+ } | {
39
+ property: string;
40
+ direction: "ASC";
41
+ })[];
42
+ penalties: ({
43
+ property: string;
44
+ direction: "DESC";
45
+ } | {
46
+ property: string;
47
+ direction: "ASC";
48
+ })[];
49
+ penaltykill: ({
50
+ property: string;
51
+ direction: "DESC";
52
+ } | {
53
+ property: string;
54
+ direction: "ASC";
55
+ })[];
56
+ penaltyShots: ({
57
+ property: string;
58
+ direction: "DESC";
59
+ } | {
60
+ property: string;
61
+ direction: "ASC";
62
+ })[];
63
+ powerplay: ({
64
+ property: string;
65
+ direction: "DESC";
66
+ } | {
67
+ property: string;
68
+ direction: "ASC";
69
+ })[];
70
+ puckPossessions: ({
71
+ property: string;
72
+ direction: "DESC";
73
+ } | {
74
+ property: string;
75
+ direction: "ASC";
76
+ })[];
77
+ summaryshooting: ({
78
+ property: string;
79
+ direction: "DESC";
80
+ } | {
81
+ property: string;
82
+ direction: "ASC";
83
+ })[];
84
+ percentages: ({
85
+ property: string;
86
+ direction: "DESC";
87
+ } | {
88
+ property: string;
89
+ direction: "ASC";
90
+ })[];
91
+ scoringRates: ({
92
+ property: string;
93
+ direction: "DESC";
94
+ } | {
95
+ property: string;
96
+ direction: "ASC";
97
+ })[];
98
+ scoringpergame: ({
99
+ property: string;
100
+ direction: "DESC";
101
+ } | {
102
+ property: string;
103
+ direction: "ASC";
104
+ })[];
105
+ shootout: ({
106
+ property: string;
107
+ direction: "DESC";
108
+ } | {
109
+ property: string;
110
+ direction: "ASC";
111
+ })[];
112
+ shottype: ({
113
+ property: string;
114
+ direction: "DESC";
115
+ } | {
116
+ property: string;
117
+ direction: "ASC";
118
+ })[];
119
+ timeonice: ({
120
+ property: string;
121
+ direction: "DESC";
122
+ } | {
123
+ property: string;
124
+ direction: "ASC";
125
+ })[];
126
+ };
127
+ /** Skater report types that have a default sort configured. */
128
+ export type SkaterReportType = keyof typeof defaultSortingByReport;
5
129
  /** Skater report types that have a default sort configured. */
6
130
  export declare const SKATER_REPORT_TYPES: string[];
7
131
  /**
@@ -9,3 +133,4 @@ export declare const SKATER_REPORT_TYPES: string[];
9
133
  * summary sort for unknown report types.
10
134
  */
11
135
  export declare function defaultSortForReport(report: string): SortExpr[];
136
+ export {};
@@ -80,6 +80,7 @@ const defaultSortingByReport = {
80
80
  { property: 'playerId', direction: 'ASC' },
81
81
  ],
82
82
  };
83
+ const sortingLookup = defaultSortingByReport;
83
84
  /** Skater report types that have a default sort configured. */
84
85
  export const SKATER_REPORT_TYPES = Object.keys(defaultSortingByReport);
85
86
  /**
@@ -87,7 +88,7 @@ export const SKATER_REPORT_TYPES = Object.keys(defaultSortingByReport);
87
88
  * summary sort for unknown report types.
88
89
  */
89
90
  export function defaultSortForReport(report) {
90
- return ((Object.hasOwn(defaultSortingByReport, report)
91
- ? defaultSortingByReport[report]
91
+ return ((Object.hasOwn(sortingLookup, report)
92
+ ? sortingLookup[report]
92
93
  : undefined) ?? skaterSummaryDefaultSorting);
93
94
  }
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { CalendarSchedule, ClubScheduleGame, OddsPartner, PlayoffBracket, PlayoffCarousel, PlayoffSeriesSchedule, ScheduleGame, TeamSeasonSchedule, WeeklySchedule } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  /**
4
5
  * Parses and normalizes a YYYY-MM-DD date: single-digit months/days are
5
6
  * accepted ("2024-10-9" -> "2024-10-09") and impossible dates are rejected.
@@ -9,8 +10,8 @@ export interface DailySchedule {
9
10
  nextStartDate: string | null;
10
11
  previousStartDate: string | null;
11
12
  date: string;
12
- oddsPartners: JsonObject[] | null;
13
- games?: JsonObject[];
13
+ oddsPartners: OddsPartner[] | null;
14
+ games?: ScheduleGame[];
14
15
  numberOfGames?: number;
15
16
  }
16
17
  /**
@@ -31,7 +32,7 @@ export declare const dailySchedule: (ctx: Context, { date }?: {
31
32
  */
32
33
  export declare const weeklySchedule: (ctx: Context, { date }?: {
33
34
  date?: string;
34
- }) => Promise<JsonObject>;
35
+ }) => Promise<WeeklySchedule>;
35
36
  /**
36
37
  * Gets monthly schedule for a specified team.
37
38
  *
@@ -42,7 +43,7 @@ export declare const weeklySchedule: (ctx: Context, { date }?: {
42
43
  export declare const teamMonthlySchedule: (ctx: Context, { teamAbbr, month }: {
43
44
  teamAbbr: string;
44
45
  month?: string;
45
- }) => Promise<JsonObject[]>;
46
+ }) => Promise<ClubScheduleGame[]>;
46
47
  /**
47
48
  * Gets weekly schedule for a specified team.
48
49
  *
@@ -53,7 +54,7 @@ export declare const teamMonthlySchedule: (ctx: Context, { teamAbbr, month }: {
53
54
  export declare const teamWeeklySchedule: (ctx: Context, { teamAbbr, date }: {
54
55
  teamAbbr: string;
55
56
  date?: string;
56
- }) => Promise<JsonObject[]>;
57
+ }) => Promise<ClubScheduleGame[]>;
57
58
  /**
58
59
  * Gets the full season schedule for a specified team.
59
60
  *
@@ -64,7 +65,7 @@ export declare const teamWeeklySchedule: (ctx: Context, { teamAbbr, date }: {
64
65
  export declare const teamSeasonSchedule: (ctx: Context, { teamAbbr, season }: {
65
66
  teamAbbr: string;
66
67
  season: Id;
67
- }) => Promise<JsonObject>;
68
+ }) => Promise<TeamSeasonSchedule>;
68
69
  /**
69
70
  * Gets the schedule in calendar format for a specified date.
70
71
  *
@@ -73,7 +74,7 @@ export declare const teamSeasonSchedule: (ctx: Context, { teamAbbr, season }: {
73
74
  */
74
75
  export declare const calendarSchedule: (ctx: Context, { date }: {
75
76
  date: string;
76
- }) => Promise<JsonObject>;
77
+ }) => Promise<CalendarSchedule>;
77
78
  /**
78
79
  * Gets all playoff series information up to the current round.
79
80
  *
@@ -82,7 +83,7 @@ export declare const calendarSchedule: (ctx: Context, { date }: {
82
83
  */
83
84
  export declare const playoffCarousel: (ctx: Context, { season }: {
84
85
  season: Id;
85
- }) => Promise<JsonObject>;
86
+ }) => Promise<PlayoffCarousel>;
86
87
  /**
87
88
  * Returns the schedule and results for a specified playoff series matchup.
88
89
  *
@@ -93,7 +94,7 @@ export declare const playoffCarousel: (ctx: Context, { season }: {
93
94
  export declare const playoffSeriesSchedule: (ctx: Context, { season, series }: {
94
95
  season: Id;
95
96
  series: string;
96
- }) => Promise<JsonObject>;
97
+ }) => Promise<PlayoffSeriesSchedule>;
97
98
  /**
98
99
  * Returns the full playoff bracket for a given year.
99
100
  *
@@ -102,7 +103,7 @@ export declare const playoffSeriesSchedule: (ctx: Context, { season, series }: {
102
103
  */
103
104
  export declare const playoffBracket: (ctx: Context, { year }: {
104
105
  year: Id;
105
- }) => Promise<JsonObject>;
106
+ }) => Promise<PlayoffBracket>;
106
107
  export declare const scheduleApi: {
107
108
  readonly dailySchedule: typeof dailySchedule;
108
109
  readonly weeklySchedule: typeof weeklySchedule;
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { LeagueStandings, StandingsSeason } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  /**
4
5
  * Gets NHL league standings for a specific date or season.
5
6
  *
@@ -14,14 +15,14 @@ import type { Id, JsonObject } from '#src/utils.mjs';
14
15
  export declare const leagueStandings: (ctx: Context, { date, season }?: {
15
16
  date?: string;
16
17
  season?: Id;
17
- }) => Promise<JsonObject>;
18
+ }) => Promise<LeagueStandings>;
18
19
  /**
19
20
  * Gets metadata for every historical NHL season: start/end dates and which
20
21
  * standings rules (conferences, divisions, wildcard, ties...) were in use.
21
22
  *
22
23
  * @example https://api-web.nhle.com/v1/standings-season
23
24
  */
24
- export declare const seasonStandingManifest: (ctx: Context) => Promise<JsonObject[]>;
25
+ export declare const seasonStandingManifest: (ctx: Context) => Promise<StandingsSeason[]>;
25
26
  export declare const standingsApi: {
26
27
  readonly leagueStandings: typeof leagueStandings;
27
28
  readonly seasonStandingManifest: typeof seasonStandingManifest;
@@ -1,7 +1,8 @@
1
- import type { QueryContext } from '#src/api/query/builder.mjs';
1
+ import { type QueryContext } from '#src/api/query/builder.mjs';
2
2
  import { type SortExpr } from '#src/api/query/sorting/sorting-options.mjs';
3
3
  import type { Context } from '#src/context.mjs';
4
- import type { Id, JsonObject } from '#src/utils.mjs';
4
+ import type { ClubStatsSeason, GameLogEntry, GoalieReportRows, PlayerLanding, SkaterReportRows, StatsApiPage, TeamSummaryRow } from '#src/types/index.mjs';
5
+ import type { Id } from '#src/utils.mjs';
5
6
  export interface TeamSummaryParams {
6
7
  /** Start season in YYYYYYYY format, e.g. 20202021 */
7
8
  startSeason: Id;
@@ -13,7 +14,7 @@ export interface TeamSummaryParams {
13
14
  isGame?: boolean;
14
15
  /** Aggregate stats across the selected seasons. Defaults to false. */
15
16
  isAggregate?: boolean;
16
- /** Custom sort. Defaults to points DESC, wins DESC, teamId ASC. */
17
+ /** Custom sort. Defaults to points DESC, wins DESC, teamId ASC (franchiseId ASC when aggregating). */
17
18
  sortExpr?: SortExpr[];
18
19
  /** Pagination offset. Defaults to 0. */
19
20
  start?: number;
@@ -40,7 +41,7 @@ export interface SkaterStatsSummaryParams {
40
41
  factCayenneExp?: string;
41
42
  defaultCayenneExp?: string;
42
43
  }
43
- export interface SkaterStatsWithQueryContextParams {
44
+ export interface SkaterStatsWithQueryContextParams<Report extends keyof SkaterReportRows = keyof SkaterReportRows> {
44
45
  /** Built with `buildQuery(filters)`. */
45
46
  queryContext: QueryContext;
46
47
  /**
@@ -49,14 +50,14 @@ export interface SkaterStatsWithQueryContextParams {
49
50
  * powerplay, puckPossessions, summaryshooting, percentages, scoringRates,
50
51
  * scoringpergame, shootout, shottype, timeonice
51
52
  */
52
- reportType: string;
53
+ reportType: Report;
53
54
  /** Custom sort. Defaults to the report type's default sort. */
54
55
  sortExpr?: SortExpr[];
55
56
  aggregate?: boolean;
56
57
  start?: number;
57
58
  limit?: number;
58
59
  }
59
- export interface GoalieStatsSummaryParams {
60
+ export interface GoalieStatsSummaryParams<Report extends keyof GoalieReportRows = keyof GoalieReportRows> {
60
61
  startSeason: Id;
61
62
  /** Defaults to `startSeason`. */
62
63
  endSeason?: Id;
@@ -64,7 +65,7 @@ export interface GoalieStatsSummaryParams {
64
65
  * Report type: summary (default), advanced, bios, daysrest, penaltyShots,
65
66
  * savesByStrength, shootout, startedVsRelieved
66
67
  */
67
- statsType?: string;
68
+ statsType?: Report;
68
69
  gameTypeId?: number;
69
70
  franchiseId?: Id;
70
71
  aggregate?: boolean;
@@ -82,7 +83,7 @@ export interface GoalieStatsSummaryParams {
82
83
  */
83
84
  export declare const gametypesPerSeasonDirectoryByTeam: (ctx: Context, { teamAbbr }: {
84
85
  teamAbbr: string;
85
- }) => Promise<JsonObject[]>;
86
+ }) => Promise<ClubStatsSeason[]>;
86
87
  /**
87
88
  * Gets a player's career statistics and biographical information.
88
89
  *
@@ -91,7 +92,7 @@ export declare const gametypesPerSeasonDirectoryByTeam: (ctx: Context, { teamAbb
91
92
  */
92
93
  export declare const playerCareerStats: (ctx: Context, { playerId }: {
93
94
  playerId: Id;
94
- }) => Promise<JsonObject>;
95
+ }) => Promise<PlayerLanding>;
95
96
  /**
96
97
  * Gets a player's game log for a specific season and game type.
97
98
  *
@@ -104,24 +105,28 @@ export declare const playerGameLog: (ctx: Context, { playerId, seasonId, gameTyp
104
105
  playerId: Id;
105
106
  seasonId: Id;
106
107
  gameType: number;
107
- }) => Promise<JsonObject[]>;
108
+ }) => Promise<GameLogEntry[]>;
108
109
  /**
109
110
  * Retrieves team summary statistics across one or more seasons.
110
111
  *
111
112
  * @example await client.stats.teamSummary({ startSeason: '20232024', endSeason: '20232024' })
112
113
  */
113
- export declare const teamSummary: (ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams) => Promise<JsonObject[]>;
114
+ export declare const teamSummary: (ctx: Context, { startSeason, endSeason, gameTypeId, isGame, isAggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: TeamSummaryParams) => Promise<TeamSummaryRow[]>;
114
115
  /**
115
116
  * Gets simplified skater statistics summary for specified seasons and
116
117
  * franchises.
117
118
  *
118
119
  * @example await client.stats.skaterStatsSummary({ startSeason: '20232024', endSeason: '20232024', franchiseId: 10 })
119
120
  */
120
- export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams) => Promise<JsonObject[]>;
121
+ export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason, franchiseId, gameTypeId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: SkaterStatsSummaryParams) => Promise<SkaterReportRows['summary'][]>;
121
122
  /**
122
123
  * Retrieves skater statistics using a query context and specified report
123
124
  * type. Returns the full response (`{ data, total }`).
124
125
  *
126
+ * The default fact filter (`gamesPlayed>=1`) is dropped for the `shootout` and
127
+ * `penaltyShots` reports, which have no `gamesPlayed` column. A fact filter
128
+ * you pass to `buildQuery` is sent as given.
129
+ *
125
130
  * @example
126
131
  * const context = buildQuery([
127
132
  * filter.season('20232024', '20232024'),
@@ -129,14 +134,14 @@ export declare const skaterStatsSummary: (ctx: Context, { startSeason, endSeason
129
134
  * ]);
130
135
  * await client.stats.skaterStatsWithQueryContext({ queryContext: context, reportType: 'summary' });
131
136
  */
132
- export declare const skaterStatsWithQueryContext: (ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams) => Promise<JsonObject>;
137
+ export declare const skaterStatsWithQueryContext: <Report extends keyof SkaterReportRows>(ctx: Context, { queryContext, reportType, sortExpr, aggregate, start, limit, }: SkaterStatsWithQueryContextParams<Report>) => Promise<StatsApiPage<SkaterReportRows[Report]>>;
133
138
  /**
134
139
  * Retrieves goalie statistics with various filtering and aggregation
135
140
  * options.
136
141
  *
137
142
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
138
143
  */
139
- export declare const goalieStatsSummary: (ctx: Context, { startSeason, endSeason, statsType, gameTypeId, franchiseId, aggregate, sortExpr, start, limit, factCayenneExp, defaultCayenneExp, }: GoalieStatsSummaryParams) => Promise<JsonObject[]>;
144
+ export declare 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][]>;
140
145
  export declare const statsApi: {
141
146
  readonly gametypesPerSeasonDirectoryByTeam: typeof gametypesPerSeasonDirectoryByTeam;
142
147
  readonly playerCareerStats: typeof playerCareerStats;
@@ -1,6 +1,12 @@
1
+ import { DEFAULT_FACT_QUERY, } from '#src/api/query/builder.mjs';
1
2
  import { goalieStatsSorts } from '#src/api/query/sorting/goalie-sorts.mjs';
2
3
  import { defaultSortForReport, } from '#src/api/query/sorting/sorting-options.mjs';
3
4
  import { Endpoint } from '#src/http-client.mjs';
5
+ /** Skater reports whose rows have no `gamesPlayed`, so the API rejects the default fact filter. */
6
+ const REPORTS_WITHOUT_GAMES_PLAYED = [
7
+ 'shootout',
8
+ 'penaltyShots',
9
+ ];
4
10
  /**
5
11
  * Gets all game types played by a team throughout their history.
6
12
  *
@@ -38,7 +44,11 @@ export const teamSummary = async (ctx, { startSeason, endSeason, gameTypeId = 2,
38
44
  : [
39
45
  { property: 'points', direction: 'DESC' },
40
46
  { property: 'wins', direction: 'DESC' },
41
- { property: 'teamId', direction: 'ASC' },
47
+ // aggregated rows span seasons, so they have no teamId
48
+ {
49
+ property: isAggregate ? 'franchiseId' : 'teamId',
50
+ direction: 'ASC',
51
+ },
42
52
  ];
43
53
  const effectiveCayenneExp = defaultCayenneExp ??
44
54
  `gameTypeId=${gameTypeId} and seasonId<=${endSeason} and seasonId>=${startSeason}`;
@@ -89,6 +99,10 @@ export const skaterStatsSummary = async (ctx, { startSeason, endSeason, franchis
89
99
  * Retrieves skater statistics using a query context and specified report
90
100
  * type. Returns the full response (`{ data, total }`).
91
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
+ *
92
106
  * @example
93
107
  * const context = buildQuery([
94
108
  * filter.season('20232024', '20232024'),
@@ -105,7 +119,10 @@ export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportTyp
105
119
  isGame: false,
106
120
  start,
107
121
  limit,
108
- factCayenneExp: queryContext.factQuery,
122
+ factCayenneExp: queryContext.factQuery === DEFAULT_FACT_QUERY &&
123
+ REPORTS_WITHOUT_GAMES_PLAYED.includes(reportType)
124
+ ? ''
125
+ : queryContext.factQuery,
109
126
  sort: JSON.stringify(effectiveSortExpr),
110
127
  cayenneExp: queryContext.query,
111
128
  };
@@ -117,9 +134,10 @@ export const skaterStatsWithQueryContext = async (ctx, { queryContext, reportTyp
117
134
  *
118
135
  * @example await client.stats.goalieStatsSummary({ startSeason: '20232024', statsType: 'advanced' })
119
136
  */
120
- export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsType = 'summary', gameTypeId = 2, franchiseId, aggregate = false, sortExpr, start = 0, limit = 25, factCayenneExp, defaultCayenneExp, }) => {
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';
121
139
  const effectiveEndSeason = endSeason === undefined || endSeason === null ? startSeason : endSeason;
122
- const effectiveSortExpr = sortExpr && sortExpr.length > 0 ? sortExpr : goalieStatsSorts(statsType);
140
+ const effectiveSortExpr = sortExpr && sortExpr.length > 0 ? sortExpr : goalieStatsSorts(report);
123
141
  const baseCayenneExp = defaultCayenneExp ??
124
142
  `gameTypeId=${gameTypeId} and seasonId<=${effectiveEndSeason} and seasonId>=${startSeason}`;
125
143
  const effectiveCayenneExp = franchiseId
@@ -134,7 +152,7 @@ export const goalieStatsSummary = async (ctx, { startSeason, endSeason, statsTyp
134
152
  sort: JSON.stringify(effectiveSortExpr),
135
153
  cayenneExp: effectiveCayenneExp,
136
154
  };
137
- const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${statsType}`, qParams)).json();
155
+ const response = await (await ctx.get(Endpoint.API_STATS, `en/goalie/${report}`, qParams)).json();
138
156
  return response.data ?? [];
139
157
  };
140
158
  export const statsApi = {
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '#src/context.mjs';
2
- import type { Id, JsonObject } from '#src/utils.mjs';
2
+ import type { Franchise, Roster, StandingsEntry } from '#src/types/index.mjs';
3
+ import type { Id } from '#src/utils.mjs';
3
4
  export interface Team {
4
5
  conference: {
5
6
  abbr: string;
@@ -16,12 +17,12 @@ export interface Team {
16
17
  franchise_id?: number;
17
18
  }
18
19
  /** Converts a raw standings entry into a `Team`. */
19
- export declare function toTeam(teamData: JsonObject): Team;
20
+ export declare function toTeam(teamData: Partial<StandingsEntry>): Team;
20
21
  /**
21
22
  * Adds a `franchise_id` to each team that has a matching franchise. Teams
22
23
  * without a match are returned unchanged (no `franchise_id` key).
23
24
  */
24
- export declare function withFranchiseIds(teams: readonly Team[], franchises: readonly JsonObject[]): Team[];
25
+ export declare function withFranchiseIds(teams: readonly Team[], franchises: readonly Pick<Franchise, 'id' | 'fullName'>[]): Team[];
25
26
  /**
26
27
  * Get a list of all NHL teams with conference, division, and franchise info.
27
28
  *
@@ -44,13 +45,13 @@ export declare const teams: (ctx: Context, { date }?: {
44
45
  export declare const teamRoster: (ctx: Context, { teamAbbr, season }: {
45
46
  teamAbbr: string;
46
47
  season: Id;
47
- }) => Promise<JsonObject>;
48
+ }) => Promise<Roster>;
48
49
  /**
49
50
  * Get a list of all past and current NHL franchises.
50
51
  *
51
52
  * @example https://api.nhle.com/stats/rest/en/franchise
52
53
  */
53
- export declare const franchises: (ctx: Context) => Promise<JsonObject[]>;
54
+ export declare const franchises: (ctx: Context) => Promise<Franchise[]>;
54
55
  export declare const teamsApi: {
55
56
  readonly teams: typeof teams;
56
57
  readonly teamRoster: typeof teamRoster;
package/dist/index.d.mts CHANGED
@@ -18,4 +18,5 @@ export type { Context, Get } from '#src/context.mjs';
18
18
  export * from '#src/errors.mjs';
19
19
  export { buildUrl, createGet, Endpoint, type QueryParams, type QueryParamValue, } from '#src/http-client.mjs';
20
20
  export { createNHLClient, type NHLClient } from '#src/nhl-client.mjs';
21
- export type { Id, JsonObject } from '#src/utils.mjs';
21
+ export type * from '#src/types/index.mjs';
22
+ export type { Id } from '#src/utils.mjs';
@@ -1,8 +1,20 @@
1
+ import { type GoalieStatsSummaryParams, type SkaterStatsWithQueryContextParams, statsApi } from '#src/api/stats.mjs';
1
2
  import { type ClientOptions } from '#src/config.mjs';
2
3
  import type { Context } from '#src/context.mjs';
4
+ import type { GoalieReportRows, SkaterReportRows, StatsApiPage } from '#src/types/index.mjs';
3
5
  type Bound<Module> = {
4
6
  [Method in keyof Module]: Module[Method] extends (ctx: Context, ...args: infer Args) => infer MethodResponse ? (...args: Args) => MethodResponse : never;
5
7
  };
8
+ /**
9
+ * `Bound` erases generic parameters, so the report-typed stats methods are
10
+ * spelled out here (without `ctx`) to keep `reportType` / `statsType`
11
+ * flowing into the row type.
12
+ */
13
+ interface StatsGenericMethods {
14
+ skaterStatsWithQueryContext<Report extends keyof SkaterReportRows>(params: SkaterStatsWithQueryContextParams<Report>): Promise<StatsApiPage<SkaterReportRows[Report]>>;
15
+ goalieStatsSummary<Report extends keyof GoalieReportRows = 'summary'>(params: GoalieStatsSummaryParams<Report>): Promise<GoalieReportRows[Report][]>;
16
+ }
17
+ type StatsClient = Omit<Bound<typeof statsApi>, 'skaterStatsWithQueryContext' | 'goalieStatsSummary'> & StatsGenericMethods;
6
18
  /**
7
19
  * Builds the main client used to access the NHL API.
8
20
  *
@@ -42,15 +54,7 @@ export declare const createNHLClient: (options?: ClientOptions) => {
42
54
  readonly seasonSeriesMatchup: typeof import("#src/api/game-center.mjs").seasonSeriesMatchup;
43
55
  readonly gameStory: typeof import("#src/api/game-center.mjs").gameStory;
44
56
  }>;
45
- readonly stats: Bound<{
46
- readonly gametypesPerSeasonDirectoryByTeam: typeof import("#src/api/stats.mjs").gametypesPerSeasonDirectoryByTeam;
47
- readonly playerCareerStats: typeof import("#src/api/stats.mjs").playerCareerStats;
48
- readonly playerGameLog: typeof import("#src/api/stats.mjs").playerGameLog;
49
- readonly teamSummary: typeof import("#src/api/stats.mjs").teamSummary;
50
- readonly skaterStatsSummary: typeof import("#src/api/stats.mjs").skaterStatsSummary;
51
- readonly skaterStatsWithQueryContext: typeof import("#src/api/stats.mjs").skaterStatsWithQueryContext;
52
- readonly goalieStatsSummary: typeof import("#src/api/stats.mjs").goalieStatsSummary;
53
- }>;
57
+ readonly stats: StatsClient;
54
58
  readonly misc: Bound<{
55
59
  readonly glossary: typeof import("#src/api/misc.mjs").glossary;
56
60
  readonly config: typeof import("#src/api/misc.mjs").config;
@@ -5,7 +5,7 @@ import { miscApi } from '#src/api/misc.mjs';
5
5
  import { playersApi } from '#src/api/players.mjs';
6
6
  import { scheduleApi } from '#src/api/schedule.mjs';
7
7
  import { standingsApi } from '#src/api/standings.mjs';
8
- import { statsApi } from '#src/api/stats.mjs';
8
+ import { statsApi, } from '#src/api/stats.mjs';
9
9
  import { teamsApi } from '#src/api/teams.mjs';
10
10
  import { resolveConfig } from '#src/config.mjs';
11
11
  import { createGet } from '#src/http-client.mjs';
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A string union that still accepts values the SDK doesn't know about yet.
3
+ * Autocomplete lists `Known`, but a new value from the NHL doesn't break
4
+ * consumers.
5
+ */
6
+ export type OpenUnion<Known extends string> = Known | (string & {});
7
+ /** A name or label with optional translations; `default` is always present. */
8
+ export interface LocalizedString {
9
+ default: string;
10
+ cs?: string;
11
+ de?: string;
12
+ es?: string;
13
+ fi?: string;
14
+ fr?: string;
15
+ sk?: string;
16
+ sv?: string;
17
+ }
18
+ /** 1 = preseason, 2 = regular season, 3 = playoffs. Other codes (4 = all-star) exist. */
19
+ export type GameType = 1 | 2 | 3 | (number & {});
20
+ /** Season in YYYYYYYY form, e.g. 20232024. */
21
+ export type SeasonId = number;
22
+ export type GameState = OpenUnion<'FUT' | 'PRE' | 'LIVE' | 'CRIT' | 'FINAL' | 'OFF'>;
23
+ export type GameScheduleState = OpenUnion<'OK' | 'PPD' | 'SUSP' | 'CNCL' | 'TBD'>;
24
+ export type PeriodType = OpenUnion<'REG' | 'OT' | 'SO'>;
25
+ export type PositionCode = OpenUnion<'C' | 'L' | 'R' | 'D' | 'G'>;
26
+ export type ShootsCatches = OpenUnion<'L' | 'R'>;
27
+ export type ZoneCode = OpenUnion<'O' | 'N' | 'D'>;
28
+ export type ShotType = OpenUnion<'wrist' | 'snap' | 'slap' | 'backhand' | 'tip-in' | 'deflected' | 'wrap-around' | 'bat'>;
29
+ /** Envelope of the stats API (`api.nhle.com/stats/rest`) for paged reports. */
30
+ export interface StatsApiPage<Row> {
31
+ data: Row[];
32
+ total: number;
33
+ }
34
+ export interface GameOutcome {
35
+ lastPeriodType: PeriodType;
36
+ /** Low sample count */
37
+ otPeriods?: number;
38
+ }
39
+ export interface PeriodDescriptor {
40
+ number: number;
41
+ periodType: PeriodType;
42
+ maxRegulationPeriods: number;
43
+ }
44
+ export interface SeriesStatus {
45
+ round: number;
46
+ seriesAbbrev: string;
47
+ seriesTitle: string;
48
+ seriesLetter: string;
49
+ neededToWin: number;
50
+ topSeedTeamAbbrev: string;
51
+ topSeedWins: number;
52
+ bottomSeedTeamAbbrev: string;
53
+ bottomSeedWins: number;
54
+ gameNumberOfSeries: number;
55
+ }
56
+ export interface TeamLogo {
57
+ light: string;
58
+ dark: string;
59
+ }
60
+ export interface TvBroadcast {
61
+ id: number;
62
+ market: string;
63
+ countryCode: string;
64
+ network: string;
65
+ sequenceNumber: number;
66
+ }
67
+ export interface OddsPartner {
68
+ partnerId: number;
69
+ country: string;
70
+ name: string;
71
+ imageUrl: string;
72
+ siteUrl: string;
73
+ bgColor: string;
74
+ textColor: string;
75
+ accentColor: string;
76
+ }
77
+ /** A betting provider's price for one side of a game. */
78
+ export interface TeamOdd {
79
+ providerId: number;
80
+ value: string;
81
+ }
@@ -0,0 +1,2 @@
1
+ // Response types derived from live NHL API probing. See CONTRIBUTING.md.
2
+ export {};