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.
Files changed (40) hide show
  1. package/README.md +72 -5
  2. package/dist/api/draft.d.mts +61 -0
  3. package/dist/api/draft.mjs +68 -0
  4. package/dist/api/edge.d.mts +198 -1
  5. package/dist/api/edge.mjs +207 -4
  6. package/dist/api/game-center.d.mts +49 -1
  7. package/dist/api/game-center.mjs +47 -0
  8. package/dist/api/misc.d.mts +115 -1
  9. package/dist/api/misc.mjs +147 -2
  10. package/dist/api/players.d.mts +55 -3
  11. package/dist/api/players.mjs +80 -3
  12. package/dist/api/query/cayenne.d.mts +4 -0
  13. package/dist/api/query/cayenne.mjs +13 -0
  14. package/dist/api/query/sorting/sorting-options.d.mts +8 -0
  15. package/dist/api/query/sorting/sorting-options.mjs +30 -0
  16. package/dist/api/schedule.d.mts +19 -6
  17. package/dist/api/schedule.mjs +17 -5
  18. package/dist/api/stats.d.mts +95 -6
  19. package/dist/api/stats.mjs +130 -30
  20. package/dist/api/teams.d.mts +43 -3
  21. package/dist/api/teams.mjs +51 -3
  22. package/dist/cli/commands.mjs +487 -22
  23. package/dist/http-client.d.mts +2 -1
  24. package/dist/http-client.mjs +8 -1
  25. package/dist/index.d.mts +8 -2
  26. package/dist/index.mjs +3 -0
  27. package/dist/nhl-client.d.mts +69 -14
  28. package/dist/nhl-client.mjs +33 -12
  29. package/dist/types/draft.d.mts +97 -0
  30. package/dist/types/draft.mjs +1 -0
  31. package/dist/types/edge.d.mts +299 -3
  32. package/dist/types/game-center.d.mts +223 -8
  33. package/dist/types/index.d.mts +1 -0
  34. package/dist/types/misc.d.mts +101 -0
  35. package/dist/types/misc.mjs +0 -1
  36. package/dist/types/players.d.mts +22 -0
  37. package/dist/types/schedule.d.mts +16 -0
  38. package/dist/types/stats.d.mts +207 -1
  39. package/dist/types/teams.d.mts +29 -1
  40. package/package.json +1 -1
@@ -73,6 +73,42 @@ const defaultCayenneExp = {
73
73
  type: 'string',
74
74
  description: 'Overrides the generated cayenneExp filter entirely',
75
75
  };
76
+ const currentSeason = {
77
+ ...season,
78
+ description: `${season.description}. Defaults to current`,
79
+ };
80
+ const nowSeason = {
81
+ ...season,
82
+ description: `${season.description}. Defaults to now`,
83
+ };
84
+ const draftSeason = {
85
+ name: 'season',
86
+ type: 'string',
87
+ description: 'Draft year in YYYY format, e.g. 2023. Defaults to now',
88
+ };
89
+ const seasonGameType = {
90
+ name: 'gameType',
91
+ type: 'int',
92
+ description: '2=Regular season, 3=Playoffs (only used with --season)',
93
+ default: '2',
94
+ };
95
+ const allTimeSeason = {
96
+ ...season,
97
+ description: `${season.description}. Defaults to every season`,
98
+ };
99
+ function leaderCategories(choices) {
100
+ return {
101
+ name: 'categories',
102
+ type: 'list',
103
+ description: `Comma-separated categories (${choices.join(', ')}). Defaults to all`,
104
+ };
105
+ }
106
+ const leaderLimit = {
107
+ name: 'limit',
108
+ type: 'int',
109
+ description: 'Rows per category (-1 for all)',
110
+ default: '5',
111
+ };
76
112
  function apiSleepRate(def) {
77
113
  return {
78
114
  name: 'apiSleepRate',
@@ -82,16 +118,8 @@ function apiSleepRate(def) {
82
118
  };
83
119
  }
84
120
  // ---- Edge -------------------------------------------------------------------
85
- const edgeSeasonArgs = [
86
- { ...season, description: `${season.description}. Defaults to current` },
87
- {
88
- name: 'gameType',
89
- type: 'int',
90
- description: '2=Regular season, 3=Playoffs (only used with --season)',
91
- default: '2',
92
- },
93
- ];
94
- function edgeCommand(name, method, idKind, description) {
121
+ const edgeSeasonArgs = [currentSeason, seasonGameType];
122
+ function edgeCommand(name, method, idKind, description, extraArgs = []) {
95
123
  const idArg = idKind === 'player'
96
124
  ? [playerId]
97
125
  : idKind === 'team'
@@ -106,12 +134,62 @@ function edgeCommand(name, method, idKind, description) {
106
134
  return {
107
135
  name,
108
136
  description,
109
- args: [...idArg, ...edgeSeasonArgs],
137
+ args: [...idArg, ...extraArgs, ...edgeSeasonArgs],
110
138
  run: (client, values) =>
111
139
  // biome-ignore lint/suspicious/noExplicitAny: dispatch by method name
112
140
  client.edge[method].call(client.edge, values),
113
141
  };
114
142
  }
143
+ const edgePositions = {
144
+ name: 'positions',
145
+ type: 'string',
146
+ description: 'Player positions',
147
+ default: 'all',
148
+ choices: ['all', 'forwards', 'defense'],
149
+ };
150
+ const edgeStrength = {
151
+ name: 'strength',
152
+ type: 'string',
153
+ description: 'all, es (even strength), pp (power play) or pk (penalty kill)',
154
+ default: 'all',
155
+ choices: ['all', 'es', 'pp', 'pk'],
156
+ };
157
+ const edgeShotLocationCategory = {
158
+ name: 'category',
159
+ type: 'string',
160
+ description: 'Shot area: all, high (danger), mid (range) or long (range)',
161
+ default: 'all',
162
+ choices: ['all', 'high', 'mid', 'long'],
163
+ };
164
+ function edgeSortBy(choices) {
165
+ return req({
166
+ name: 'sortBy',
167
+ type: 'string',
168
+ description: 'Metric to rank by',
169
+ choices,
170
+ });
171
+ }
172
+ const edgeZoneSortBy = req({
173
+ name: 'sortBy',
174
+ type: 'string',
175
+ description: 'Zone to rank by',
176
+ choices: ['offensive', 'neutral', 'defensive'],
177
+ });
178
+ const distanceSortBy = edgeSortBy([
179
+ 'total',
180
+ 'per-60',
181
+ 'max-game',
182
+ 'max-period',
183
+ ]);
184
+ const skatingSpeedSortBy = edgeSortBy(['max', 'over-22', '20-22', '18-20']);
185
+ const shotSpeedSortBy = edgeSortBy([
186
+ 'max',
187
+ 'over-100',
188
+ '90-99',
189
+ '80-89',
190
+ '70-79',
191
+ ]);
192
+ const shotLocationSortBy = edgeSortBy(['sog', 'goals', 'shooting-pctg']);
115
193
  // ---- Stats query-context filters --------------------------------------------
116
194
  const queryFilterArgs = [
117
195
  {
@@ -257,15 +335,45 @@ export const MODULES = [
257
335
  {
258
336
  name: 'team-roster',
259
337
  description: 'Roster for a team and season',
260
- args: [teamAbbr, req(season)],
338
+ args: [teamAbbr, currentSeason],
261
339
  run: (client, values) => client.teams.teamRoster(values),
262
340
  },
341
+ {
342
+ name: 'roster-seasons',
343
+ description: 'Every season a team has a roster for',
344
+ args: [teamAbbr],
345
+ run: (client, values) => client.teams.rosterSeasons(values),
346
+ },
347
+ {
348
+ name: 'team-scoreboard',
349
+ description: "A team's recent and upcoming games",
350
+ args: [teamAbbr],
351
+ run: (client, values) => client.teams.teamScoreboard(values),
352
+ },
263
353
  {
264
354
  name: 'franchises',
265
355
  description: 'All past and current NHL franchises',
266
356
  args: [],
267
357
  run: (client) => client.teams.franchises(),
268
358
  },
359
+ {
360
+ name: 'stats-teams',
361
+ description: 'Every team in the stats API, past and present',
362
+ args: [],
363
+ run: (client) => client.teams.statsTeams(),
364
+ },
365
+ {
366
+ name: 'team-by-id',
367
+ description: 'One stats API team by its team id',
368
+ args: [
369
+ req({
370
+ name: 'teamId',
371
+ type: 'string',
372
+ description: 'NHL team id, e.g. 10',
373
+ }),
374
+ ],
375
+ run: (client, values) => client.teams.teamById(values),
376
+ },
269
377
  ],
270
378
  },
271
379
  {
@@ -324,13 +432,13 @@ export const MODULES = [
324
432
  {
325
433
  name: 'team-season-schedule',
326
434
  description: "A team's full season schedule",
327
- args: [teamAbbr, req(season)],
435
+ args: [teamAbbr, nowSeason],
328
436
  run: (client, values) => client.schedule.teamSeasonSchedule(values),
329
437
  },
330
438
  {
331
439
  name: 'calendar-schedule',
332
440
  description: 'Schedule in calendar format for a date',
333
- args: [req(date())],
441
+ args: [date('Date in YYYY-MM-DD format. Defaults to now')],
334
442
  run: (client, values) => client.schedule.calendarSchedule(values),
335
443
  },
336
444
  {
@@ -352,6 +460,19 @@ export const MODULES = [
352
460
  ],
353
461
  run: (client, values) => client.schedule.playoffSeriesSchedule(values),
354
462
  },
463
+ {
464
+ name: 'playoff-series-meta',
465
+ description: 'Round title and seeded teams of one playoff series',
466
+ args: [
467
+ req({ name: 'year', type: 'string', description: 'Year, e.g. 2024' }),
468
+ req({
469
+ name: 'series',
470
+ type: 'string',
471
+ description: 'Series letter: a-h first round ... o final',
472
+ }),
473
+ ],
474
+ run: (client, values) => client.schedule.playoffSeriesMeta(values),
475
+ },
355
476
  {
356
477
  name: 'playoff-bracket',
357
478
  description: 'Full playoff bracket for a year',
@@ -416,6 +537,37 @@ export const MODULES = [
416
537
  args: [gameId],
417
538
  run: (client, values) => client.gameCenter.gameStory(values),
418
539
  },
540
+ {
541
+ name: 'scoreboard',
542
+ description: 'Every game in the week around a date, grouped by date',
543
+ args: [date('Date in YYYY-MM-DD format. Defaults to now')],
544
+ run: (client, values) => client.gameCenter.scoreboard(values),
545
+ },
546
+ {
547
+ name: 'wsc-play-by-play',
548
+ description: 'Flat play-by-play feed used by the nhl.com game story',
549
+ args: [gameId],
550
+ run: (client, values) => client.gameCenter.wscPlayByPlay(values),
551
+ },
552
+ {
553
+ name: 'play-replay',
554
+ description: 'Replay card for one play-by-play event',
555
+ args: [
556
+ gameId,
557
+ req({
558
+ name: 'eventNumber',
559
+ type: 'string',
560
+ description: "The play's eventId from play-by-play, e.g. 193",
561
+ }),
562
+ ],
563
+ run: (client, values) => client.gameCenter.playReplay(values),
564
+ },
565
+ {
566
+ name: 'game-meta',
567
+ description: 'Teams, season state and game state for a game',
568
+ args: [gameId],
569
+ run: (client, values) => client.gameCenter.gameMeta(values),
570
+ },
419
571
  ],
420
572
  },
421
573
  {
@@ -439,19 +591,63 @@ export const MODULES = [
439
591
  description: "A player's game log for a season",
440
592
  args: [
441
593
  playerId,
442
- req({
594
+ {
443
595
  name: 'seasonId',
444
596
  type: 'string',
445
- description: 'Season in YYYYYYYY format',
446
- }),
447
- req({
597
+ description: 'Season in YYYYYYYY format. Defaults to now',
598
+ },
599
+ {
448
600
  name: 'gameType',
449
601
  type: 'int',
450
- description: '1=Preseason, 2=Regular, 3=Playoffs',
451
- }),
602
+ description: '1=Preseason, 2=Regular, 3=Playoffs (only used with --season-id)',
603
+ default: '2',
604
+ },
452
605
  ],
453
606
  run: (client, values) => client.stats.playerGameLog(values),
454
607
  },
608
+ {
609
+ name: 'skater-stats-leaders',
610
+ description: 'Skater stats leaders by category for a season',
611
+ args: [
612
+ currentSeason,
613
+ seasonGameType,
614
+ leaderCategories([
615
+ 'goals',
616
+ 'assists',
617
+ 'points',
618
+ 'plusMinus',
619
+ 'penaltyMins',
620
+ 'goalsPp',
621
+ 'goalsSh',
622
+ 'faceoffLeaders',
623
+ 'toi',
624
+ ]),
625
+ leaderLimit,
626
+ ],
627
+ run: (client, values) => client.stats.skaterStatsLeaders(values),
628
+ },
629
+ {
630
+ name: 'goalie-stats-leaders',
631
+ description: 'Goalie stats leaders by category for a season',
632
+ args: [
633
+ currentSeason,
634
+ seasonGameType,
635
+ leaderCategories([
636
+ 'wins',
637
+ 'shutouts',
638
+ 'savePctg',
639
+ 'goalsAgainstAverage',
640
+ ]),
641
+ leaderLimit,
642
+ ],
643
+ run: (client, values) => client.stats.goalieStatsLeaders(values),
644
+ },
645
+ {
646
+ name: 'club-stats',
647
+ description: "A team's skater and goalie stats for a season",
648
+ args: [teamAbbr, nowSeason, seasonGameType],
649
+ run: (client, values) => client.stats.clubStats(values),
650
+ },
455
651
  {
456
652
  name: 'team-summary',
457
653
  description: 'Team summary stats across seasons',
@@ -585,6 +781,52 @@ export const MODULES = [
585
781
  ],
586
782
  run: (client, values) => client.stats.goalieStatsSummary(values),
587
783
  },
784
+ {
785
+ name: 'skater-leaders',
786
+ description: 'Top 10 single-season skater records for a stat (stats API)',
787
+ args: [
788
+ req({
789
+ name: 'attribute',
790
+ type: 'string',
791
+ description: 'Stat to rank by',
792
+ choices: ['points', 'goals', 'assists', 'gamesPlayed'],
793
+ }),
794
+ allTimeSeason,
795
+ ],
796
+ run: (client, values) => client.stats.skaterLeaders(values),
797
+ },
798
+ {
799
+ name: 'goalie-leaders',
800
+ description: 'Top 10 single-season goalie records for a stat (stats API)',
801
+ args: [
802
+ req({
803
+ name: 'attribute',
804
+ type: 'string',
805
+ description: 'Stat to rank by',
806
+ choices: [
807
+ 'gaa',
808
+ 'savePctg',
809
+ 'shutouts',
810
+ 'timeOnIce',
811
+ 'gamesPlayed',
812
+ ],
813
+ }),
814
+ allTimeSeason,
815
+ ],
816
+ run: (client, values) => client.stats.goalieLeaders(values),
817
+ },
818
+ {
819
+ name: 'skater-milestones',
820
+ description: 'Career milestones active skaters are approaching',
821
+ args: [],
822
+ run: (client) => client.stats.skaterMilestones(),
823
+ },
824
+ {
825
+ name: 'goalie-milestones',
826
+ description: 'Career milestones active goalies are approaching',
827
+ args: [],
828
+ run: (client) => client.stats.goalieMilestones(),
829
+ },
588
830
  ],
589
831
  },
590
832
  {
@@ -614,11 +856,29 @@ export const MODULES = [
614
856
  edgeCommand('team-landing', 'teamLanding', 'none', 'EDGE team landing page (league leaders)'),
615
857
  edgeCommand('team-shot-speed-detail', 'teamShotSpeedDetail', 'team', 'EDGE team shot speed'),
616
858
  edgeCommand('team-skating-speed-detail', 'teamSkatingSpeedDetail', 'team', 'EDGE team skating speed'),
859
+ edgeCommand('team-comparison', 'teamComparison', 'team', 'EDGE team comparison stats'),
860
+ edgeCommand('skater-distance-top-10', 'skaterDistanceTop10', 'none', 'EDGE top 10 skaters by skating distance', [edgePositions, edgeStrength, distanceSortBy]),
861
+ edgeCommand('skater-speed-top-10', 'skaterSpeedTop10', 'none', 'EDGE top 10 skaters by skating speed', [edgePositions, skatingSpeedSortBy]),
862
+ edgeCommand('skater-zone-time-top-10', 'skaterZoneTimeTop10', 'none', 'EDGE top 10 skaters by zone time', [edgePositions, edgeStrength, edgeZoneSortBy]),
863
+ edgeCommand('skater-shot-speed-top-10', 'skaterShotSpeedTop10', 'none', 'EDGE top 10 skaters by shot speed', [edgePositions, shotSpeedSortBy]),
864
+ edgeCommand('skater-shot-location-top-10', 'skaterShotLocationTop10', 'none', 'EDGE top 10 skaters by shot location', [edgePositions, shotLocationSortBy, edgeShotLocationCategory]),
865
+ edgeCommand('goalie-5v5-top-10', 'goalie5v5Top10', 'none', 'EDGE top 10 goalies at 5v5', [edgeSortBy(['save-pctg', 'save-pctg-close', 'shots', 'shots-per-60'])]),
866
+ edgeCommand('goalie-shot-location-top-10', 'goalieShotLocationTop10', 'none', 'EDGE top 10 goalies by shot location', [
867
+ edgeSortBy(['save-pctg', 'saves', 'goals-against', 'shots-against']),
868
+ edgeShotLocationCategory,
869
+ ]),
870
+ edgeCommand('goalie-save-percentage-top-10', 'goalieSavePercentageTop10', 'none', 'EDGE top 10 goalies by games above .900', [edgeSortBy(['games', 'pctg'])]),
871
+ edgeCommand('team-skating-distance-top-10', 'teamSkatingDistanceTop10', 'none', 'EDGE top 10 teams by skating distance', [edgePositions, edgeStrength, distanceSortBy]),
872
+ edgeCommand('team-skating-speed-top-10', 'teamSkatingSpeedTop10', 'none', 'EDGE top 10 teams by skating speed', [edgePositions, skatingSpeedSortBy]),
873
+ edgeCommand('team-zone-time-top-10', 'teamZoneTimeTop10', 'none', 'EDGE top 10 teams by zone time', [edgeStrength, edgeZoneSortBy]),
874
+ edgeCommand('team-shot-speed-top-10', 'teamShotSpeedTop10', 'none', 'EDGE top 10 teams by shot speed', [edgePositions, shotSpeedSortBy]),
875
+ edgeCommand('team-shot-location-top-10', 'teamShotLocationTop10', 'none', 'EDGE top 10 teams by shot location', [edgePositions, shotLocationSortBy, edgeShotLocationCategory]),
876
+ edgeCommand('by-the-numbers', 'byTheNumbers', 'none', 'EDGE league highlights (latest night, or season bests with --season)'),
617
877
  ],
618
878
  },
619
879
  {
620
880
  name: 'players',
621
- description: 'Prospects and team rosters',
881
+ description: 'Prospects, team rosters and player search',
622
882
  commands: [
623
883
  {
624
884
  name: 'prospects-by-team',
@@ -629,9 +889,110 @@ export const MODULES = [
629
889
  {
630
890
  name: 'players-by-team',
631
891
  description: "A team's roster for a season",
632
- args: [teamAbbr, req(season)],
892
+ args: [teamAbbr, currentSeason],
633
893
  run: (client, values) => client.players.playersByTeam(values),
634
894
  },
895
+ {
896
+ name: 'player-spotlight',
897
+ description: 'Players featured in the nhl.com spotlight',
898
+ args: [],
899
+ run: (client) => client.players.playerSpotlight(),
900
+ },
901
+ {
902
+ name: 'player-search',
903
+ description: 'Search every player (needs a filter). At most 5 rows per page; page with --start',
904
+ args: [
905
+ {
906
+ name: 'name',
907
+ type: 'string',
908
+ description: 'Case-insensitive part of the full name, e.g. matth',
909
+ },
910
+ {
911
+ name: 'teamId',
912
+ type: 'string',
913
+ description: 'NHL team id of the current team, e.g. 10',
914
+ },
915
+ {
916
+ name: 'position',
917
+ type: 'string',
918
+ description: 'Position; F matches every forward',
919
+ choices: ['C', 'L', 'R', 'D', 'G', 'F'],
920
+ },
921
+ {
922
+ name: 'cayenneExp',
923
+ type: 'string',
924
+ description: 'Extra filter, e.g. sweaterNumber=34',
925
+ },
926
+ {
927
+ name: 'sort',
928
+ type: 'string',
929
+ description: 'Field to sort by, e.g. lastName',
930
+ },
931
+ {
932
+ name: 'dir',
933
+ type: 'string',
934
+ description: 'Sort direction',
935
+ choices: ['ASC', 'DESC'],
936
+ },
937
+ start,
938
+ {
939
+ name: 'include',
940
+ type: 'list',
941
+ description: 'Comma-separated fields to return, e.g. id,fullName',
942
+ },
943
+ {
944
+ name: 'exclude',
945
+ type: 'list',
946
+ description: 'Comma-separated fields to leave out',
947
+ },
948
+ ],
949
+ run: (client, values) => client.players.playerSearch(values),
950
+ },
951
+ ],
952
+ },
953
+ {
954
+ name: 'draft',
955
+ description: 'Draft rankings, picks and the live draft tracker',
956
+ commands: [
957
+ {
958
+ name: 'rankings',
959
+ description: 'Central Scouting rankings for one prospect category',
960
+ args: [
961
+ draftSeason,
962
+ {
963
+ name: 'category',
964
+ type: 'int',
965
+ description: '1=NA skater, 2=Intl skater, 3=NA goalie, 4=Intl goalie (only used with --season)',
966
+ default: '1',
967
+ choices: ['1', '2', '3', '4'],
968
+ },
969
+ ],
970
+ run: (client, values) => client.draft.rankings(values),
971
+ },
972
+ {
973
+ name: 'tracker',
974
+ description: 'Live draft tracker for the current draft',
975
+ args: [],
976
+ run: (client) => client.draft.tracker(),
977
+ },
978
+ {
979
+ name: 'picks',
980
+ description: 'Picks of a draft. Without --season, round 1 of the current draft',
981
+ args: [
982
+ draftSeason,
983
+ {
984
+ name: 'round',
985
+ type: 'string',
986
+ description: 'Round 1-7 or all (only used with --season)',
987
+ default: 'all',
988
+ choices: ['1', '2', '3', '4', '5', '6', '7', 'all'],
989
+ },
990
+ ],
991
+ run: (client, { round, ...values }) => client.draft.picks({
992
+ ...values,
993
+ round: round === undefined || round === 'all' ? round : Number(round),
994
+ }),
995
+ },
635
996
  ],
636
997
  },
637
998
  {
@@ -668,6 +1029,110 @@ export const MODULES = [
668
1029
  args: [],
669
1030
  run: (client) => client.misc.draftYearAndRounds(),
670
1031
  },
1032
+ {
1033
+ name: 'component-seasons',
1034
+ description: 'Season and game type the stats API serves by default',
1035
+ args: [],
1036
+ run: (client) => client.misc.componentSeasons(),
1037
+ },
1038
+ {
1039
+ name: 'ping',
1040
+ description: 'Check that the stats API is up (prints true)',
1041
+ args: [],
1042
+ run: (client) => client.misc.ping(),
1043
+ },
1044
+ {
1045
+ name: 'games',
1046
+ description: 'Games from the stats API (needs at least one filter)',
1047
+ args: [
1048
+ season,
1049
+ {
1050
+ name: 'gameType',
1051
+ type: 'int',
1052
+ description: '1=Preseason, 2=Regular season, 3=Playoffs',
1053
+ },
1054
+ {
1055
+ name: 'teamId',
1056
+ type: 'string',
1057
+ description: 'NHL team id, home or away, e.g. 10',
1058
+ },
1059
+ {
1060
+ name: 'startDate',
1061
+ type: 'string',
1062
+ description: 'First game date, YYYY-MM-DD',
1063
+ },
1064
+ {
1065
+ name: 'endDate',
1066
+ type: 'string',
1067
+ description: 'Last game date, YYYY-MM-DD',
1068
+ },
1069
+ {
1070
+ name: 'cayenneExp',
1071
+ type: 'string',
1072
+ description: 'Extra filter, e.g. homeScore>=7',
1073
+ },
1074
+ ],
1075
+ run: (client, values) => client.misc.games(values),
1076
+ },
1077
+ {
1078
+ name: 'tv-schedule',
1079
+ description: 'National TV broadcasts for the week around a date',
1080
+ args: [date('Date in YYYY-MM-DD format. Defaults to now')],
1081
+ run: (client, values) => client.misc.tvSchedule(values),
1082
+ },
1083
+ {
1084
+ name: 'partner-game-odds',
1085
+ description: "Betting odds for today's games from a country's partner",
1086
+ args: [
1087
+ req({
1088
+ name: 'countryCode',
1089
+ type: 'string',
1090
+ description: 'Two-letter country code, e.g. US, CA',
1091
+ }),
1092
+ ],
1093
+ run: (client, values) => client.misc.partnerGameOdds(values),
1094
+ },
1095
+ {
1096
+ name: 'season-ids',
1097
+ description: 'Every NHL season id, oldest first',
1098
+ args: [],
1099
+ run: (client) => client.misc.seasonIds(),
1100
+ },
1101
+ {
1102
+ name: 'meta',
1103
+ description: 'Display metadata for players and teams',
1104
+ args: [
1105
+ {
1106
+ name: 'players',
1107
+ type: 'int-list',
1108
+ description: 'Comma-separated player ids, e.g. 8478402,8476945',
1109
+ },
1110
+ {
1111
+ name: 'teams',
1112
+ type: 'list',
1113
+ description: 'Comma-separated team abbreviations, e.g. TOR,BUF',
1114
+ },
1115
+ ],
1116
+ run: (client, values) => client.misc.meta(values),
1117
+ },
1118
+ {
1119
+ name: 'location',
1120
+ description: "The caller's country, from their IP address",
1121
+ args: [],
1122
+ run: (client) => client.misc.location(),
1123
+ },
1124
+ {
1125
+ name: 'postal-lookup',
1126
+ description: 'Teams whose broadcast market covers a postal code',
1127
+ args: [
1128
+ req({
1129
+ name: 'postalCode',
1130
+ type: 'string',
1131
+ description: 'Postal or ZIP code, e.g. 90210',
1132
+ }),
1133
+ ],
1134
+ run: (client, values) => client.misc.postalLookup(values),
1135
+ },
671
1136
  ],
672
1137
  },
673
1138
  {
@@ -8,7 +8,8 @@ export declare const Endpoint: {
8
8
  };
9
9
  export type Endpoint = (typeof Endpoint)[keyof typeof Endpoint];
10
10
  export type QueryParamValue = string | number | boolean | null | undefined;
11
- export type QueryParams = Record<string, QueryParamValue>;
11
+ /** An array value repeats the key once per element (`include=a&include=b`). */
12
+ export type QueryParams = Record<string, QueryParamValue | readonly QueryParamValue[]>;
12
13
  export declare function buildUrl(endpoint: Endpoint, resource: string, queryParams?: QueryParams): string;
13
14
  /** Maps a non-2xx HTTP status to the matching NHLApiException subclass. */
14
15
  export declare function errorForStatus(status: number, message: string): NHLApiException;
@@ -18,7 +18,14 @@ export function buildUrl(endpoint, resource, queryParams) {
18
18
  }
19
19
  const search = new URLSearchParams();
20
20
  for (const [key, value] of Object.entries(queryParams)) {
21
- search.append(key, paramToString(value));
21
+ if (Array.isArray(value)) {
22
+ for (const item of value) {
23
+ search.append(key, paramToString(item));
24
+ }
25
+ }
26
+ else {
27
+ search.append(key, paramToString(value));
28
+ }
22
29
  }
23
30
  const qs = search.toString();
24
31
  if (!qs) {
package/dist/index.d.mts CHANGED
@@ -1,15 +1,21 @@
1
- export type { EdgePlayerParams, EdgeSeasonParams, EdgeTeamParams, } from '#src/api/edge.mjs';
1
+ export type { DraftPicksParams, DraftRankingsParams, DraftRound, } from '#src/api/draft.mjs';
2
+ export * as draft from '#src/api/draft.mjs';
3
+ export { ProspectCategory } from '#src/api/draft.mjs';
4
+ export type { EdgeGoalie5v5SortBy, EdgeGoalieSavePercentageSortBy, EdgeGoalieShotLocationSortBy, EdgeGoalieShotLocationTop10Params, EdgePlayerParams, EdgePosition, EdgePositionTop10Params, EdgeSeasonParams, EdgeShotLocationCategory, EdgeShotLocationSortBy, EdgeShotLocationTop10Params, EdgeShotSpeedSortBy, EdgeSkatingDistanceSortBy, EdgeSkatingSpeedSortBy, EdgeStrength, EdgeStrengthTop10Params, EdgeTeamParams, EdgeTeamZoneTimeTop10Params, EdgeTop10Params, EdgeZone, } from '#src/api/edge.mjs';
2
5
  export * as edge from '#src/api/edge.mjs';
6
+ export { EdgePositions, EdgeStrengths, EdgeZones } from '#src/api/edge.mjs';
3
7
  export * as gameCenter from '#src/api/game-center.mjs';
4
8
  export * as helpers from '#src/api/helpers.mjs';
9
+ export type { GamesParams } from '#src/api/misc.mjs';
5
10
  export * as misc from '#src/api/misc.mjs';
11
+ export type { PlayerSearchParams } from '#src/api/players.mjs';
6
12
  export * as players from '#src/api/players.mjs';
7
13
  export * from '#src/api/query/index.mjs';
8
14
  export type { DailySchedule } from '#src/api/schedule.mjs';
9
15
  export * as schedule from '#src/api/schedule.mjs';
10
16
  export { normalizeDate } from '#src/api/schedule.mjs';
11
17
  export * as standings from '#src/api/standings.mjs';
12
- export type { GoalieStatsSummaryParams, SkaterStatsSummaryParams, SkaterStatsWithQueryContextParams, TeamSummaryParams, } from '#src/api/stats.mjs';
18
+ export type { GoalieStatsSummaryParams, SkaterStatsSummaryParams, SkaterStatsWithQueryContextParams, StatsApiLeadersParams, StatsLeadersParams, TeamSummaryParams, } from '#src/api/stats.mjs';
13
19
  export * as stats from '#src/api/stats.mjs';
14
20
  export type { Team } from '#src/api/teams.mjs';
15
21
  export * as teams from '#src/api/teams.mjs';
package/dist/index.mjs CHANGED
@@ -1,4 +1,7 @@
1
+ export * as draft from '#src/api/draft.mjs';
2
+ export { ProspectCategory } from '#src/api/draft.mjs';
1
3
  export * as edge from '#src/api/edge.mjs';
4
+ export { EdgePositions, EdgeStrengths, EdgeZones } from '#src/api/edge.mjs';
2
5
  export * as gameCenter from '#src/api/game-center.mjs';
3
6
  export * as helpers from '#src/api/helpers.mjs';
4
7
  export * as misc from '#src/api/misc.mjs';