propline 0.22.1 → 0.24.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 +31 -1
- package/dist/index.cjs +77 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -5
- package/dist/index.d.ts +70 -5
- package/dist/index.js +77 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -653,19 +653,53 @@ interface GetDfsPayoutsOptions {
|
|
|
653
653
|
*/
|
|
654
654
|
legWinProb?: number;
|
|
655
655
|
}
|
|
656
|
+
/**
|
|
657
|
+
* Structured error body returned by gated/throttled endpoints
|
|
658
|
+
* (see https://prop-line.com/docs#errors). Branch on `error` — the
|
|
659
|
+
* codes are stable — and follow the URLs instead of parsing prose.
|
|
660
|
+
*/
|
|
661
|
+
interface PropLineErrorInfo {
|
|
662
|
+
/** Stable machine-readable code, e.g. "upgrade_required", "daily_limit_exceeded". */
|
|
663
|
+
error?: string;
|
|
664
|
+
/** Human-readable sentence. */
|
|
665
|
+
message?: string;
|
|
666
|
+
/** Cheapest tier that unlocks a gated feature (403s). */
|
|
667
|
+
required_tier?: string;
|
|
668
|
+
/** Where to unlock it — pre-filled one-click URL on daily-cap 429s. */
|
|
669
|
+
upgrade_url?: string;
|
|
670
|
+
docs_url?: string;
|
|
671
|
+
signup_url?: string;
|
|
672
|
+
backfill_url?: string;
|
|
673
|
+
/** Burst-limit backoff hint (429s). */
|
|
674
|
+
retry_after_seconds?: number;
|
|
675
|
+
/** Daily-cap 429s: recommended next plan incl. its own upgrade_url. */
|
|
676
|
+
recommended?: {
|
|
677
|
+
plan?: string;
|
|
678
|
+
upgrade_url?: string;
|
|
679
|
+
[key: string]: unknown;
|
|
680
|
+
};
|
|
681
|
+
[key: string]: unknown;
|
|
682
|
+
}
|
|
656
683
|
/** Base error for all PropLine API failures. */
|
|
657
684
|
declare class PropLineError extends Error {
|
|
658
685
|
readonly statusCode: number;
|
|
686
|
+
/** Human-readable detail message. */
|
|
659
687
|
readonly detail: string;
|
|
660
|
-
|
|
688
|
+
/** Structured error body, when the API returned one. */
|
|
689
|
+
readonly info?: PropLineErrorInfo;
|
|
690
|
+
constructor(statusCode: number, detail: string, info?: PropLineErrorInfo);
|
|
691
|
+
/** Stable machine-readable code (e.g. "upgrade_required"), if present. */
|
|
692
|
+
get errorCode(): string | undefined;
|
|
693
|
+
/** The URL that unlocks a gated feature or lifts a cap, if present. */
|
|
694
|
+
get upgradeUrl(): string | undefined;
|
|
661
695
|
}
|
|
662
696
|
/** Thrown when the API key is missing or invalid (HTTP 401). */
|
|
663
697
|
declare class AuthError extends PropLineError {
|
|
664
|
-
constructor(detail?: string);
|
|
698
|
+
constructor(detail?: string, info?: PropLineErrorInfo);
|
|
665
699
|
}
|
|
666
700
|
/** Thrown when the daily request limit is exceeded (HTTP 429). */
|
|
667
701
|
declare class RateLimitError extends PropLineError {
|
|
668
|
-
constructor(detail?: string);
|
|
702
|
+
constructor(detail?: string, info?: PropLineErrorInfo);
|
|
669
703
|
}
|
|
670
704
|
interface PropLineOptions {
|
|
671
705
|
/** API base URL. Default: `https://api.prop-line.com/v1`. */
|
|
@@ -886,6 +920,22 @@ interface VerifySignatureOptions {
|
|
|
886
920
|
/** Value of the `X-PropLine-Signature` header. */
|
|
887
921
|
signature: string;
|
|
888
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Live daily-quota state, parsed from the `X-Daily-*` headers the API
|
|
925
|
+
* returns on every authenticated response.
|
|
926
|
+
*/
|
|
927
|
+
interface QuotaStatus {
|
|
928
|
+
/** Your tier's daily request cap. */
|
|
929
|
+
limit: number;
|
|
930
|
+
/** Requests used today (including the request that produced this). */
|
|
931
|
+
used: number;
|
|
932
|
+
/** Requests left before the cap. */
|
|
933
|
+
remaining: number;
|
|
934
|
+
/** Unix seconds when the quota resets (00:00 UTC — a hard reset, not a rolling window). */
|
|
935
|
+
resetEpoch: number;
|
|
936
|
+
/** Quota reset time as a `Date`. */
|
|
937
|
+
resetAt: Date;
|
|
938
|
+
}
|
|
889
939
|
/**
|
|
890
940
|
* Client for the PropLine player props API.
|
|
891
941
|
*
|
|
@@ -901,9 +951,24 @@ declare class PropLine {
|
|
|
901
951
|
readonly apiKey: string;
|
|
902
952
|
readonly baseUrl: string;
|
|
903
953
|
readonly timeoutMs: number;
|
|
954
|
+
/**
|
|
955
|
+
* Daily-quota state from the most recent API response, or `null` before
|
|
956
|
+
* the first request. Updated on every call (including 429s):
|
|
957
|
+
*
|
|
958
|
+
* ```ts
|
|
959
|
+
* await client.getSports();
|
|
960
|
+
* console.log(client.lastQuota?.remaining); // 999
|
|
961
|
+
* ```
|
|
962
|
+
*/
|
|
963
|
+
lastQuota: QuotaStatus | null;
|
|
904
964
|
private readonly _fetch;
|
|
905
965
|
constructor(apiKey: string, options?: PropLineOptions);
|
|
906
966
|
private _buildUrl;
|
|
967
|
+
/**
|
|
968
|
+
* Record the X-Daily-* quota headers when present (absent on
|
|
969
|
+
* unauthenticated errors, e.g. an invalid key's 401).
|
|
970
|
+
*/
|
|
971
|
+
private _captureQuota;
|
|
907
972
|
private _request;
|
|
908
973
|
/** List all available sports. */
|
|
909
974
|
getSports(): Promise<Sport[]>;
|
|
@@ -1264,6 +1329,6 @@ declare const Bookmakers: {
|
|
|
1264
1329
|
readonly PRIZEPICKS: "prizepicks";
|
|
1265
1330
|
};
|
|
1266
1331
|
type BookmakerKey = (typeof Bookmakers)[keyof typeof Bookmakers];
|
|
1267
|
-
declare const VERSION = "0.
|
|
1332
|
+
declare const VERSION = "0.24.0";
|
|
1268
1333
|
|
|
1269
|
-
export { AuthError, type BestLine, type BestLineSide, type BestPrice, type Bookmaker, type BookmakerKey, Bookmakers, type CalcEventEvOptions, type ClosingBookmaker, type ClosingMarket, type ClosingOutcome, type ContextResponse, type CreateWebhookOptions, type DfsPayoutTier, type DfsPayoutsResponse, type DfsPlayPayout, type EvLine, type EvOutcome, type Event, type EventBestLineResponse, type EventEvCalcResponse, type EventEvResponse, type ExportOddsHistoryOptions, type ExportResolvedPropsOptions, type FuturesEvent, type FuturesMarket, type FuturesOutcome, type GetDfsPayoutsOptions, type GetEventBestLineOptions, type GetEventEvOptions, type GetMlbGrandSalamiOptions, type GetNhlDailyGoalsTotalOptions, type GetOddsClosingOptions, type GetOddsHistoryOptions, type GetOddsOptions, type GetPlayerHistoryOptions, type GetPlayerTrendsOptions, type GetResultsOptions, type GetScoresOptions, type GetStatsOptions, type HitRateSplit, type ListWebhookDeliveriesOptions, type Market, type MarketSummary, type MlbGrandSalamiBook, type MlbGrandSalamiResponse, type MovementBookmaker, type MovementMarket, type MovementOutcome, type MovementResponse, type NhlDailyGoalsTotalBook, type NhlDailyGoalsTotalResponse, type OddsClosingResponse, type OddsHistoryBookmaker, type OddsHistoryMarket, type OddsHistoryOutcome, type OddsHistoryResponse, type OddsResponse, type Outcome, type OutcomeSnapshot, type PeriodFilter, type PlayerHistoryEntry, type PlayerHistoryResponse, type PlayerMarketTrend, type PlayerStat, type PlayerTrends, PropLine, PropLineError, type PropLineOptions, RateLimitError, type ResolutionSummary, type ResolutionSummaryMarket, type ResolutionSummarySport, type ResolvedOutcome, type ResultsMarket, type ResultsResponse, type ScoreEvent, type Sport, type StatsResponse, type SteamMove, type TrendLastGame, type TrendStreak, type UpdateWebhookOptions, VERSION, type VerifySignatureOptions, type WeatherInfo, type Webhook, type WebhookDelivery, type WebhookEventType };
|
|
1334
|
+
export { AuthError, type BestLine, type BestLineSide, type BestPrice, type Bookmaker, type BookmakerKey, Bookmakers, type CalcEventEvOptions, type ClosingBookmaker, type ClosingMarket, type ClosingOutcome, type ContextResponse, type CreateWebhookOptions, type DfsPayoutTier, type DfsPayoutsResponse, type DfsPlayPayout, type EvLine, type EvOutcome, type Event, type EventBestLineResponse, type EventEvCalcResponse, type EventEvResponse, type ExportOddsHistoryOptions, type ExportResolvedPropsOptions, type FuturesEvent, type FuturesMarket, type FuturesOutcome, type GetDfsPayoutsOptions, type GetEventBestLineOptions, type GetEventEvOptions, type GetMlbGrandSalamiOptions, type GetNhlDailyGoalsTotalOptions, type GetOddsClosingOptions, type GetOddsHistoryOptions, type GetOddsOptions, type GetPlayerHistoryOptions, type GetPlayerTrendsOptions, type GetResultsOptions, type GetScoresOptions, type GetStatsOptions, type HitRateSplit, type ListWebhookDeliveriesOptions, type Market, type MarketSummary, type MlbGrandSalamiBook, type MlbGrandSalamiResponse, type MovementBookmaker, type MovementMarket, type MovementOutcome, type MovementResponse, type NhlDailyGoalsTotalBook, type NhlDailyGoalsTotalResponse, type OddsClosingResponse, type OddsHistoryBookmaker, type OddsHistoryMarket, type OddsHistoryOutcome, type OddsHistoryResponse, type OddsResponse, type Outcome, type OutcomeSnapshot, type PeriodFilter, type PlayerHistoryEntry, type PlayerHistoryResponse, type PlayerMarketTrend, type PlayerStat, type PlayerTrends, PropLine, PropLineError, type PropLineErrorInfo, type PropLineOptions, type QuotaStatus, RateLimitError, type ResolutionSummary, type ResolutionSummaryMarket, type ResolutionSummarySport, type ResolvedOutcome, type ResultsMarket, type ResultsResponse, type ScoreEvent, type Sport, type StatsResponse, type SteamMove, type TrendLastGame, type TrendStreak, type UpdateWebhookOptions, VERSION, type VerifySignatureOptions, type WeatherInfo, type Webhook, type WebhookDelivery, type WebhookEventType };
|
package/dist/index.d.ts
CHANGED
|
@@ -653,19 +653,53 @@ interface GetDfsPayoutsOptions {
|
|
|
653
653
|
*/
|
|
654
654
|
legWinProb?: number;
|
|
655
655
|
}
|
|
656
|
+
/**
|
|
657
|
+
* Structured error body returned by gated/throttled endpoints
|
|
658
|
+
* (see https://prop-line.com/docs#errors). Branch on `error` — the
|
|
659
|
+
* codes are stable — and follow the URLs instead of parsing prose.
|
|
660
|
+
*/
|
|
661
|
+
interface PropLineErrorInfo {
|
|
662
|
+
/** Stable machine-readable code, e.g. "upgrade_required", "daily_limit_exceeded". */
|
|
663
|
+
error?: string;
|
|
664
|
+
/** Human-readable sentence. */
|
|
665
|
+
message?: string;
|
|
666
|
+
/** Cheapest tier that unlocks a gated feature (403s). */
|
|
667
|
+
required_tier?: string;
|
|
668
|
+
/** Where to unlock it — pre-filled one-click URL on daily-cap 429s. */
|
|
669
|
+
upgrade_url?: string;
|
|
670
|
+
docs_url?: string;
|
|
671
|
+
signup_url?: string;
|
|
672
|
+
backfill_url?: string;
|
|
673
|
+
/** Burst-limit backoff hint (429s). */
|
|
674
|
+
retry_after_seconds?: number;
|
|
675
|
+
/** Daily-cap 429s: recommended next plan incl. its own upgrade_url. */
|
|
676
|
+
recommended?: {
|
|
677
|
+
plan?: string;
|
|
678
|
+
upgrade_url?: string;
|
|
679
|
+
[key: string]: unknown;
|
|
680
|
+
};
|
|
681
|
+
[key: string]: unknown;
|
|
682
|
+
}
|
|
656
683
|
/** Base error for all PropLine API failures. */
|
|
657
684
|
declare class PropLineError extends Error {
|
|
658
685
|
readonly statusCode: number;
|
|
686
|
+
/** Human-readable detail message. */
|
|
659
687
|
readonly detail: string;
|
|
660
|
-
|
|
688
|
+
/** Structured error body, when the API returned one. */
|
|
689
|
+
readonly info?: PropLineErrorInfo;
|
|
690
|
+
constructor(statusCode: number, detail: string, info?: PropLineErrorInfo);
|
|
691
|
+
/** Stable machine-readable code (e.g. "upgrade_required"), if present. */
|
|
692
|
+
get errorCode(): string | undefined;
|
|
693
|
+
/** The URL that unlocks a gated feature or lifts a cap, if present. */
|
|
694
|
+
get upgradeUrl(): string | undefined;
|
|
661
695
|
}
|
|
662
696
|
/** Thrown when the API key is missing or invalid (HTTP 401). */
|
|
663
697
|
declare class AuthError extends PropLineError {
|
|
664
|
-
constructor(detail?: string);
|
|
698
|
+
constructor(detail?: string, info?: PropLineErrorInfo);
|
|
665
699
|
}
|
|
666
700
|
/** Thrown when the daily request limit is exceeded (HTTP 429). */
|
|
667
701
|
declare class RateLimitError extends PropLineError {
|
|
668
|
-
constructor(detail?: string);
|
|
702
|
+
constructor(detail?: string, info?: PropLineErrorInfo);
|
|
669
703
|
}
|
|
670
704
|
interface PropLineOptions {
|
|
671
705
|
/** API base URL. Default: `https://api.prop-line.com/v1`. */
|
|
@@ -886,6 +920,22 @@ interface VerifySignatureOptions {
|
|
|
886
920
|
/** Value of the `X-PropLine-Signature` header. */
|
|
887
921
|
signature: string;
|
|
888
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Live daily-quota state, parsed from the `X-Daily-*` headers the API
|
|
925
|
+
* returns on every authenticated response.
|
|
926
|
+
*/
|
|
927
|
+
interface QuotaStatus {
|
|
928
|
+
/** Your tier's daily request cap. */
|
|
929
|
+
limit: number;
|
|
930
|
+
/** Requests used today (including the request that produced this). */
|
|
931
|
+
used: number;
|
|
932
|
+
/** Requests left before the cap. */
|
|
933
|
+
remaining: number;
|
|
934
|
+
/** Unix seconds when the quota resets (00:00 UTC — a hard reset, not a rolling window). */
|
|
935
|
+
resetEpoch: number;
|
|
936
|
+
/** Quota reset time as a `Date`. */
|
|
937
|
+
resetAt: Date;
|
|
938
|
+
}
|
|
889
939
|
/**
|
|
890
940
|
* Client for the PropLine player props API.
|
|
891
941
|
*
|
|
@@ -901,9 +951,24 @@ declare class PropLine {
|
|
|
901
951
|
readonly apiKey: string;
|
|
902
952
|
readonly baseUrl: string;
|
|
903
953
|
readonly timeoutMs: number;
|
|
954
|
+
/**
|
|
955
|
+
* Daily-quota state from the most recent API response, or `null` before
|
|
956
|
+
* the first request. Updated on every call (including 429s):
|
|
957
|
+
*
|
|
958
|
+
* ```ts
|
|
959
|
+
* await client.getSports();
|
|
960
|
+
* console.log(client.lastQuota?.remaining); // 999
|
|
961
|
+
* ```
|
|
962
|
+
*/
|
|
963
|
+
lastQuota: QuotaStatus | null;
|
|
904
964
|
private readonly _fetch;
|
|
905
965
|
constructor(apiKey: string, options?: PropLineOptions);
|
|
906
966
|
private _buildUrl;
|
|
967
|
+
/**
|
|
968
|
+
* Record the X-Daily-* quota headers when present (absent on
|
|
969
|
+
* unauthenticated errors, e.g. an invalid key's 401).
|
|
970
|
+
*/
|
|
971
|
+
private _captureQuota;
|
|
907
972
|
private _request;
|
|
908
973
|
/** List all available sports. */
|
|
909
974
|
getSports(): Promise<Sport[]>;
|
|
@@ -1264,6 +1329,6 @@ declare const Bookmakers: {
|
|
|
1264
1329
|
readonly PRIZEPICKS: "prizepicks";
|
|
1265
1330
|
};
|
|
1266
1331
|
type BookmakerKey = (typeof Bookmakers)[keyof typeof Bookmakers];
|
|
1267
|
-
declare const VERSION = "0.
|
|
1332
|
+
declare const VERSION = "0.24.0";
|
|
1268
1333
|
|
|
1269
|
-
export { AuthError, type BestLine, type BestLineSide, type BestPrice, type Bookmaker, type BookmakerKey, Bookmakers, type CalcEventEvOptions, type ClosingBookmaker, type ClosingMarket, type ClosingOutcome, type ContextResponse, type CreateWebhookOptions, type DfsPayoutTier, type DfsPayoutsResponse, type DfsPlayPayout, type EvLine, type EvOutcome, type Event, type EventBestLineResponse, type EventEvCalcResponse, type EventEvResponse, type ExportOddsHistoryOptions, type ExportResolvedPropsOptions, type FuturesEvent, type FuturesMarket, type FuturesOutcome, type GetDfsPayoutsOptions, type GetEventBestLineOptions, type GetEventEvOptions, type GetMlbGrandSalamiOptions, type GetNhlDailyGoalsTotalOptions, type GetOddsClosingOptions, type GetOddsHistoryOptions, type GetOddsOptions, type GetPlayerHistoryOptions, type GetPlayerTrendsOptions, type GetResultsOptions, type GetScoresOptions, type GetStatsOptions, type HitRateSplit, type ListWebhookDeliveriesOptions, type Market, type MarketSummary, type MlbGrandSalamiBook, type MlbGrandSalamiResponse, type MovementBookmaker, type MovementMarket, type MovementOutcome, type MovementResponse, type NhlDailyGoalsTotalBook, type NhlDailyGoalsTotalResponse, type OddsClosingResponse, type OddsHistoryBookmaker, type OddsHistoryMarket, type OddsHistoryOutcome, type OddsHistoryResponse, type OddsResponse, type Outcome, type OutcomeSnapshot, type PeriodFilter, type PlayerHistoryEntry, type PlayerHistoryResponse, type PlayerMarketTrend, type PlayerStat, type PlayerTrends, PropLine, PropLineError, type PropLineOptions, RateLimitError, type ResolutionSummary, type ResolutionSummaryMarket, type ResolutionSummarySport, type ResolvedOutcome, type ResultsMarket, type ResultsResponse, type ScoreEvent, type Sport, type StatsResponse, type SteamMove, type TrendLastGame, type TrendStreak, type UpdateWebhookOptions, VERSION, type VerifySignatureOptions, type WeatherInfo, type Webhook, type WebhookDelivery, type WebhookEventType };
|
|
1334
|
+
export { AuthError, type BestLine, type BestLineSide, type BestPrice, type Bookmaker, type BookmakerKey, Bookmakers, type CalcEventEvOptions, type ClosingBookmaker, type ClosingMarket, type ClosingOutcome, type ContextResponse, type CreateWebhookOptions, type DfsPayoutTier, type DfsPayoutsResponse, type DfsPlayPayout, type EvLine, type EvOutcome, type Event, type EventBestLineResponse, type EventEvCalcResponse, type EventEvResponse, type ExportOddsHistoryOptions, type ExportResolvedPropsOptions, type FuturesEvent, type FuturesMarket, type FuturesOutcome, type GetDfsPayoutsOptions, type GetEventBestLineOptions, type GetEventEvOptions, type GetMlbGrandSalamiOptions, type GetNhlDailyGoalsTotalOptions, type GetOddsClosingOptions, type GetOddsHistoryOptions, type GetOddsOptions, type GetPlayerHistoryOptions, type GetPlayerTrendsOptions, type GetResultsOptions, type GetScoresOptions, type GetStatsOptions, type HitRateSplit, type ListWebhookDeliveriesOptions, type Market, type MarketSummary, type MlbGrandSalamiBook, type MlbGrandSalamiResponse, type MovementBookmaker, type MovementMarket, type MovementOutcome, type MovementResponse, type NhlDailyGoalsTotalBook, type NhlDailyGoalsTotalResponse, type OddsClosingResponse, type OddsHistoryBookmaker, type OddsHistoryMarket, type OddsHistoryOutcome, type OddsHistoryResponse, type OddsResponse, type Outcome, type OutcomeSnapshot, type PeriodFilter, type PlayerHistoryEntry, type PlayerHistoryResponse, type PlayerMarketTrend, type PlayerStat, type PlayerTrends, PropLine, PropLineError, type PropLineErrorInfo, type PropLineOptions, type QuotaStatus, RateLimitError, type ResolutionSummary, type ResolutionSummaryMarket, type ResolutionSummarySport, type ResolvedOutcome, type ResultsMarket, type ResultsResponse, type ScoreEvent, type Sport, type StatsResponse, type SteamMove, type TrendLastGame, type TrendStreak, type UpdateWebhookOptions, VERSION, type VerifySignatureOptions, type WeatherInfo, type Webhook, type WebhookDelivery, type WebhookEventType };
|
package/dist/index.js
CHANGED
|
@@ -3,25 +3,37 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|
|
3
3
|
import { writeFile } from "fs/promises";
|
|
4
4
|
var PropLineError = class extends Error {
|
|
5
5
|
statusCode;
|
|
6
|
+
/** Human-readable detail message. */
|
|
6
7
|
detail;
|
|
7
|
-
|
|
8
|
+
/** Structured error body, when the API returned one. */
|
|
9
|
+
info;
|
|
10
|
+
constructor(statusCode, detail, info) {
|
|
8
11
|
super(`[${statusCode}] ${detail}`);
|
|
9
12
|
this.name = "PropLineError";
|
|
10
13
|
this.statusCode = statusCode;
|
|
11
14
|
this.detail = detail;
|
|
15
|
+
this.info = info;
|
|
12
16
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
17
|
}
|
|
18
|
+
/** Stable machine-readable code (e.g. "upgrade_required"), if present. */
|
|
19
|
+
get errorCode() {
|
|
20
|
+
return this.info?.error;
|
|
21
|
+
}
|
|
22
|
+
/** The URL that unlocks a gated feature or lifts a cap, if present. */
|
|
23
|
+
get upgradeUrl() {
|
|
24
|
+
return this.info?.upgrade_url ?? this.info?.recommended?.upgrade_url;
|
|
25
|
+
}
|
|
14
26
|
};
|
|
15
27
|
var AuthError = class extends PropLineError {
|
|
16
|
-
constructor(detail = "Invalid API key") {
|
|
17
|
-
super(401, detail);
|
|
28
|
+
constructor(detail = "Invalid API key", info) {
|
|
29
|
+
super(401, detail, info);
|
|
18
30
|
this.name = "AuthError";
|
|
19
31
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
20
32
|
}
|
|
21
33
|
};
|
|
22
34
|
var RateLimitError = class extends PropLineError {
|
|
23
|
-
constructor(detail = "Rate limit exceeded") {
|
|
24
|
-
super(429, detail);
|
|
35
|
+
constructor(detail = "Rate limit exceeded", info) {
|
|
36
|
+
super(429, detail, info);
|
|
25
37
|
this.name = "RateLimitError";
|
|
26
38
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
27
39
|
}
|
|
@@ -40,6 +52,16 @@ var PropLine = class {
|
|
|
40
52
|
apiKey;
|
|
41
53
|
baseUrl;
|
|
42
54
|
timeoutMs;
|
|
55
|
+
/**
|
|
56
|
+
* Daily-quota state from the most recent API response, or `null` before
|
|
57
|
+
* the first request. Updated on every call (including 429s):
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* await client.getSports();
|
|
61
|
+
* console.log(client.lastQuota?.remaining); // 999
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
lastQuota = null;
|
|
43
65
|
_fetch;
|
|
44
66
|
constructor(apiKey, options = {}) {
|
|
45
67
|
if (!apiKey) {
|
|
@@ -69,6 +91,25 @@ var PropLine = class {
|
|
|
69
91
|
}
|
|
70
92
|
return url.toString();
|
|
71
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Record the X-Daily-* quota headers when present (absent on
|
|
96
|
+
* unauthenticated errors, e.g. an invalid key's 401).
|
|
97
|
+
*/
|
|
98
|
+
_captureQuota(resp) {
|
|
99
|
+
const limit = Number(resp.headers.get("X-Daily-Limit"));
|
|
100
|
+
const used = Number(resp.headers.get("X-Daily-Used"));
|
|
101
|
+
const remaining = Number(resp.headers.get("X-Daily-Remaining"));
|
|
102
|
+
const resetEpoch = Number(resp.headers.get("X-Daily-Reset"));
|
|
103
|
+
if (resp.headers.has("X-Daily-Limit") && Number.isFinite(limit) && Number.isFinite(used) && Number.isFinite(remaining) && Number.isFinite(resetEpoch)) {
|
|
104
|
+
this.lastQuota = {
|
|
105
|
+
limit,
|
|
106
|
+
used,
|
|
107
|
+
remaining,
|
|
108
|
+
resetEpoch,
|
|
109
|
+
resetAt: new Date(resetEpoch * 1e3)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
72
113
|
async _request(method, path, init = {}) {
|
|
73
114
|
const url = this._buildUrl(path, init.params);
|
|
74
115
|
const controller = new AbortController();
|
|
@@ -87,14 +128,18 @@ var PropLine = class {
|
|
|
87
128
|
} finally {
|
|
88
129
|
clearTimeout(timer);
|
|
89
130
|
}
|
|
131
|
+
this._captureQuota(resp);
|
|
90
132
|
if (resp.status === 401) {
|
|
91
|
-
|
|
133
|
+
const d = await readDetail(resp, "Invalid API key");
|
|
134
|
+
throw new AuthError(d.message, d.info);
|
|
92
135
|
}
|
|
93
136
|
if (resp.status === 429) {
|
|
94
|
-
|
|
137
|
+
const d = await readDetail(resp, "Rate limit exceeded");
|
|
138
|
+
throw new RateLimitError(d.message, d.info);
|
|
95
139
|
}
|
|
96
140
|
if (resp.status >= 400) {
|
|
97
|
-
|
|
141
|
+
const d = await readDetail(resp, resp.statusText);
|
|
142
|
+
throw new PropLineError(resp.status, d.message, d.info);
|
|
98
143
|
}
|
|
99
144
|
if (resp.status === 204) {
|
|
100
145
|
return void 0;
|
|
@@ -541,14 +586,17 @@ var PropLine = class {
|
|
|
541
586
|
} finally {
|
|
542
587
|
clearTimeout(timer);
|
|
543
588
|
}
|
|
589
|
+
this._captureQuota(resp);
|
|
544
590
|
if (resp.status === 401) {
|
|
545
591
|
throw new AuthError();
|
|
546
592
|
}
|
|
547
593
|
if (resp.status === 403) {
|
|
548
|
-
|
|
594
|
+
const d = await readDetail(resp, "Pro tier required");
|
|
595
|
+
throw new PropLineError(403, d.message, d.info);
|
|
549
596
|
}
|
|
550
597
|
if (resp.status >= 400) {
|
|
551
|
-
|
|
598
|
+
const d = await readDetail(resp, resp.statusText);
|
|
599
|
+
throw new PropLineError(resp.status, d.message, d.info);
|
|
552
600
|
}
|
|
553
601
|
const buf = new Uint8Array(await resp.arrayBuffer());
|
|
554
602
|
if (options.outPath) {
|
|
@@ -576,17 +624,20 @@ var PropLine = class {
|
|
|
576
624
|
} finally {
|
|
577
625
|
clearTimeout(timer);
|
|
578
626
|
}
|
|
627
|
+
this._captureQuota(resp);
|
|
579
628
|
if (resp.status === 401) {
|
|
580
629
|
throw new AuthError();
|
|
581
630
|
}
|
|
582
631
|
if (resp.status === 403) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
632
|
+
const d = await readDetail(
|
|
633
|
+
resp,
|
|
634
|
+
"Historical Backfill pass or Enterprise required"
|
|
586
635
|
);
|
|
636
|
+
throw new PropLineError(403, d.message, d.info);
|
|
587
637
|
}
|
|
588
638
|
if (resp.status >= 400) {
|
|
589
|
-
|
|
639
|
+
const d = await readDetail(resp, resp.statusText);
|
|
640
|
+
throw new PropLineError(resp.status, d.message, d.info);
|
|
590
641
|
}
|
|
591
642
|
const buf = new Uint8Array(await resp.arrayBuffer());
|
|
592
643
|
if (options.outPath) {
|
|
@@ -696,15 +747,22 @@ function webhookBody(options) {
|
|
|
696
747
|
async function readDetail(resp, fallback) {
|
|
697
748
|
try {
|
|
698
749
|
const text = await resp.text();
|
|
699
|
-
if (!text) return fallback;
|
|
750
|
+
if (!text) return { message: fallback };
|
|
700
751
|
try {
|
|
701
752
|
const json = JSON.parse(text);
|
|
702
|
-
if (typeof json.detail === "string") return json.detail;
|
|
753
|
+
if (typeof json.detail === "string") return { message: json.detail };
|
|
754
|
+
if (json.detail && typeof json.detail === "object") {
|
|
755
|
+
const info = json.detail;
|
|
756
|
+
return {
|
|
757
|
+
message: typeof info.message === "string" ? info.message : text,
|
|
758
|
+
info
|
|
759
|
+
};
|
|
760
|
+
}
|
|
703
761
|
} catch {
|
|
704
762
|
}
|
|
705
|
-
return text || fallback;
|
|
763
|
+
return { message: text || fallback };
|
|
706
764
|
} catch {
|
|
707
|
-
return fallback;
|
|
765
|
+
return { message: fallback };
|
|
708
766
|
}
|
|
709
767
|
}
|
|
710
768
|
|
|
@@ -720,7 +778,7 @@ var Bookmakers = {
|
|
|
720
778
|
POLYMARKET: "polymarket",
|
|
721
779
|
PRIZEPICKS: "prizepicks"
|
|
722
780
|
};
|
|
723
|
-
var VERSION = "0.
|
|
781
|
+
var VERSION = "0.24.0";
|
|
724
782
|
export {
|
|
725
783
|
AuthError,
|
|
726
784
|
Bookmakers,
|