nhl-api-ts 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +295 -2
- package/dist/api/edge.d.mts +179 -0
- package/dist/api/edge.mjs +184 -0
- package/dist/api/game-center.d.mts +83 -0
- package/dist/api/game-center.mjs +74 -0
- package/dist/api/helpers.d.mts +46 -0
- package/dist/api/helpers.mjs +106 -0
- package/dist/api/misc.d.mts +40 -0
- package/dist/api/misc.mjs +43 -0
- package/dist/api/players.d.mts +27 -0
- package/dist/api/players.mjs +18 -0
- package/dist/api/query/builder.d.mts +20 -0
- package/dist/api/query/builder.mjs +28 -0
- package/dist/api/query/errors.d.mts +3 -0
- package/dist/api/query/errors.mjs +6 -0
- package/dist/api/query/filters/base.d.mts +4 -0
- package/dist/api/query/filters/base.mjs +2 -0
- package/dist/api/query/filters/decision.d.mts +13 -0
- package/dist/api/query/filters/decision.mjs +26 -0
- package/dist/api/query/filters/draft.d.mts +15 -0
- package/dist/api/query/filters/draft.mjs +27 -0
- package/dist/api/query/filters/experience.d.mts +9 -0
- package/dist/api/query/filters/experience.mjs +17 -0
- package/dist/api/query/filters/franchise.d.mts +9 -0
- package/dist/api/query/filters/franchise.mjs +15 -0
- package/dist/api/query/filters/game-type.d.mts +10 -0
- package/dist/api/query/filters/game-type.mjs +16 -0
- package/dist/api/query/filters/goalie-sorts.d.mts +3 -0
- package/dist/api/query/filters/goalie-sorts.mjs +55 -0
- package/dist/api/query/filters/home-road.d.mts +9 -0
- package/dist/api/query/filters/home-road.mjs +16 -0
- package/dist/api/query/filters/index.d.mts +14 -0
- package/dist/api/query/filters/index.mjs +14 -0
- package/dist/api/query/filters/nationality.d.mts +12 -0
- package/dist/api/query/filters/nationality.mjs +19 -0
- package/dist/api/query/filters/opponent.d.mts +10 -0
- package/dist/api/query/filters/opponent.mjs +16 -0
- package/dist/api/query/filters/position.d.mts +16 -0
- package/dist/api/query/filters/position.mjs +28 -0
- package/dist/api/query/filters/season.d.mts +14 -0
- package/dist/api/query/filters/season.mjs +24 -0
- package/dist/api/query/filters/shoot-catch.d.mts +9 -0
- package/dist/api/query/filters/shoot-catch.mjs +16 -0
- package/dist/api/query/filters/status.d.mts +20 -0
- package/dist/api/query/filters/status.mjs +28 -0
- package/dist/api/query/filters.d.mts +93 -0
- package/dist/api/query/filters.mjs +118 -0
- package/dist/api/query/index.d.mts +4 -0
- package/dist/api/query/index.mjs +4 -0
- package/dist/api/query/sorting/goalie-sorts.d.mts +6 -0
- package/dist/api/query/sorting/goalie-sorts.mjs +59 -0
- package/dist/api/query/sorting/sorting-options.d.mts +11 -0
- package/dist/api/query/sorting/sorting-options.mjs +93 -0
- package/dist/api/schedule.d.mts +116 -0
- package/dist/api/schedule.mjs +131 -0
- package/dist/api/standings.d.mts +28 -0
- package/dist/api/standings.mjs +38 -0
- package/dist/api/stats.d.mts +148 -0
- package/dist/api/stats.mjs +148 -0
- package/dist/api/teams.d.mts +58 -0
- package/dist/api/teams.mjs +91 -0
- package/dist/cli/colors.d.mts +14 -0
- package/dist/cli/colors.mjs +13 -0
- package/dist/cli/commands.d.mts +27 -0
- package/dist/cli/commands.mjs +695 -0
- package/dist/cli/run.d.mts +9 -0
- package/dist/cli/run.mjs +313 -0
- package/dist/cli.d.mts +2 -0
- package/dist/cli.mjs +13 -0
- package/dist/config.d.mts +20 -0
- package/dist/config.mjs +4 -0
- package/dist/context.d.mts +6 -0
- package/dist/context.mjs +1 -0
- package/dist/errors.d.mts +35 -0
- package/dist/errors.mjs +49 -0
- package/dist/http-client.d.mts +27 -0
- package/dist/http-client.mjs +95 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +15 -0
- package/dist/logging.d.mts +14 -0
- package/dist/logging.mjs +13 -0
- package/dist/nhl-client.d.mts +97 -0
- package/dist/nhl-client.mjs +40 -0
- package/dist/utils.d.mts +5 -0
- package/dist/utils.mjs +3 -0
- package/package.json +77 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class GameTypeQuery extends QueryBase {
|
|
3
|
+
gameType;
|
|
4
|
+
gameTypeQ = 'gameTypeId';
|
|
5
|
+
/** @param gameType 1=Preseason, 2=Regular season, 3=Playoffs */
|
|
6
|
+
constructor(gameType) {
|
|
7
|
+
super();
|
|
8
|
+
this.gameType = gameType;
|
|
9
|
+
}
|
|
10
|
+
toQuery() {
|
|
11
|
+
return `${this.gameTypeQ}=${this.gameType}`;
|
|
12
|
+
}
|
|
13
|
+
validate() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Default sorting criteria for goalie stats reports. */
|
|
2
|
+
export function goalieStatsSorts(report) {
|
|
3
|
+
switch (report) {
|
|
4
|
+
case 'summary':
|
|
5
|
+
return [
|
|
6
|
+
{ property: 'wins', direction: 'DESC' },
|
|
7
|
+
{ property: 'gamesPlayed', direction: 'ASC' },
|
|
8
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
9
|
+
];
|
|
10
|
+
case 'advanced':
|
|
11
|
+
return [
|
|
12
|
+
{ property: 'qualityStart', direction: 'DESC' },
|
|
13
|
+
{ property: 'goalsAgainstAverage', direction: 'ASC' },
|
|
14
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
15
|
+
];
|
|
16
|
+
case 'bios':
|
|
17
|
+
return [
|
|
18
|
+
{ property: 'lastName', direction: 'ASC_CI' },
|
|
19
|
+
{ property: 'goalieFullName', direction: 'ASC_CI' },
|
|
20
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
21
|
+
];
|
|
22
|
+
case 'daysrest':
|
|
23
|
+
return [
|
|
24
|
+
{ property: 'wins', direction: 'DESC' },
|
|
25
|
+
{ property: 'savePct', direction: 'DESC' },
|
|
26
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
27
|
+
];
|
|
28
|
+
case 'penaltyShots':
|
|
29
|
+
return [
|
|
30
|
+
{ property: 'penaltyShotsSaves', direction: 'DESC' },
|
|
31
|
+
{ property: 'penaltyShotSavePct', direction: 'DESC' },
|
|
32
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
33
|
+
];
|
|
34
|
+
case 'savesByStrength':
|
|
35
|
+
return [
|
|
36
|
+
{ property: 'wins', direction: 'DESC' },
|
|
37
|
+
{ property: 'savePct', direction: 'DESC' },
|
|
38
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
39
|
+
];
|
|
40
|
+
case 'shootout':
|
|
41
|
+
return [
|
|
42
|
+
{ property: 'shootoutWins', direction: 'DESC' },
|
|
43
|
+
{ property: 'shootoutSavePct', direction: 'DESC' },
|
|
44
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
45
|
+
];
|
|
46
|
+
case 'startedVsRelieved':
|
|
47
|
+
return [
|
|
48
|
+
{ property: 'gamesStarted', direction: 'DESC' },
|
|
49
|
+
{ property: 'gamesStartedSavePct', direction: 'DESC' },
|
|
50
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
51
|
+
];
|
|
52
|
+
default:
|
|
53
|
+
return [{}];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export declare class HomeRoadQuery extends QueryBase {
|
|
3
|
+
readonly homeRoad: string;
|
|
4
|
+
private readonly homeRoadQ;
|
|
5
|
+
/** @param homeRoad H or R to indicate home or road games. */
|
|
6
|
+
constructor(homeRoad: string);
|
|
7
|
+
toQuery(): string;
|
|
8
|
+
validate(): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class HomeRoadQuery extends QueryBase {
|
|
3
|
+
homeRoad;
|
|
4
|
+
homeRoadQ = 'homeRoad';
|
|
5
|
+
/** @param homeRoad H or R to indicate home or road games. */
|
|
6
|
+
constructor(homeRoad) {
|
|
7
|
+
super();
|
|
8
|
+
this.homeRoad = homeRoad;
|
|
9
|
+
}
|
|
10
|
+
toQuery() {
|
|
11
|
+
return `${this.homeRoadQ}='${this.homeRoad}'`;
|
|
12
|
+
}
|
|
13
|
+
validate() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export { DecisionQuery } from '#src/api/query/filters/decision.mjs';
|
|
3
|
+
export { DraftQuery } from '#src/api/query/filters/draft.mjs';
|
|
4
|
+
export { ExperienceQuery } from '#src/api/query/filters/experience.mjs';
|
|
5
|
+
export { FranchiseQuery } from '#src/api/query/filters/franchise.mjs';
|
|
6
|
+
export { GameTypeQuery } from '#src/api/query/filters/game-type.mjs';
|
|
7
|
+
export { goalieStatsSorts } from '#src/api/query/filters/goalie-sorts.mjs';
|
|
8
|
+
export { HomeRoadQuery } from '#src/api/query/filters/home-road.mjs';
|
|
9
|
+
export { NationalityQuery } from '#src/api/query/filters/nationality.mjs';
|
|
10
|
+
export { OpponentQuery } from '#src/api/query/filters/opponent.mjs';
|
|
11
|
+
export { PositionQuery, PositionTypes, } from '#src/api/query/filters/position.mjs';
|
|
12
|
+
export { SeasonQuery } from '#src/api/query/filters/season.mjs';
|
|
13
|
+
export { ShootCatchesQuery } from '#src/api/query/filters/shoot-catch.mjs';
|
|
14
|
+
export { StatusQuery, type StatusQueryOptions, } from '#src/api/query/filters/status.mjs';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export { DecisionQuery } from '#src/api/query/filters/decision.mjs';
|
|
3
|
+
export { DraftQuery } from '#src/api/query/filters/draft.mjs';
|
|
4
|
+
export { ExperienceQuery } from '#src/api/query/filters/experience.mjs';
|
|
5
|
+
export { FranchiseQuery } from '#src/api/query/filters/franchise.mjs';
|
|
6
|
+
export { GameTypeQuery } from '#src/api/query/filters/game-type.mjs';
|
|
7
|
+
export { goalieStatsSorts } from '#src/api/query/filters/goalie-sorts.mjs';
|
|
8
|
+
export { HomeRoadQuery } from '#src/api/query/filters/home-road.mjs';
|
|
9
|
+
export { NationalityQuery } from '#src/api/query/filters/nationality.mjs';
|
|
10
|
+
export { OpponentQuery } from '#src/api/query/filters/opponent.mjs';
|
|
11
|
+
export { PositionQuery, PositionTypes, } from '#src/api/query/filters/position.mjs';
|
|
12
|
+
export { SeasonQuery } from '#src/api/query/filters/season.mjs';
|
|
13
|
+
export { ShootCatchesQuery } from '#src/api/query/filters/shoot-catch.mjs';
|
|
14
|
+
export { StatusQuery, } from '#src/api/query/filters/status.mjs';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Country/Nationality codes can be found via the `client.misc.countries()`
|
|
4
|
+
* endpoint, e.g. "CAN", "USA", "SWE", "FIN", "CZE", "RUS".
|
|
5
|
+
*/
|
|
6
|
+
export declare class NationalityQuery extends QueryBase {
|
|
7
|
+
readonly nationCode: string;
|
|
8
|
+
private readonly nationQ;
|
|
9
|
+
constructor(nationCode: string);
|
|
10
|
+
validate(): boolean;
|
|
11
|
+
toQuery(): string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Country/Nationality codes can be found via the `client.misc.countries()`
|
|
4
|
+
* endpoint, e.g. "CAN", "USA", "SWE", "FIN", "CZE", "RUS".
|
|
5
|
+
*/
|
|
6
|
+
export class NationalityQuery extends QueryBase {
|
|
7
|
+
nationCode;
|
|
8
|
+
nationQ = 'nationalityCode';
|
|
9
|
+
constructor(nationCode) {
|
|
10
|
+
super();
|
|
11
|
+
this.nationCode = nationCode;
|
|
12
|
+
}
|
|
13
|
+
validate() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
toQuery() {
|
|
17
|
+
return `${this.nationQ}='${this.nationCode}'`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
import type { Id } from '#src/utils.mjs';
|
|
3
|
+
export declare class OpponentQuery extends QueryBase {
|
|
4
|
+
readonly opponentId: Id;
|
|
5
|
+
private readonly opponentQ;
|
|
6
|
+
/** Opponent filter. Takes in the ID of the opponent franchise. */
|
|
7
|
+
constructor(opponentFranchiseId: Id);
|
|
8
|
+
toQuery(): string;
|
|
9
|
+
validate(): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class OpponentQuery extends QueryBase {
|
|
3
|
+
opponentId;
|
|
4
|
+
opponentQ = 'opponentFranchiseId';
|
|
5
|
+
/** Opponent filter. Takes in the ID of the opponent franchise. */
|
|
6
|
+
constructor(opponentFranchiseId) {
|
|
7
|
+
super();
|
|
8
|
+
this.opponentId = opponentFranchiseId;
|
|
9
|
+
}
|
|
10
|
+
toQuery() {
|
|
11
|
+
return `${this.opponentQ}=${this.opponentId}`;
|
|
12
|
+
}
|
|
13
|
+
validate() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export declare const PositionTypes: {
|
|
3
|
+
readonly ALL_FORWARDS: 'F';
|
|
4
|
+
readonly CENTER: 'C';
|
|
5
|
+
readonly LEFT_WING: 'L';
|
|
6
|
+
readonly RIGHT_WING: 'R';
|
|
7
|
+
readonly DEFENSE: 'D';
|
|
8
|
+
};
|
|
9
|
+
export type PositionTypes = (typeof PositionTypes)[keyof typeof PositionTypes];
|
|
10
|
+
export declare class PositionQuery extends QueryBase {
|
|
11
|
+
readonly position: PositionTypes;
|
|
12
|
+
private readonly positionQ;
|
|
13
|
+
constructor(position: PositionTypes);
|
|
14
|
+
toQuery(): string;
|
|
15
|
+
validate(): boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export const PositionTypes = {
|
|
3
|
+
ALL_FORWARDS: 'F',
|
|
4
|
+
CENTER: 'C',
|
|
5
|
+
LEFT_WING: 'L',
|
|
6
|
+
RIGHT_WING: 'R',
|
|
7
|
+
DEFENSE: 'D',
|
|
8
|
+
};
|
|
9
|
+
export class PositionQuery extends QueryBase {
|
|
10
|
+
position;
|
|
11
|
+
positionQ = 'positionCode';
|
|
12
|
+
constructor(position) {
|
|
13
|
+
super();
|
|
14
|
+
this.position = position;
|
|
15
|
+
}
|
|
16
|
+
toQuery() {
|
|
17
|
+
// All forwards require an OR clause
|
|
18
|
+
if (this.position === PositionTypes.ALL_FORWARDS) {
|
|
19
|
+
return (`(${this.positionQ}='${PositionTypes.LEFT_WING}' ` +
|
|
20
|
+
`or ${this.positionQ}='${PositionTypes.RIGHT_WING}' ` +
|
|
21
|
+
`or ${this.positionQ}='${PositionTypes.CENTER}')`);
|
|
22
|
+
}
|
|
23
|
+
return `${this.positionQ}='${this.position}'`;
|
|
24
|
+
}
|
|
25
|
+
validate() {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
import type { Id } from '#src/utils.mjs';
|
|
3
|
+
export declare class SeasonQuery extends QueryBase {
|
|
4
|
+
readonly seasonStart: Id;
|
|
5
|
+
readonly seasonEnd: Id;
|
|
6
|
+
private readonly seasonStartQ;
|
|
7
|
+
private readonly seasonStartQExp;
|
|
8
|
+
private readonly seasonEndQ;
|
|
9
|
+
private readonly seasonEndQExp;
|
|
10
|
+
/** Seasons in YYYYYYYY format, e.g. 20232024. */
|
|
11
|
+
constructor(seasonStart: Id, seasonEnd: Id);
|
|
12
|
+
toQuery(): string;
|
|
13
|
+
validate(): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class SeasonQuery extends QueryBase {
|
|
3
|
+
seasonStart;
|
|
4
|
+
seasonEnd;
|
|
5
|
+
seasonStartQ = 'seasonId';
|
|
6
|
+
seasonStartQExp = '>=';
|
|
7
|
+
seasonEndQ = 'seasonId';
|
|
8
|
+
seasonEndQExp = '<=';
|
|
9
|
+
/** Seasons in YYYYYYYY format, e.g. 20232024. */
|
|
10
|
+
constructor(seasonStart, seasonEnd) {
|
|
11
|
+
super();
|
|
12
|
+
this.seasonStart = seasonStart;
|
|
13
|
+
this.seasonEnd = seasonEnd;
|
|
14
|
+
}
|
|
15
|
+
toQuery() {
|
|
16
|
+
let query = `${this.seasonStartQ} ${this.seasonStartQExp} ${this.seasonStart}`;
|
|
17
|
+
query += ' and ';
|
|
18
|
+
query += `${this.seasonEndQ} ${this.seasonEndQExp} ${this.seasonEnd}`;
|
|
19
|
+
return query;
|
|
20
|
+
}
|
|
21
|
+
validate() {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export declare class ShootCatchesQuery extends QueryBase {
|
|
3
|
+
readonly shootCatch: string;
|
|
4
|
+
readonly shootCatchQ = "shootsCatches";
|
|
5
|
+
/** Shoot / catch filter. @param shootCatch L or R */
|
|
6
|
+
constructor(shootCatch: string);
|
|
7
|
+
toQuery(): string;
|
|
8
|
+
validate(): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class ShootCatchesQuery extends QueryBase {
|
|
3
|
+
shootCatch;
|
|
4
|
+
shootCatchQ = 'shootsCatches';
|
|
5
|
+
/** Shoot / catch filter. @param shootCatch L or R */
|
|
6
|
+
constructor(shootCatch) {
|
|
7
|
+
super();
|
|
8
|
+
this.shootCatch = shootCatch;
|
|
9
|
+
}
|
|
10
|
+
toQuery() {
|
|
11
|
+
return `${this.shootCatchQ}='${this.shootCatch}'`;
|
|
12
|
+
}
|
|
13
|
+
validate() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export interface StatusQueryOptions {
|
|
3
|
+
/** Only current active players. */
|
|
4
|
+
isActive?: boolean;
|
|
5
|
+
/** Only Hall of Fame players. Takes precedence over `isActive`. */
|
|
6
|
+
isHallOfFame?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class StatusQuery extends QueryBase {
|
|
9
|
+
readonly isActive: boolean;
|
|
10
|
+
readonly isHallOfFame: boolean;
|
|
11
|
+
private readonly activeQ;
|
|
12
|
+
private readonly hofQ;
|
|
13
|
+
/**
|
|
14
|
+
* Player status. Not supplying either option matches active and inactive
|
|
15
|
+
* players.
|
|
16
|
+
*/
|
|
17
|
+
constructor({ isActive, isHallOfFame, }?: StatusQueryOptions);
|
|
18
|
+
toQuery(): string;
|
|
19
|
+
validate(): boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { QueryBase } from '#src/api/query/filters/base.mjs';
|
|
2
|
+
export class StatusQuery extends QueryBase {
|
|
3
|
+
isActive;
|
|
4
|
+
isHallOfFame;
|
|
5
|
+
activeQ = 'active';
|
|
6
|
+
hofQ = 'isInHallOfFame';
|
|
7
|
+
/**
|
|
8
|
+
* Player status. Not supplying either option matches active and inactive
|
|
9
|
+
* players.
|
|
10
|
+
*/
|
|
11
|
+
constructor({ isActive = false, isHallOfFame = false, } = {}) {
|
|
12
|
+
super();
|
|
13
|
+
this.isActive = isActive;
|
|
14
|
+
this.isHallOfFame = isHallOfFame;
|
|
15
|
+
}
|
|
16
|
+
toQuery() {
|
|
17
|
+
if (this.isHallOfFame) {
|
|
18
|
+
return `${this.hofQ}=1`;
|
|
19
|
+
}
|
|
20
|
+
if (this.isActive) {
|
|
21
|
+
return `${this.activeQ}=1`;
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
validate() {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Id } from '#src/utils.mjs';
|
|
2
|
+
export declare const PositionTypes: {
|
|
3
|
+
readonly ALL_FORWARDS: 'F';
|
|
4
|
+
readonly CENTER: 'C';
|
|
5
|
+
readonly LEFT_WING: 'L';
|
|
6
|
+
readonly RIGHT_WING: 'R';
|
|
7
|
+
readonly DEFENSE: 'D';
|
|
8
|
+
};
|
|
9
|
+
export type PositionTypes = (typeof PositionTypes)[keyof typeof PositionTypes];
|
|
10
|
+
/** Goalie decision. W=win, L=loss, O=overtime loss. */
|
|
11
|
+
export type Decision = 'W' | 'L' | 'O';
|
|
12
|
+
export interface StatusQueryOptions {
|
|
13
|
+
/** Only current active players. */
|
|
14
|
+
isActive?: boolean;
|
|
15
|
+
/** Only Hall of Fame players. Takes precedence over `isActive`. */
|
|
16
|
+
isHallOfFame?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export type Filter = {
|
|
19
|
+
kind: 'decision';
|
|
20
|
+
decision: Decision;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'draft';
|
|
23
|
+
year: Id;
|
|
24
|
+
round?: Id;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'experience';
|
|
27
|
+
isRookie: boolean;
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'franchise';
|
|
30
|
+
franchiseId: Id;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'gameType';
|
|
33
|
+
gameType: Id;
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'homeRoad';
|
|
36
|
+
homeRoad: string;
|
|
37
|
+
} | {
|
|
38
|
+
kind: 'nationality';
|
|
39
|
+
nationCode: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'opponent';
|
|
42
|
+
opponentId: Id;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'position';
|
|
45
|
+
position: PositionTypes;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'season';
|
|
48
|
+
start: Id;
|
|
49
|
+
end: Id;
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'shootCatch';
|
|
52
|
+
shootCatch: string;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'status';
|
|
55
|
+
isActive: boolean;
|
|
56
|
+
isHallOfFame: boolean;
|
|
57
|
+
};
|
|
58
|
+
export declare const filter: {
|
|
59
|
+
/** @param decision W, L, O */
|
|
60
|
+
readonly decision: (decision: Decision) => Filter;
|
|
61
|
+
/**
|
|
62
|
+
* @param year Draft year
|
|
63
|
+
* @param round Optional draft round. The API seems to default this to "1".
|
|
64
|
+
*/
|
|
65
|
+
readonly draft: (year: Id, round?: Id) => Filter;
|
|
66
|
+
/** isRookie: true = rookies only, false = veterans only. */
|
|
67
|
+
readonly experience: (isRookie: boolean) => Filter;
|
|
68
|
+
readonly franchise: (franchiseId: Id) => Filter;
|
|
69
|
+
/** @param gameType 1=Preseason, 2=Regular season, 3=Playoffs */
|
|
70
|
+
readonly gameType: (gameType: Id) => Filter;
|
|
71
|
+
/** @param homeRoad H or R to indicate home or road games. */
|
|
72
|
+
readonly homeRoad: (homeRoad: string) => Filter;
|
|
73
|
+
/**
|
|
74
|
+
* Country/Nationality codes can be found via the `client.misc.countries()`
|
|
75
|
+
* endpoint, e.g. "CAN", "USA", "SWE", "FIN", "CZE", "RUS".
|
|
76
|
+
*/
|
|
77
|
+
readonly nationality: (nationCode: string) => Filter;
|
|
78
|
+
/** @param opponentId The ID of the opponent franchise. */
|
|
79
|
+
readonly opponent: (opponentId: Id) => Filter;
|
|
80
|
+
readonly position: (position: PositionTypes) => Filter;
|
|
81
|
+
/** Seasons in YYYYYYYY format, e.g. 20232024. */
|
|
82
|
+
readonly season: (start: Id, end: Id) => Filter;
|
|
83
|
+
/** @param shootCatch L or R */
|
|
84
|
+
readonly shootCatch: (shootCatch: string) => Filter;
|
|
85
|
+
/**
|
|
86
|
+
* Player status. Not supplying either option matches active and inactive
|
|
87
|
+
* players.
|
|
88
|
+
*/
|
|
89
|
+
readonly status: ({ isActive, isHallOfFame, }?: StatusQueryOptions) => Filter;
|
|
90
|
+
};
|
|
91
|
+
export declare function toQuery(filter: Filter): string;
|
|
92
|
+
/** Returns an error message if the filter is invalid, otherwise undefined. */
|
|
93
|
+
export declare function validateFilter(filter: Filter): string | undefined;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export const PositionTypes = {
|
|
2
|
+
ALL_FORWARDS: 'F',
|
|
3
|
+
CENTER: 'C',
|
|
4
|
+
LEFT_WING: 'L',
|
|
5
|
+
RIGHT_WING: 'R',
|
|
6
|
+
DEFENSE: 'D',
|
|
7
|
+
};
|
|
8
|
+
export const filter = {
|
|
9
|
+
/** @param decision W, L, O */
|
|
10
|
+
decision: (decision) => ({ kind: 'decision', decision }),
|
|
11
|
+
/**
|
|
12
|
+
* @param year Draft year
|
|
13
|
+
* @param round Optional draft round. The API seems to default this to "1".
|
|
14
|
+
*/
|
|
15
|
+
draft: (year, round) => ({ kind: 'draft', year, round }),
|
|
16
|
+
/** isRookie: true = rookies only, false = veterans only. */
|
|
17
|
+
experience: (isRookie) => ({
|
|
18
|
+
kind: 'experience',
|
|
19
|
+
isRookie,
|
|
20
|
+
}),
|
|
21
|
+
franchise: (franchiseId) => ({ kind: 'franchise', franchiseId }),
|
|
22
|
+
/** @param gameType 1=Preseason, 2=Regular season, 3=Playoffs */
|
|
23
|
+
gameType: (gameType) => ({ kind: 'gameType', gameType }),
|
|
24
|
+
/** @param homeRoad H or R to indicate home or road games. */
|
|
25
|
+
homeRoad: (homeRoad) => ({ kind: 'homeRoad', homeRoad }),
|
|
26
|
+
/**
|
|
27
|
+
* Country/Nationality codes can be found via the `client.misc.countries()`
|
|
28
|
+
* endpoint, e.g. "CAN", "USA", "SWE", "FIN", "CZE", "RUS".
|
|
29
|
+
*/
|
|
30
|
+
nationality: (nationCode) => ({
|
|
31
|
+
kind: 'nationality',
|
|
32
|
+
nationCode,
|
|
33
|
+
}),
|
|
34
|
+
/** @param opponentId The ID of the opponent franchise. */
|
|
35
|
+
opponent: (opponentId) => ({ kind: 'opponent', opponentId }),
|
|
36
|
+
position: (position) => ({
|
|
37
|
+
kind: 'position',
|
|
38
|
+
position,
|
|
39
|
+
}),
|
|
40
|
+
/** Seasons in YYYYYYYY format, e.g. 20232024. */
|
|
41
|
+
season: (start, end) => ({ kind: 'season', start, end }),
|
|
42
|
+
/** @param shootCatch L or R */
|
|
43
|
+
shootCatch: (shootCatch) => ({
|
|
44
|
+
kind: 'shootCatch',
|
|
45
|
+
shootCatch,
|
|
46
|
+
}),
|
|
47
|
+
/**
|
|
48
|
+
* Player status. Not supplying either option matches active and inactive
|
|
49
|
+
* players.
|
|
50
|
+
*/
|
|
51
|
+
status: ({ isActive = false, isHallOfFame = false, } = {}) => ({
|
|
52
|
+
kind: 'status',
|
|
53
|
+
isActive,
|
|
54
|
+
isHallOfFame,
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
export function toQuery(filter) {
|
|
58
|
+
switch (filter.kind) {
|
|
59
|
+
case 'decision': {
|
|
60
|
+
return `decision='${filter.decision}'`;
|
|
61
|
+
}
|
|
62
|
+
case 'draft': {
|
|
63
|
+
return filter.round
|
|
64
|
+
? `draftYear=${filter.year} and draftRound=${filter.round}`
|
|
65
|
+
: `draftYear=${filter.year}`;
|
|
66
|
+
}
|
|
67
|
+
case 'experience': {
|
|
68
|
+
return `isRookie='${filter.isRookie ? '1' : '0'}'`;
|
|
69
|
+
}
|
|
70
|
+
case 'franchise': {
|
|
71
|
+
return `franchiseId=${filter.franchiseId}`;
|
|
72
|
+
}
|
|
73
|
+
case 'gameType': {
|
|
74
|
+
return `gameTypeId=${filter.gameType}`;
|
|
75
|
+
}
|
|
76
|
+
case 'homeRoad': {
|
|
77
|
+
return `homeRoad='${filter.homeRoad}'`;
|
|
78
|
+
}
|
|
79
|
+
case 'nationality': {
|
|
80
|
+
return `nationalityCode='${filter.nationCode}'`;
|
|
81
|
+
}
|
|
82
|
+
case 'opponent': {
|
|
83
|
+
return `opponentFranchiseId=${filter.opponentId}`;
|
|
84
|
+
}
|
|
85
|
+
case 'position': {
|
|
86
|
+
// All forwards require an OR clause
|
|
87
|
+
if (filter.position === PositionTypes.ALL_FORWARDS) {
|
|
88
|
+
return (`(positionCode='${PositionTypes.LEFT_WING}' ` +
|
|
89
|
+
`or positionCode='${PositionTypes.RIGHT_WING}' ` +
|
|
90
|
+
`or positionCode='${PositionTypes.CENTER}')`);
|
|
91
|
+
}
|
|
92
|
+
return `positionCode='${filter.position}'`;
|
|
93
|
+
}
|
|
94
|
+
case 'season': {
|
|
95
|
+
return `seasonId >= ${filter.start} and seasonId <= ${filter.end}`;
|
|
96
|
+
}
|
|
97
|
+
case 'shootCatch': {
|
|
98
|
+
return `shootsCatches='${filter.shootCatch}'`;
|
|
99
|
+
}
|
|
100
|
+
case 'status': {
|
|
101
|
+
if (filter.isHallOfFame) {
|
|
102
|
+
return 'isInHallOfFame=1';
|
|
103
|
+
}
|
|
104
|
+
if (filter.isActive) {
|
|
105
|
+
return 'active=1';
|
|
106
|
+
}
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Returns an error message if the filter is invalid, otherwise undefined. */
|
|
112
|
+
export function validateFilter(filter) {
|
|
113
|
+
if (filter.kind === 'decision' &&
|
|
114
|
+
!['W', 'L', 'O'].includes(filter.decision)) {
|
|
115
|
+
return 'Decision value must be one of [W, L, O]';
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { buildQuery, isValidQuery, type QueryContext, } from '#src/api/query/builder.mjs';
|
|
2
|
+
export * from '#src/api/query/filters.mjs';
|
|
3
|
+
export { goalieStatsSorts } from '#src/api/query/sorting/goalie-sorts.mjs';
|
|
4
|
+
export { defaultSortForReport, SKATER_REPORT_TYPES, type SortExpr, } from '#src/api/query/sorting/sorting-options.mjs';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { buildQuery, isValidQuery, } from '#src/api/query/builder.mjs';
|
|
2
|
+
export * from '#src/api/query/filters.mjs';
|
|
3
|
+
export { goalieStatsSorts } from '#src/api/query/sorting/goalie-sorts.mjs';
|
|
4
|
+
export { defaultSortForReport, SKATER_REPORT_TYPES, } from '#src/api/query/sorting/sorting-options.mjs';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SortExpr } from '#src/api/query/sorting/sorting-options.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Default sorting criteria for goalie stats reports. Falls back to the
|
|
4
|
+
* goalie summary sort for unknown report types.
|
|
5
|
+
*/
|
|
6
|
+
export declare function goalieStatsSorts(report: string): SortExpr[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const goalieSummaryDefaultSorting = [
|
|
2
|
+
{ property: 'wins', direction: 'DESC' },
|
|
3
|
+
{ property: 'gamesPlayed', direction: 'ASC' },
|
|
4
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
5
|
+
];
|
|
6
|
+
/**
|
|
7
|
+
* Default sorting criteria for goalie stats reports. Falls back to the
|
|
8
|
+
* goalie summary sort for unknown report types.
|
|
9
|
+
*/
|
|
10
|
+
export function goalieStatsSorts(report) {
|
|
11
|
+
switch (report) {
|
|
12
|
+
case 'summary':
|
|
13
|
+
return goalieSummaryDefaultSorting;
|
|
14
|
+
case 'advanced':
|
|
15
|
+
return [
|
|
16
|
+
{ property: 'qualityStart', direction: 'DESC' },
|
|
17
|
+
{ property: 'goalsAgainstAverage', direction: 'ASC' },
|
|
18
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
19
|
+
];
|
|
20
|
+
case 'bios':
|
|
21
|
+
return [
|
|
22
|
+
{ property: 'lastName', direction: 'ASC_CI' },
|
|
23
|
+
{ property: 'goalieFullName', direction: 'ASC_CI' },
|
|
24
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
25
|
+
];
|
|
26
|
+
case 'daysrest':
|
|
27
|
+
return [
|
|
28
|
+
{ property: 'wins', direction: 'DESC' },
|
|
29
|
+
{ property: 'savePct', direction: 'DESC' },
|
|
30
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
31
|
+
];
|
|
32
|
+
case 'penaltyShots':
|
|
33
|
+
return [
|
|
34
|
+
{ property: 'penaltyShotsSaves', direction: 'DESC' },
|
|
35
|
+
{ property: 'penaltyShotSavePct', direction: 'DESC' },
|
|
36
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
37
|
+
];
|
|
38
|
+
case 'savesByStrength':
|
|
39
|
+
return [
|
|
40
|
+
{ property: 'wins', direction: 'DESC' },
|
|
41
|
+
{ property: 'savePct', direction: 'DESC' },
|
|
42
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
43
|
+
];
|
|
44
|
+
case 'shootout':
|
|
45
|
+
return [
|
|
46
|
+
{ property: 'shootoutWins', direction: 'DESC' },
|
|
47
|
+
{ property: 'shootoutSavePct', direction: 'DESC' },
|
|
48
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
49
|
+
];
|
|
50
|
+
case 'startedVsRelieved':
|
|
51
|
+
return [
|
|
52
|
+
{ property: 'gamesStarted', direction: 'DESC' },
|
|
53
|
+
{ property: 'gamesStartedSavePct', direction: 'DESC' },
|
|
54
|
+
{ property: 'playerId', direction: 'ASC' },
|
|
55
|
+
];
|
|
56
|
+
default:
|
|
57
|
+
return goalieSummaryDefaultSorting;
|
|
58
|
+
}
|
|
59
|
+
}
|