@mrdoge/node 0.1.1 → 0.1.2
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/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WelcomeParams, MethodName, MethodParams, MethodResult, SubscriptionEventParams, SubscriptionClosedParams, SubscriptionMethodName, PushEventsOf, SubscriptionClosedReason, ErrorCode } from '@mrdoge/protocol';
|
|
1
|
+
import { WelcomeParams, MethodName, MethodParams, MethodResult, SubscriptionEventParams, SubscriptionClosedParams, SubscriptionMethodName, PushEventsOf, SubscriptionClosedReason, Match, AiPick, ErrorCode } from '@mrdoge/protocol';
|
|
2
2
|
export { AiPick, BetItem, Clock, Competition, ErrorCode, Market, Match, MatchDetail, MatchDetailSelect, MatchSelect, MatchState, MatchStats, MatchStatus, Pagination, Period, PickConfidence, PickLeg, PickResult, Recommendation, Region, Selector, Sport, StatPlayer, SubscriptionClosedReason, Team, TeamDetail, TeamForm, TeamFormMatch, TeamFormResult, WelcomeParams } from '@mrdoge/protocol';
|
|
3
3
|
import { MrDogeHttpClient } from '@mrdoge/http';
|
|
4
4
|
|
|
@@ -19,6 +19,15 @@ interface BackoffConfig {
|
|
|
19
19
|
interface CallOptions {
|
|
20
20
|
signal?: AbortSignal;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Options for `listAll` cursor-walk helpers. `signal` aborts the in-flight
|
|
24
|
+
* page; the helper rethrows the `AbortError`. `onPage` fires after every
|
|
25
|
+
* page lands — pass it to stream partial results into your store while the
|
|
26
|
+
* walk continues.
|
|
27
|
+
*/
|
|
28
|
+
interface ListAllOptions<T> extends CallOptions {
|
|
29
|
+
onPage?: (page: T[], accumulated: T[]) => void;
|
|
30
|
+
}
|
|
22
31
|
interface ConnectionConfig {
|
|
23
32
|
baseUrl: string;
|
|
24
33
|
apiKey: string;
|
|
@@ -229,6 +238,17 @@ declare class Matches {
|
|
|
229
238
|
private readonly http;
|
|
230
239
|
constructor(conn: Connection, defaults: Defaults, http: MrDogeHttpClient);
|
|
231
240
|
list(params?: MethodParams<"matches.list">, options?: CallOptions): Promise<MethodResult<"matches.list">>;
|
|
241
|
+
/**
|
|
242
|
+
* Walk every page of `matches.list` and return one combined array. The
|
|
243
|
+
* helper drives the cursor for you — pass everything except `cursor`,
|
|
244
|
+
* including `limit` for page size. AbortSignal aborts the whole walk.
|
|
245
|
+
* `onPage` fires after each page for progressive rendering.
|
|
246
|
+
*
|
|
247
|
+
* Server-side keyset cursor pagination keeps the walk drift-safe (no
|
|
248
|
+
* duplicate or missed IDs across page boundaries even when the underlying
|
|
249
|
+
* set shifts mid-walk).
|
|
250
|
+
*/
|
|
251
|
+
listAll(params?: Omit<MethodParams<"matches.list">, "cursor">, options?: ListAllOptions<Match>): Promise<Match[]>;
|
|
232
252
|
get(params: MethodParams<"matches.get">, options?: CallOptions): Promise<MethodResult<"matches.get">>;
|
|
233
253
|
trending(params?: MethodParams<"matches.trending">, options?: CallOptions): Promise<MethodResult<"matches.trending">>;
|
|
234
254
|
search(params: MethodParams<"matches.search">, options?: CallOptions): Promise<MethodResult<"matches.search">>;
|
|
@@ -243,6 +263,12 @@ declare class Picks {
|
|
|
243
263
|
locale?: string;
|
|
244
264
|
});
|
|
245
265
|
list(params?: MethodParams<"ai.picks.list">, options?: CallOptions): Promise<MethodResult<"ai.picks.list">>;
|
|
266
|
+
/**
|
|
267
|
+
* Walk every page of `ai.picks.list` and return one combined array. Same
|
|
268
|
+
* shape as `matches.listAll`. Server-side keyset pagination keeps the
|
|
269
|
+
* walk drift-safe.
|
|
270
|
+
*/
|
|
271
|
+
listAll(params?: Omit<MethodParams<"ai.picks.list">, "cursor">, options?: ListAllOptions<AiPick>): Promise<AiPick[]>;
|
|
246
272
|
}
|
|
247
273
|
declare class Recommendations {
|
|
248
274
|
private readonly conn;
|
|
@@ -419,4 +445,4 @@ declare class AbortError extends MrDogeError {
|
|
|
419
445
|
constructor(message?: string);
|
|
420
446
|
}
|
|
421
447
|
|
|
422
|
-
export { AbortError, type CallOptions, ConnectionError, ConnectionLimitError, DEFAULT_BASE_URL, DisconnectedError, ForbiddenError, InternalError, MrDoge, MrDogeError, type MrDogeOptions, NotFoundError, ProtocolError, RateLimitError, Subscription, SubscriptionLimitError, TimeoutError, UnauthorizedError, UnavailableError, ValidationError };
|
|
448
|
+
export { AbortError, type CallOptions, ConnectionError, ConnectionLimitError, DEFAULT_BASE_URL, DisconnectedError, ForbiddenError, InternalError, type ListAllOptions, MrDoge, MrDogeError, type MrDogeOptions, NotFoundError, ProtocolError, RateLimitError, Subscription, SubscriptionLimitError, TimeoutError, UnauthorizedError, UnavailableError, ValidationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WelcomeParams, MethodName, MethodParams, MethodResult, SubscriptionEventParams, SubscriptionClosedParams, SubscriptionMethodName, PushEventsOf, SubscriptionClosedReason, ErrorCode } from '@mrdoge/protocol';
|
|
1
|
+
import { WelcomeParams, MethodName, MethodParams, MethodResult, SubscriptionEventParams, SubscriptionClosedParams, SubscriptionMethodName, PushEventsOf, SubscriptionClosedReason, Match, AiPick, ErrorCode } from '@mrdoge/protocol';
|
|
2
2
|
export { AiPick, BetItem, Clock, Competition, ErrorCode, Market, Match, MatchDetail, MatchDetailSelect, MatchSelect, MatchState, MatchStats, MatchStatus, Pagination, Period, PickConfidence, PickLeg, PickResult, Recommendation, Region, Selector, Sport, StatPlayer, SubscriptionClosedReason, Team, TeamDetail, TeamForm, TeamFormMatch, TeamFormResult, WelcomeParams } from '@mrdoge/protocol';
|
|
3
3
|
import { MrDogeHttpClient } from '@mrdoge/http';
|
|
4
4
|
|
|
@@ -19,6 +19,15 @@ interface BackoffConfig {
|
|
|
19
19
|
interface CallOptions {
|
|
20
20
|
signal?: AbortSignal;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Options for `listAll` cursor-walk helpers. `signal` aborts the in-flight
|
|
24
|
+
* page; the helper rethrows the `AbortError`. `onPage` fires after every
|
|
25
|
+
* page lands — pass it to stream partial results into your store while the
|
|
26
|
+
* walk continues.
|
|
27
|
+
*/
|
|
28
|
+
interface ListAllOptions<T> extends CallOptions {
|
|
29
|
+
onPage?: (page: T[], accumulated: T[]) => void;
|
|
30
|
+
}
|
|
22
31
|
interface ConnectionConfig {
|
|
23
32
|
baseUrl: string;
|
|
24
33
|
apiKey: string;
|
|
@@ -229,6 +238,17 @@ declare class Matches {
|
|
|
229
238
|
private readonly http;
|
|
230
239
|
constructor(conn: Connection, defaults: Defaults, http: MrDogeHttpClient);
|
|
231
240
|
list(params?: MethodParams<"matches.list">, options?: CallOptions): Promise<MethodResult<"matches.list">>;
|
|
241
|
+
/**
|
|
242
|
+
* Walk every page of `matches.list` and return one combined array. The
|
|
243
|
+
* helper drives the cursor for you — pass everything except `cursor`,
|
|
244
|
+
* including `limit` for page size. AbortSignal aborts the whole walk.
|
|
245
|
+
* `onPage` fires after each page for progressive rendering.
|
|
246
|
+
*
|
|
247
|
+
* Server-side keyset cursor pagination keeps the walk drift-safe (no
|
|
248
|
+
* duplicate or missed IDs across page boundaries even when the underlying
|
|
249
|
+
* set shifts mid-walk).
|
|
250
|
+
*/
|
|
251
|
+
listAll(params?: Omit<MethodParams<"matches.list">, "cursor">, options?: ListAllOptions<Match>): Promise<Match[]>;
|
|
232
252
|
get(params: MethodParams<"matches.get">, options?: CallOptions): Promise<MethodResult<"matches.get">>;
|
|
233
253
|
trending(params?: MethodParams<"matches.trending">, options?: CallOptions): Promise<MethodResult<"matches.trending">>;
|
|
234
254
|
search(params: MethodParams<"matches.search">, options?: CallOptions): Promise<MethodResult<"matches.search">>;
|
|
@@ -243,6 +263,12 @@ declare class Picks {
|
|
|
243
263
|
locale?: string;
|
|
244
264
|
});
|
|
245
265
|
list(params?: MethodParams<"ai.picks.list">, options?: CallOptions): Promise<MethodResult<"ai.picks.list">>;
|
|
266
|
+
/**
|
|
267
|
+
* Walk every page of `ai.picks.list` and return one combined array. Same
|
|
268
|
+
* shape as `matches.listAll`. Server-side keyset pagination keeps the
|
|
269
|
+
* walk drift-safe.
|
|
270
|
+
*/
|
|
271
|
+
listAll(params?: Omit<MethodParams<"ai.picks.list">, "cursor">, options?: ListAllOptions<AiPick>): Promise<AiPick[]>;
|
|
246
272
|
}
|
|
247
273
|
declare class Recommendations {
|
|
248
274
|
private readonly conn;
|
|
@@ -419,4 +445,4 @@ declare class AbortError extends MrDogeError {
|
|
|
419
445
|
constructor(message?: string);
|
|
420
446
|
}
|
|
421
447
|
|
|
422
|
-
export { AbortError, type CallOptions, ConnectionError, ConnectionLimitError, DEFAULT_BASE_URL, DisconnectedError, ForbiddenError, InternalError, MrDoge, MrDogeError, type MrDogeOptions, NotFoundError, ProtocolError, RateLimitError, Subscription, SubscriptionLimitError, TimeoutError, UnauthorizedError, UnavailableError, ValidationError };
|
|
448
|
+
export { AbortError, type CallOptions, ConnectionError, ConnectionLimitError, DEFAULT_BASE_URL, DisconnectedError, ForbiddenError, InternalError, type ListAllOptions, MrDoge, MrDogeError, type MrDogeOptions, NotFoundError, ProtocolError, RateLimitError, Subscription, SubscriptionLimitError, TimeoutError, UnauthorizedError, UnavailableError, ValidationError };
|
package/dist/index.js
CHANGED
|
@@ -756,6 +756,29 @@ var Matches = class {
|
|
|
756
756
|
options
|
|
757
757
|
);
|
|
758
758
|
}
|
|
759
|
+
/**
|
|
760
|
+
* Walk every page of `matches.list` and return one combined array. The
|
|
761
|
+
* helper drives the cursor for you — pass everything except `cursor`,
|
|
762
|
+
* including `limit` for page size. AbortSignal aborts the whole walk.
|
|
763
|
+
* `onPage` fires after each page for progressive rendering.
|
|
764
|
+
*
|
|
765
|
+
* Server-side keyset cursor pagination keeps the walk drift-safe (no
|
|
766
|
+
* duplicate or missed IDs across page boundaries even when the underlying
|
|
767
|
+
* set shifts mid-walk).
|
|
768
|
+
*/
|
|
769
|
+
async listAll(params = {}, options) {
|
|
770
|
+
const { onPage, ...callOptions } = options ?? {};
|
|
771
|
+
const result = [];
|
|
772
|
+
let cursor;
|
|
773
|
+
do {
|
|
774
|
+
const page = await this.list({ ...params, cursor }, callOptions);
|
|
775
|
+
const pageData = page.data;
|
|
776
|
+
result.push(...pageData);
|
|
777
|
+
onPage?.(pageData, result);
|
|
778
|
+
cursor = page.pagination.nextCursor ?? void 0;
|
|
779
|
+
} while (cursor);
|
|
780
|
+
return result;
|
|
781
|
+
}
|
|
759
782
|
get(params, options) {
|
|
760
783
|
return this.conn.call(
|
|
761
784
|
"matches.get",
|
|
@@ -872,6 +895,24 @@ var Picks = class {
|
|
|
872
895
|
options
|
|
873
896
|
);
|
|
874
897
|
}
|
|
898
|
+
/**
|
|
899
|
+
* Walk every page of `ai.picks.list` and return one combined array. Same
|
|
900
|
+
* shape as `matches.listAll`. Server-side keyset pagination keeps the
|
|
901
|
+
* walk drift-safe.
|
|
902
|
+
*/
|
|
903
|
+
async listAll(params = {}, options) {
|
|
904
|
+
const { onPage, ...callOptions } = options ?? {};
|
|
905
|
+
const result = [];
|
|
906
|
+
let cursor;
|
|
907
|
+
do {
|
|
908
|
+
const page = await this.list({ ...params, cursor }, callOptions);
|
|
909
|
+
const pageData = page.data;
|
|
910
|
+
result.push(...pageData);
|
|
911
|
+
onPage?.(pageData, result);
|
|
912
|
+
cursor = page.pagination.nextCursor ?? void 0;
|
|
913
|
+
} while (cursor);
|
|
914
|
+
return result;
|
|
915
|
+
}
|
|
875
916
|
};
|
|
876
917
|
var Recommendations = class {
|
|
877
918
|
constructor(conn, defaults) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/connection.ts","../src/errors.ts","../src/internal/emitter.ts","../src/internal/backoff.ts","../src/resources/regions.ts","../src/resources/competitions.ts","../src/resources/teams.ts","../src/subscription.ts","../src/resources/matches.ts","../src/resources/ai.ts","../src/resources/tokens.ts"],"sourcesContent":["/**\n * @mrdoge/node — official Node / TypeScript SDK for Mr. Doge realtime sports data.\n *\n * ```ts\n * import { MrDoge } from \"@mrdoge/node\"\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n */\n\nexport { MrDoge, type MrDogeOptions, DEFAULT_BASE_URL } from \"./client\"\nexport { Subscription } from \"./subscription\"\nexport type { CallOptions } from \"./connection\"\nexport {\n MrDogeError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ValidationError,\n RateLimitError,\n SubscriptionLimitError,\n ConnectionLimitError,\n UnavailableError,\n InternalError,\n ProtocolError,\n ConnectionError,\n DisconnectedError,\n TimeoutError,\n AbortError,\n} from \"./errors\"\n\n// Re-export the most useful protocol types so consumers don't have to import\n// from `@mrdoge/protocol` directly for typical usage.\nexport type {\n Region,\n Competition,\n Team,\n TeamDetail,\n TeamForm,\n TeamFormMatch,\n TeamFormResult,\n Sport,\n Match,\n MatchDetail,\n MatchStats,\n MatchStatus,\n MatchState,\n MatchSelect,\n MatchDetailSelect,\n Selector,\n Clock,\n Period,\n StatPlayer,\n Market,\n BetItem,\n Pagination,\n AiPick,\n PickConfidence,\n PickResult,\n PickLeg,\n Recommendation,\n WelcomeParams,\n SubscriptionClosedReason,\n ErrorCode,\n} from \"@mrdoge/protocol\"\n","import { createHttpClient, type MrDogeHttpClient } from \"@mrdoge/http\"\nimport { Connection, DEFAULT_CONFIG, type ConnectionConfig, type ConnectionEvents } from \"./connection\"\nimport { type BackoffConfig } from \"./internal/backoff\"\nimport { Regions } from \"./resources/regions\"\nimport { Competitions } from \"./resources/competitions\"\nimport { Teams } from \"./resources/teams\"\nimport { Matches } from \"./resources/matches\"\nimport { Ai } from \"./resources/ai\"\nimport { Tokens } from \"./resources/tokens\"\n\nexport const DEFAULT_BASE_URL = \"wss://api.mrdoge.co/sdk/v1\"\n\n/**\n * Derive the HTTP gateway URL from the configured WS URL by swapping the\n * scheme. One `baseUrl` config drives both transports.\n */\nfunction wsToHttp(url: string): string {\n if (url.startsWith(\"wss://\")) return \"https://\" + url.slice(\"wss://\".length)\n if (url.startsWith(\"ws://\")) return \"http://\" + url.slice(\"ws://\".length)\n return url\n}\n\nexport interface MrDogeOptions {\n apiKey: string\n\n /** Override the server URL (e.g. for local dev). Defaults to production. */\n baseUrl?: string\n\n /** Default locale applied to every call; overridable per-call. */\n locale?: string\n\n /** Default timezone applied to every call; overridable per-call. */\n timezone?: string\n\n /** Request-level timeout in milliseconds. Default 10s. */\n requestTimeoutMs?: number\n\n /** Max reconnect attempts on transient disconnects. Default Infinity. */\n maxReconnectAttempts?: number\n\n /** Exponential backoff config for reconnects. */\n reconnectBackoff?: Partial<BackoffConfig>\n\n /**\n * Whether to negotiate `permessage-deflate` compression at the WS handshake.\n * Default `true`. Disable for CPU-constrained environments.\n */\n compression?: boolean\n}\n\n/**\n * Mr. Doge SDK entrypoint.\n *\n * ```ts\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n *\n * The constructor does not open a connection. The WebSocket is opened lazily\n * on the first method call and reused for the lifetime of the client.\n */\nexport class MrDoge {\n readonly regions: Regions\n readonly competitions: Competitions\n readonly teams: Teams\n readonly matches: Matches\n readonly ai: Ai\n readonly tokens: Tokens\n\n private readonly connection: Connection\n private readonly http: MrDogeHttpClient\n\n constructor(options: MrDogeOptions) {\n if (!options?.apiKey) throw new Error(\"MrDoge: `apiKey` is required\")\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL\n const requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs\n\n this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n })\n\n const config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl,\n apiKey: options.apiKey,\n httpClient: this.http,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n maxReconnectAttempts:\n options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,\n reconnectBackoff: {\n ...DEFAULT_CONFIG.reconnectBackoff,\n ...options.reconnectBackoff,\n },\n compression: options.compression ?? DEFAULT_CONFIG.compression,\n }\n\n this.connection = new Connection(config)\n\n const defaults = { locale: options.locale, timezone: options.timezone }\n this.regions = new Regions(this.connection, defaults)\n this.competitions = new Competitions(this.connection, defaults)\n this.teams = new Teams(this.connection, defaults)\n this.matches = new Matches(this.connection, defaults, this.http)\n this.ai = new Ai(this.connection, defaults)\n this.tokens = new Tokens(this.connection)\n }\n\n /**\n * Listen to connection lifecycle events.\n */\n on<E extends keyof ConnectionEvents>(\n event: E,\n fn: (payload: ConnectionEvents[E]) => void,\n ): () => void {\n return this.connection.on(event, fn)\n }\n\n /**\n * Force-open the connection now instead of waiting for the first call.\n * Returns the welcome payload from the server.\n */\n async connect() {\n return this.connection.connect()\n }\n\n /**\n * Close the connection and cancel every active subscription. The client is\n * unusable after `close()`.\n */\n async close(): Promise<void> {\n await this.connection.close()\n }\n}\n","import WebSocket, { type RawData } from \"ws\"\nimport {\n PROTOCOL_VERSION,\n SUBPROTOCOL,\n type MethodName,\n type MethodParams,\n type MethodResult,\n type WelcomeParams,\n type SubscriptionEventParams,\n type SubscriptionClosedParams,\n type RpcRequest,\n} from \"@mrdoge/protocol\"\nimport type { HttpMethodName, MrDogeHttpClient } from \"@mrdoge/http\"\nimport {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\n\n/**\n * Per-call options accepted by every method that makes a request. Mirrors\n * the `fetch` convention so callers can plug in a standard `AbortController`.\n *\n * When `signal` fires, the in-flight request is dropped client-side and the\n * returned promise rejects with `AbortError` (`err.name === \"AbortError\"`).\n */\nexport interface CallOptions {\n signal?: AbortSignal\n}\n\n// Terminal close codes — see PROTOCOL.md §10.\nconst TERMINAL_CLOSE_CODES = new Set([4001, 4002, 4003, 4029])\n\nexport interface ConnectionConfig {\n baseUrl: string\n apiKey: string\n /**\n * HTTP client used as the cold-start fast path. When `call()` fires\n * before the WebSocket is open, it routes through this client so reads\n * don't pay the WS handshake latency. Subscriptions still always use WS.\n */\n httpClient: MrDogeHttpClient\n /** Default locale applied to method params. Per-call overrides win. */\n locale?: string\n /** Default timezone applied to method params. Per-call overrides win. */\n timezone?: string\n requestTimeoutMs: number\n maxReconnectAttempts: number\n reconnectBackoff: BackoffConfig\n compression: boolean\n /** Auth must complete (auth ack + welcome) within this many ms. */\n authTimeoutMs: number\n}\n\nexport const DEFAULT_CONFIG: Omit<\n ConnectionConfig,\n \"apiKey\" | \"baseUrl\" | \"httpClient\"\n> = {\n requestTimeoutMs: 10_000,\n maxReconnectAttempts: Infinity,\n reconnectBackoff: DEFAULT_BACKOFF,\n compression: true,\n authTimeoutMs: 10_000,\n}\n\nexport interface ConnectionEvents {\n connected: { welcome: WelcomeParams }\n disconnected: { reason: string; code: number }\n reconnecting: { attempt: number; delayMs: number }\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * Active subscriptions tracked by the connection. The handle's `subId` is\n * mutable — it changes on reconnect when the server issues a fresh id.\n */\nexport interface SubscriptionRegistration {\n /** Current server-issued sub id. Changes on reconnect. */\n subId: string\n method: MethodName\n params: unknown\n onEvent: (event: SubscriptionEventParams) => void\n onClosed: (params: SubscriptionClosedParams) => void\n /** Called by the connection when a reconnect resubscribe produced a fresh snapshot. */\n onSnapshot: (newSubId: string, snapshot: unknown) => void\n}\n\n/**\n * Long-lived WebSocket connection with JSON-RPC dispatch and automatic\n * reconnection. Subscriptions are resubscribed transparently on reconnect.\n */\nexport class Connection {\n private readonly emitter = new Emitter<ConnectionEvents>()\n private readonly config: ConnectionConfig\n private ws: WebSocket | null = null\n private nextRequestId = 1\n private readonly pending = new Map<string, PendingRequest>()\n private readonly subscriptions = new Map<string, SubscriptionRegistration>()\n private connectingPromise: Promise<WelcomeParams> | null = null\n private welcome: WelcomeParams | null = null\n private closed = false\n private reconnectAttempt = 0\n private reconnectAbort: AbortController | null = null\n\n constructor(config: ConnectionConfig) {\n this.config = config\n }\n\n on = this.emitter.on.bind(this.emitter)\n off = this.emitter.off.bind(this.emitter)\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.welcome !== null\n }\n\n /**\n * Idempotent. Returns the welcome payload once connected + authed.\n */\n async connect(): Promise<WelcomeParams> {\n if (this.closed) throw new ConnectionError(\"Connection is closed\")\n if (this.welcome && this.ws?.readyState === WebSocket.OPEN) return this.welcome\n if (this.connectingPromise) return this.connectingPromise\n\n this.connectingPromise = this.openAndAuth().finally(() => {\n this.connectingPromise = null\n })\n return this.connectingPromise\n }\n\n async call<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n options?: CallOptions,\n ): Promise<MethodResult<M>> {\n if (this.closed) {\n return Promise.reject(new DisconnectedError(\"Client closed\"))\n }\n // If WS isn't open, route reads through HTTP — saves the WS handshake\n // (~1s+) on cold start. Only customer-facing reads reach `call()`;\n // auth + subscription.cancel use `send()` directly. Subscriptions go\n // through `registerSubscription` which always opens WS.\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return this.config.httpClient.call(\n method as HttpMethodName,\n params as MethodParams<HttpMethodName>,\n options,\n ) as Promise<MethodResult<M>>\n }\n return this.send(method, params, options) as Promise<MethodResult<M>>\n }\n\n /**\n * Registers a subscription with the connection. The connection sends the\n * subscribe call, stores the registration for reconnect, and routes incoming\n * push events to the handler.\n */\n async registerSubscription<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n handlers: {\n onEvent: SubscriptionRegistration[\"onEvent\"]\n onClosed: SubscriptionRegistration[\"onClosed\"]\n onSnapshot: SubscriptionRegistration[\"onSnapshot\"]\n },\n options?: CallOptions,\n ): Promise<{ subId: string; snapshot: unknown }> {\n await this.connect()\n const result = (await this.send(method, params, options)) as { sub: string; snapshot: unknown }\n const registration: SubscriptionRegistration = {\n subId: result.sub,\n method,\n params,\n onEvent: handlers.onEvent,\n onClosed: handlers.onClosed,\n onSnapshot: handlers.onSnapshot,\n }\n this.subscriptions.set(result.sub, registration)\n return { subId: result.sub, snapshot: result.snapshot }\n }\n\n /**\n * Cancels a subscription server-side and removes the registration locally.\n */\n async cancelSubscription(subId: string): Promise<void> {\n const reg = this.subscriptions.get(subId)\n if (!reg) return\n this.subscriptions.delete(subId)\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n await this.send(\"subscription.cancel\" as MethodName, { sub: subId } as never)\n } catch {\n // Best-effort: even if server rejects, local cleanup is done.\n }\n }\n }\n\n async close(): Promise<void> {\n this.closed = true\n this.reconnectAbort?.abort()\n this.reconnectAbort = null\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(\"Connection closed by client\"))\n }\n this.pending.clear()\n this.subscriptions.clear()\n if (this.ws && this.ws.readyState <= WebSocket.OPEN) {\n this.ws.close(1000, \"client_close\")\n }\n this.ws = null\n this.welcome = null\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async openAndAuth(): Promise<WelcomeParams> {\n const ws = new WebSocket(this.config.baseUrl, [SUBPROTOCOL], {\n perMessageDeflate: this.config.compression\n ? { threshold: 1024 }\n : false,\n handshakeTimeout: 15_000,\n })\n this.ws = ws\n this.welcome = null\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup()\n resolve()\n }\n const onError = (err: Error) => {\n cleanup()\n reject(new ConnectionError(`Failed to open WebSocket: ${err.message}`))\n }\n const onClose = (code: number, reason: Buffer) => {\n cleanup()\n reject(new ConnectionError(`WebSocket closed before open (${code}): ${reason.toString()}`))\n }\n const cleanup = () => {\n ws.off(\"open\", onOpen)\n ws.off(\"error\", onError)\n ws.off(\"close\", onClose)\n }\n ws.once(\"open\", onOpen)\n ws.once(\"error\", onError)\n ws.once(\"close\", onClose)\n })\n\n // Attach long-lived listeners now that we're open.\n ws.on(\"message\", (data) => this.handleMessage(data))\n ws.on(\"close\", (code, reason) => this.handleClose(code, reason.toString()))\n ws.on(\"error\", (err) => this.handleSocketError(err))\n\n // Send auth as the first frame and await both the ack and the welcome.\n const welcome = await this.performAuth()\n this.welcome = welcome\n this.reconnectAttempt = 0\n this.emitter.emit(\"connected\", { welcome })\n\n // If this was a reconnect, resubscribe everything.\n if (this.subscriptions.size > 0) {\n await this.resubscribeAll()\n }\n return welcome\n }\n\n private async performAuth(): Promise<WelcomeParams> {\n const welcomePromise = new Promise<WelcomeParams>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new TimeoutError(\"Auth timed out waiting for welcome\"))\n }, this.config.authTimeoutMs)\n this.pendingWelcome = {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n }\n })\n\n const authAck = this.send(\"auth\" as MethodName, { apiKey: this.config.apiKey } as never).catch(\n (err: Error) => {\n // Surface auth-level error explicitly (server may close immediately).\n if (err instanceof MrDogeError) throw err\n throw new UnauthorizedError(`Authentication failed: ${err.message}`)\n },\n )\n\n await authAck\n return welcomePromise\n }\n\n /**\n * Set during `performAuth` so we can resolve when the `welcome` notification arrives.\n */\n private pendingWelcome: PendingRequest | null = null\n\n private send(\n method: string,\n params: unknown,\n options?: CallOptions,\n ): Promise<unknown> {\n if (options?.signal?.aborted) {\n return Promise.reject(new AbortError())\n }\n const ws = this.ws\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new DisconnectedError(\"Socket not open\"))\n }\n const id = String(this.nextRequestId++)\n const frame: RpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n }\n return new Promise((resolve, reject) => {\n const onAbort = () => {\n this.pending.delete(id)\n clearTimeout(timer)\n options!.signal!.removeEventListener(\"abort\", onAbort)\n reject(new AbortError())\n }\n const detachSignal = () => {\n options?.signal?.removeEventListener(\"abort\", onAbort)\n }\n const wrappedResolve = (val: unknown) => {\n detachSignal()\n resolve(val)\n }\n const wrappedReject = (err: Error) => {\n detachSignal()\n reject(err)\n }\n const timer = setTimeout(() => {\n this.pending.delete(id)\n detachSignal()\n reject(new TimeoutError(`Request \"${method}\" timed out after ${this.config.requestTimeoutMs}ms`))\n }, this.config.requestTimeoutMs)\n this.pending.set(id, { resolve: wrappedResolve, reject: wrappedReject, timer })\n options?.signal?.addEventListener(\"abort\", onAbort)\n try {\n ws.send(JSON.stringify(frame))\n } catch (err) {\n this.pending.delete(id)\n clearTimeout(timer)\n detachSignal()\n reject(new ConnectionError(`Failed to send frame: ${(err as Error).message}`))\n }\n })\n }\n\n private handleMessage(raw: RawData): void {\n let text: string\n if (typeof raw === \"string\") text = raw\n else if (Buffer.isBuffer(raw)) text = raw.toString(\"utf8\")\n else if (raw instanceof ArrayBuffer) text = Buffer.from(raw).toString(\"utf8\")\n else text = Buffer.concat(raw as Buffer[]).toString(\"utf8\")\n\n let frame: any\n try {\n frame = JSON.parse(text)\n } catch {\n // Drop unparseable frames — the protocol guarantees JSON.\n return\n }\n if (frame.jsonrpc !== \"2.0\") return\n\n // Response to a pending request?\n if (typeof frame.id === \"string\") {\n const p = this.pending.get(frame.id)\n if (!p) return\n this.pending.delete(frame.id)\n clearTimeout(p.timer)\n if (frame.error) {\n p.reject(rpcErrorToTyped(frame.error))\n } else {\n p.resolve(frame.result)\n }\n return\n }\n\n // Notification — `method` carries the event name.\n if (typeof frame.method === \"string\") {\n this.handleNotification(frame.method, frame.params)\n }\n }\n\n private handleNotification(method: string, params: unknown): void {\n if (method === \"welcome\") {\n const pending = this.pendingWelcome\n this.pendingWelcome = null\n if (pending) {\n clearTimeout(pending.timer)\n pending.resolve(params as WelcomeParams)\n }\n return\n }\n\n if (method === \"subscription.event\") {\n const p = params as SubscriptionEventParams\n const reg = this.subscriptions.get(p.sub)\n reg?.onEvent(p)\n return\n }\n\n if (method === \"subscription.closed\") {\n const p = params as SubscriptionClosedParams\n const reg = this.subscriptions.get(p.sub)\n if (reg) {\n this.subscriptions.delete(p.sub)\n reg.onClosed(p)\n }\n return\n }\n\n // Unknown notifications: ignore per the additive-future-changes rule.\n }\n\n private handleClose(code: number, reason: string): void {\n const wasConnected = this.welcome !== null\n this.welcome = null\n this.ws = null\n\n // Reject every in-flight request — they didn't complete.\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(`Connection closed (${code}): ${reason}`))\n }\n this.pending.clear()\n if (this.pendingWelcome) {\n clearTimeout(this.pendingWelcome.timer)\n this.pendingWelcome.reject(new DisconnectedError(`Connection closed during auth (${code})`))\n this.pendingWelcome = null\n }\n\n if (this.closed) return\n\n this.emitter.emit(\"disconnected\", { code, reason })\n\n if (TERMINAL_CLOSE_CODES.has(code)) {\n // Don't reconnect on terminal codes — let the caller surface it.\n this.closed = true\n return\n }\n\n if (wasConnected || this.subscriptions.size > 0) {\n // Try to reconnect.\n this.scheduleReconnect()\n }\n }\n\n private handleSocketError(_err: Error): void {\n // The \"close\" event always follows; let handleClose drive reconnection.\n }\n\n private async scheduleReconnect(): Promise<void> {\n if (this.closed) return\n if (this.reconnectAbort) return // already scheduled\n this.reconnectAbort = new AbortController()\n const signal = this.reconnectAbort.signal\n\n while (!this.closed && this.reconnectAttempt < this.config.maxReconnectAttempts) {\n this.reconnectAttempt += 1\n const delayMs = nextDelay(this.reconnectAttempt, this.config.reconnectBackoff)\n this.emitter.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs })\n try {\n await sleep(delayMs, signal)\n } catch {\n return // aborted\n }\n if (this.closed) return\n try {\n await this.openAndAuth()\n this.reconnectAbort = null\n return\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n this.closed = true\n this.reconnectAbort = null\n return\n }\n // Otherwise loop and try again with bigger backoff.\n }\n }\n this.reconnectAbort = null\n }\n\n private async resubscribeAll(): Promise<void> {\n const olds = Array.from(this.subscriptions.values())\n this.subscriptions.clear()\n for (const old of olds) {\n try {\n const result = (await this.send(old.method, old.params)) as {\n sub: string\n snapshot: unknown\n }\n old.subId = result.sub\n this.subscriptions.set(result.sub, old)\n old.onSnapshot(result.sub, result.snapshot)\n } catch (err) {\n old.onClosed({\n sub: old.subId,\n reason: \"internal_error\",\n message:\n err instanceof Error\n ? `Resubscribe failed: ${err.message}`\n : \"Resubscribe failed\",\n })\n }\n }\n }\n}\n\nexport { PROTOCOL_VERSION }\n","import type { ErrorCode, RpcError } from \"@mrdoge/protocol\"\n\n/**\n * Base class for every SDK-thrown error. Map by `instanceof` or by `code`.\n */\nexport class MrDogeError extends Error {\n readonly code: ErrorCode | \"connection_error\" | \"disconnected\" | \"timeout\" | \"aborted\" | \"unknown\"\n readonly data?: unknown\n\n constructor(\n code: MrDogeError[\"code\"],\n message: string,\n data?: unknown,\n ) {\n super(message)\n this.name = this.constructor.name\n this.code = code\n this.data = data\n }\n}\n\nexport class UnauthorizedError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unauthorized\", message, data)\n }\n}\n\nexport class ForbiddenError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"forbidden\", message, data)\n }\n}\n\nexport class NotFoundError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"not_found\", message, data)\n }\n}\n\nexport class ValidationError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"invalid_params\", message, data)\n }\n}\n\nexport class RateLimitError extends MrDogeError {\n readonly retryAfterMs: number\n readonly limit?: number\n readonly remaining?: number\n readonly resetAt?: Date\n\n constructor(message: string, data?: unknown) {\n super(\"rate_limited\", message, data)\n const d = (data ?? {}) as {\n retryAfterMs?: number\n limit?: number\n remaining?: number\n resetAt?: string\n }\n this.retryAfterMs = d.retryAfterMs ?? 0\n this.limit = d.limit\n this.remaining = d.remaining\n this.resetAt = d.resetAt ? new Date(d.resetAt) : undefined\n }\n}\n\nexport class SubscriptionLimitError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"subscription_limit_exceeded\", message, data)\n }\n}\n\nexport class ConnectionLimitError extends MrDogeError {\n readonly current?: number\n readonly max?: number\n\n constructor(message: string, data?: unknown) {\n super(\"connection_limit_exceeded\", message, data)\n const d = (data ?? {}) as { current?: number; max?: number }\n this.current = d.current\n this.max = d.max\n }\n}\n\nexport class UnavailableError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unavailable\", message, data)\n }\n}\n\nexport class InternalError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"internal_error\", message, data)\n }\n}\n\nexport class ProtocolError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"protocol_error\", message, data)\n }\n}\n\n/** Raised when the SDK can't reach or stay connected to the server. */\nexport class ConnectionError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"connection_error\", message, data)\n }\n}\n\n/** A request was in flight when the connection dropped. The caller should retry if safe. */\nexport class DisconnectedError extends MrDogeError {\n constructor(message = \"Connection dropped before response\", data?: unknown) {\n super(\"disconnected\", message, data)\n }\n}\n\nexport class TimeoutError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"timeout\", message, data)\n }\n}\n\n/**\n * Thrown when a request is aborted via the customer-supplied\n * `options.signal`. Matches `fetch` convention — `err.name === \"AbortError\"`.\n */\nexport class AbortError extends MrDogeError {\n constructor(message = \"Request aborted\") {\n super(\"aborted\", message)\n }\n}\n\nconst CODE_MAP: Record<ErrorCode, new (message: string, data?: unknown) => MrDogeError> = {\n invalid_request: ProtocolError,\n invalid_params: ValidationError,\n method_not_found: ProtocolError,\n unauthorized: UnauthorizedError,\n forbidden: ForbiddenError,\n not_found: NotFoundError,\n rate_limited: RateLimitError,\n subscription_limit_exceeded: SubscriptionLimitError,\n connection_limit_exceeded: ConnectionLimitError,\n unavailable: UnavailableError,\n internal_error: InternalError,\n protocol_error: ProtocolError,\n}\n\n/**\n * Convert a wire-format RpcError into the appropriate typed SDK error.\n */\nexport function rpcErrorToTyped(err: RpcError): MrDogeError {\n const Ctor = CODE_MAP[err.code]\n if (!Ctor) return new MrDogeError(\"unknown\", err.message, err.data)\n return new Ctor(err.message, err.data)\n}\n","/**\n * Tiny typed event emitter — avoids depending on Node's `events` module so\n * we can target browsers later without a polyfill.\n *\n * Listeners registered via `on` return an unsubscribe function for that\n * specific listener.\n */\nexport class Emitter<Events extends Record<string, any>> {\n private listeners = new Map<keyof Events, Set<(payload: any) => void>>()\n\n on<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): () => void {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(fn)\n return () => set!.delete(fn)\n }\n\n off<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): void {\n this.listeners.get(event)?.delete(fn)\n }\n\n emit<E extends keyof Events>(event: E, payload: Events[E]): void {\n const set = this.listeners.get(event)\n if (!set || set.size === 0) return\n for (const fn of [...set]) {\n try {\n fn(payload)\n } catch (err) {\n queueMicrotask(() => {\n throw err\n })\n }\n }\n }\n\n clear(): void {\n this.listeners.clear()\n }\n}\n","export interface BackoffConfig {\n minMs: number\n maxMs: number\n /** Jitter as a fraction of the computed delay (0.2 = ±20%). */\n jitter: number\n}\n\nexport const DEFAULT_BACKOFF: BackoffConfig = {\n minMs: 1_000,\n maxMs: 30_000,\n jitter: 0.2,\n}\n\n/**\n * Returns the delay (ms) for a given reconnect attempt (1-indexed). Capped\n * exponential growth with random jitter.\n */\nexport function nextDelay(attempt: number, cfg: BackoffConfig = DEFAULT_BACKOFF): number {\n const exp = Math.min(cfg.maxMs, cfg.minMs * 2 ** (attempt - 1))\n const jitter = exp * cfg.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(exp + jitter))\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"aborted\"))\n return\n }\n const t = setTimeout(resolve, ms)\n signal?.addEventListener(\"abort\", () => {\n clearTimeout(t)\n reject(new Error(\"aborted\"))\n })\n })\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Regions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"regions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"regions.list\">> {\n return this.conn.call(\n \"regions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Competitions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"competitions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"competitions.list\">> {\n return this.conn.call(\n \"competitions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Teams {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"teams.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.list\">> {\n return this.conn.call(\n \"teams.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n get(\n params: MethodParams<\"teams.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.get\">> {\n return this.conn.call(\n \"teams.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n form(\n params: MethodParams<\"teams.form\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.form\">> {\n return this.conn.call(\n \"teams.form\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type {\n SubscriptionEventParams,\n SubscriptionClosedReason,\n MethodResult,\n SubscriptionMethodName,\n PushEventsOf,\n} from \"@mrdoge/protocol\"\nimport type { Connection } from \"./connection\"\nimport { Emitter } from \"./internal/emitter\"\n\n/**\n * Maps each push event name to the typed `data` payload it carries.\n * Derived from the discriminated union in `@mrdoge/protocol`.\n */\ntype EventDataMap = {\n [E in SubscriptionEventParams as E[\"event\"]]: E[\"data\"]\n}\n\ntype SnapshotOf<M extends SubscriptionMethodName> = MethodResult<M> extends {\n snapshot: infer S\n}\n ? S\n : never\n\ntype SubEventMap<M extends SubscriptionMethodName> = {\n [E in PushEventsOf<M> & keyof EventDataMap]: EventDataMap[E]\n} & {\n snapshot: SnapshotOf<M>\n closed: { reason: SubscriptionClosedReason; message?: string }\n}\n\n/**\n * Sentinel subId used when the Subscription was constructed from an HTTP\n * cold-start snapshot before the WS subscribe response arrived. The real\n * subId replaces it via `_deliverSnapshot` once WS resolves.\n */\nexport const PENDING_SUB_ID = \"__pending_ws__\"\n\n/**\n * Handle returned by `mrdoge.matches.subscribe(...)` and `subscribeLive(...)`.\n *\n * Stable across reconnects: the underlying server-issued `sub` id may change,\n * but this handle and its listeners persist. On reconnect, the SDK refreshes\n * `snapshot` and emits a `snapshot` event so callers can replace their local\n * state.\n */\nexport class Subscription<M extends SubscriptionMethodName> {\n private readonly emitter = new Emitter<SubEventMap<M>>()\n private readonly connection: Connection\n private internalSubId: string\n private currentSnapshot: SnapshotOf<M>\n private cancelled = false\n /**\n * True when `cancel()` was called before the WS subscribe arrived (subId\n * still pending). Once WS resolves, `_deliverSnapshot` issues the\n * server-side cancel so we don't leak a registered subscription.\n */\n private pendingCancel = false\n\n /** @internal — constructed by the SDK, not by user code. */\n constructor(connection: Connection, subId: string, initialSnapshot: SnapshotOf<M>) {\n this.connection = connection\n this.internalSubId = subId\n this.currentSnapshot = initialSnapshot\n }\n\n /** The latest snapshot the server has emitted (initial, or post-reconnect). */\n get snapshot(): SnapshotOf<M> {\n return this.currentSnapshot\n }\n\n /** Current server-issued subscription id. Changes on reconnect. */\n get id(): string {\n return this.internalSubId\n }\n\n /**\n * Listen for a push event from this subscription. Returns an unsubscribe\n * function that removes only this listener.\n *\n * In addition to protocol push events, two synthetic events fire:\n * - `snapshot` — when a reconnect produced a fresh snapshot\n * - `closed` — when the server terminates the subscription (or cancel)\n */\n on<E extends keyof SubEventMap<M>>(\n event: E,\n fn: (payload: SubEventMap<M>[E]) => void,\n ): () => void {\n return this.emitter.on(event, fn)\n }\n\n /**\n * Cancel the subscription server-side. Idempotent — calling twice is safe.\n */\n async cancel(): Promise<void> {\n if (this.cancelled) return\n this.cancelled = true\n if (this.internalSubId === PENDING_SUB_ID) {\n // WS hasn't delivered the real subId yet — flag for cancellation when\n // it arrives. Don't await; `cancel()` returns immediately.\n this.pendingCancel = true\n this.emitter.clear()\n return\n }\n await this.connection.cancelSubscription(this.internalSubId)\n this.emitter.clear()\n }\n\n // ---------------------------------------------------------------------\n // Internal — invoked by Connection's routing layer.\n // ---------------------------------------------------------------------\n\n /** @internal */\n _deliverEvent(params: SubscriptionEventParams): void {\n if (this.cancelled) return\n this.emitter.emit(\n params.event as keyof SubEventMap<M>,\n params.data as SubEventMap<M>[keyof SubEventMap<M>],\n )\n }\n\n /** @internal */\n _deliverSnapshot(newSubId: string, snapshot: SnapshotOf<M>): void {\n this.internalSubId = newSubId\n // Customer cancelled while we were still waiting for WS. The server\n // registered the subscription anyway — release it now.\n if (this.pendingCancel) {\n this.pendingCancel = false\n this.connection.cancelSubscription(newSubId).catch(() => undefined)\n return\n }\n if (this.cancelled) return\n this.currentSnapshot = snapshot\n this.emitter.emit(\"snapshot\" as keyof SubEventMap<M>, snapshot as never)\n }\n\n /** @internal */\n _deliverClosed(reason: SubscriptionClosedReason, message?: string): void {\n if (this.cancelled) return\n this.cancelled = true\n this.emitter.emit(\n \"closed\" as keyof SubEventMap<M>,\n { reason, message } as never,\n )\n this.emitter.clear()\n }\n}\n","import type {\n MethodParams,\n MethodResult,\n SubscriptionEventParams,\n SubscriptionClosedParams,\n} from \"@mrdoge/protocol\"\nimport type { MrDogeHttpClient } from \"@mrdoge/http\"\nimport type { CallOptions, Connection } from \"../connection\"\nimport { Subscription, PENDING_SUB_ID } from \"../subscription\"\n\ninterface Defaults {\n locale?: string\n timezone?: string\n}\n\nexport class Matches {\n constructor(\n private readonly conn: Connection,\n private readonly defaults: Defaults,\n private readonly http: MrDogeHttpClient,\n ) {}\n\n list(\n params: MethodParams<\"matches.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.list\">> {\n return this.conn.call(\n \"matches.list\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n get(\n params: MethodParams<\"matches.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.get\">> {\n return this.conn.call(\n \"matches.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n trending(\n params: MethodParams<\"matches.trending\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.trending\">> {\n return this.conn.call(\n \"matches.trending\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n search(\n params: MethodParams<\"matches.search\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.search\">> {\n return this.conn.call(\n \"matches.search\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n async subscribeLive(\n params: MethodParams<\"matches.subscribeLive\"> = {},\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribeLive\">> {\n const merged = { locale: this.defaults.locale, ...params }\n\n // Race HTTP `matches.getLive` against the WS subscribe. HTTP returns from\n // the server-side Redis cache in ~50-150ms; the WS path pays the TCP +\n // TLS + auth handshake on cold start (~1.5s). Whichever lands first\n // populates `.snapshot`. The WS path always continues — it's the source\n // of `match.upd` / `match.del` deltas after the initial snapshot.\n let handle: Subscription<\"matches.subscribeLive\">\n\n const wsPromise = this.conn.registerSubscription(\n \"matches.subscribeLive\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n\n const httpPromise = this.http\n .call(\n \"matches.getLive\",\n merged as MethodParams<\"matches.getLive\">,\n options,\n )\n .then((snapshot) => ({ kind: \"http\" as const, snapshot }))\n\n type Winner =\n | { kind: \"http\"; snapshot: MethodResult<\"matches.getLive\"> }\n | { kind: \"ws\"; subId: string; snapshot: MethodResult<\"matches.subscribeLive\">[\"snapshot\"] }\n\n const wsRace: Promise<Winner> = wsPromise.then((r) => ({\n kind: \"ws\",\n subId: r.subId,\n snapshot: r.snapshot as MethodResult<\"matches.subscribeLive\">[\"snapshot\"],\n }))\n\n let winner: Winner\n try {\n winner = await Promise.race<Winner>([httpPromise, wsRace])\n } catch {\n // HTTP rejected before WS resolved. Fall back to WS alone.\n const ws = await wsPromise\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n ws.subId,\n ws.snapshot as never,\n )\n return handle\n }\n\n if (winner.kind === \"ws\") {\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n winner.subId,\n winner.snapshot as never,\n )\n return handle\n }\n\n // HTTP won — build the Subscription with the HTTP snapshot and a pending\n // subId. The WS subscribe is still in flight; when it resolves, the\n // onSnapshot handler (or our tail handler) delivers the real subId +\n // canonical snapshot. If WS fails outright, deliver `closed` so the\n // caller can react.\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n PENDING_SUB_ID,\n winner.snapshot as never,\n )\n wsPromise\n .then((r) => {\n handle._deliverSnapshot(r.subId, r.snapshot as never)\n })\n .catch((err) => {\n handle._deliverClosed(\n \"internal_error\",\n err instanceof Error ? err.message : String(err),\n )\n })\n return handle\n }\n\n async subscribe(\n params: MethodParams<\"matches.subscribe\">,\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribe\">> {\n const merged = { locale: this.defaults.locale, ...params }\n let handle: Subscription<\"matches.subscribe\">\n const { subId, snapshot } = await this.conn.registerSubscription(\n \"matches.subscribe\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n handle = new Subscription<\"matches.subscribe\">(this.conn, subId, snapshot as never)\n return handle\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nclass Picks {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.picks.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.picks.list\">> {\n return this.conn.call(\n \"ai.picks.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nclass Recommendations {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.recommendations.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.recommendations.list\">> {\n return this.conn.call(\n \"ai.recommendations.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nexport class Ai {\n readonly picks: Picks\n readonly recommendations: Recommendations\n\n constructor(conn: Connection, defaults: { locale?: string }) {\n this.picks = new Picks(conn, defaults)\n this.recommendations = new Recommendations(conn, defaults)\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\n/**\n * Server-side resource for minting short-lived auth tokens for client-side use.\n *\n * Typical use: customer's backend has the `sk_live_...` key and exposes an\n * HTTP route that mints tokens for their frontend (browser / React Native):\n *\n * ```ts\n * app.post(\"/api/mrdoge/token\", async (req, res) => {\n * const { token, expiresAt } = await mrdoge.tokens.create({ ttl: 600 })\n * res.json({ token, expiresAt })\n * })\n * ```\n *\n * The frontend uses these tokens with `@mrdoge/client` — the sk_live_... key\n * never leaves the backend.\n */\nexport class Tokens {\n constructor(private readonly conn: Connection) {}\n\n /**\n * Mint a short-lived JWT auth token.\n *\n * @param params.ttl Token lifetime in seconds. Default 600 (10 min).\n * Server-enforced bounds: min 60, max 86400 (24h).\n * @returns { token, expiresAt } — `token` is opaque to the customer; pass\n * it to `@mrdoge/client`. `expiresAt` is ISO-8601.\n */\n create(\n params: MethodParams<\"tokens.create\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"tokens.create\">> {\n return this.conn.call(\"tokens.create\", params, options)\n }\n}\n"],"mappings":"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","names":["WebSocket"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/connection.ts","../src/errors.ts","../src/internal/emitter.ts","../src/internal/backoff.ts","../src/resources/regions.ts","../src/resources/competitions.ts","../src/resources/teams.ts","../src/subscription.ts","../src/resources/matches.ts","../src/resources/ai.ts","../src/resources/tokens.ts"],"sourcesContent":["/**\n * @mrdoge/node — official Node / TypeScript SDK for Mr. Doge realtime sports data.\n *\n * ```ts\n * import { MrDoge } from \"@mrdoge/node\"\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n */\n\nexport { MrDoge, type MrDogeOptions, DEFAULT_BASE_URL } from \"./client\"\nexport { Subscription } from \"./subscription\"\nexport type { CallOptions, ListAllOptions } from \"./connection\"\nexport {\n MrDogeError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ValidationError,\n RateLimitError,\n SubscriptionLimitError,\n ConnectionLimitError,\n UnavailableError,\n InternalError,\n ProtocolError,\n ConnectionError,\n DisconnectedError,\n TimeoutError,\n AbortError,\n} from \"./errors\"\n\n// Re-export the most useful protocol types so consumers don't have to import\n// from `@mrdoge/protocol` directly for typical usage.\nexport type {\n Region,\n Competition,\n Team,\n TeamDetail,\n TeamForm,\n TeamFormMatch,\n TeamFormResult,\n Sport,\n Match,\n MatchDetail,\n MatchStats,\n MatchStatus,\n MatchState,\n MatchSelect,\n MatchDetailSelect,\n Selector,\n Clock,\n Period,\n StatPlayer,\n Market,\n BetItem,\n Pagination,\n AiPick,\n PickConfidence,\n PickResult,\n PickLeg,\n Recommendation,\n WelcomeParams,\n SubscriptionClosedReason,\n ErrorCode,\n} from \"@mrdoge/protocol\"\n","import { createHttpClient, type MrDogeHttpClient } from \"@mrdoge/http\"\nimport { Connection, DEFAULT_CONFIG, type ConnectionConfig, type ConnectionEvents } from \"./connection\"\nimport { type BackoffConfig } from \"./internal/backoff\"\nimport { Regions } from \"./resources/regions\"\nimport { Competitions } from \"./resources/competitions\"\nimport { Teams } from \"./resources/teams\"\nimport { Matches } from \"./resources/matches\"\nimport { Ai } from \"./resources/ai\"\nimport { Tokens } from \"./resources/tokens\"\n\nexport const DEFAULT_BASE_URL = \"wss://api.mrdoge.co/sdk/v1\"\n\n/**\n * Derive the HTTP gateway URL from the configured WS URL by swapping the\n * scheme. One `baseUrl` config drives both transports.\n */\nfunction wsToHttp(url: string): string {\n if (url.startsWith(\"wss://\")) return \"https://\" + url.slice(\"wss://\".length)\n if (url.startsWith(\"ws://\")) return \"http://\" + url.slice(\"ws://\".length)\n return url\n}\n\nexport interface MrDogeOptions {\n apiKey: string\n\n /** Override the server URL (e.g. for local dev). Defaults to production. */\n baseUrl?: string\n\n /** Default locale applied to every call; overridable per-call. */\n locale?: string\n\n /** Default timezone applied to every call; overridable per-call. */\n timezone?: string\n\n /** Request-level timeout in milliseconds. Default 10s. */\n requestTimeoutMs?: number\n\n /** Max reconnect attempts on transient disconnects. Default Infinity. */\n maxReconnectAttempts?: number\n\n /** Exponential backoff config for reconnects. */\n reconnectBackoff?: Partial<BackoffConfig>\n\n /**\n * Whether to negotiate `permessage-deflate` compression at the WS handshake.\n * Default `true`. Disable for CPU-constrained environments.\n */\n compression?: boolean\n}\n\n/**\n * Mr. Doge SDK entrypoint.\n *\n * ```ts\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n *\n * The constructor does not open a connection. The WebSocket is opened lazily\n * on the first method call and reused for the lifetime of the client.\n */\nexport class MrDoge {\n readonly regions: Regions\n readonly competitions: Competitions\n readonly teams: Teams\n readonly matches: Matches\n readonly ai: Ai\n readonly tokens: Tokens\n\n private readonly connection: Connection\n private readonly http: MrDogeHttpClient\n\n constructor(options: MrDogeOptions) {\n if (!options?.apiKey) throw new Error(\"MrDoge: `apiKey` is required\")\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL\n const requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs\n\n this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n })\n\n const config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl,\n apiKey: options.apiKey,\n httpClient: this.http,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n maxReconnectAttempts:\n options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,\n reconnectBackoff: {\n ...DEFAULT_CONFIG.reconnectBackoff,\n ...options.reconnectBackoff,\n },\n compression: options.compression ?? DEFAULT_CONFIG.compression,\n }\n\n this.connection = new Connection(config)\n\n const defaults = { locale: options.locale, timezone: options.timezone }\n this.regions = new Regions(this.connection, defaults)\n this.competitions = new Competitions(this.connection, defaults)\n this.teams = new Teams(this.connection, defaults)\n this.matches = new Matches(this.connection, defaults, this.http)\n this.ai = new Ai(this.connection, defaults)\n this.tokens = new Tokens(this.connection)\n }\n\n /**\n * Listen to connection lifecycle events.\n */\n on<E extends keyof ConnectionEvents>(\n event: E,\n fn: (payload: ConnectionEvents[E]) => void,\n ): () => void {\n return this.connection.on(event, fn)\n }\n\n /**\n * Force-open the connection now instead of waiting for the first call.\n * Returns the welcome payload from the server.\n */\n async connect() {\n return this.connection.connect()\n }\n\n /**\n * Close the connection and cancel every active subscription. The client is\n * unusable after `close()`.\n */\n async close(): Promise<void> {\n await this.connection.close()\n }\n}\n","import WebSocket, { type RawData } from \"ws\"\nimport {\n PROTOCOL_VERSION,\n SUBPROTOCOL,\n type MethodName,\n type MethodParams,\n type MethodResult,\n type WelcomeParams,\n type SubscriptionEventParams,\n type SubscriptionClosedParams,\n type RpcRequest,\n} from \"@mrdoge/protocol\"\nimport type { HttpMethodName, MrDogeHttpClient } from \"@mrdoge/http\"\nimport {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\n\n/**\n * Per-call options accepted by every method that makes a request. Mirrors\n * the `fetch` convention so callers can plug in a standard `AbortController`.\n *\n * When `signal` fires, the in-flight request is dropped client-side and the\n * returned promise rejects with `AbortError` (`err.name === \"AbortError\"`).\n */\nexport interface CallOptions {\n signal?: AbortSignal\n}\n\n/**\n * Options for `listAll` cursor-walk helpers. `signal` aborts the in-flight\n * page; the helper rethrows the `AbortError`. `onPage` fires after every\n * page lands — pass it to stream partial results into your store while the\n * walk continues.\n */\nexport interface ListAllOptions<T> extends CallOptions {\n onPage?: (page: T[], accumulated: T[]) => void\n}\n\n// Terminal close codes — see PROTOCOL.md §10.\nconst TERMINAL_CLOSE_CODES = new Set([4001, 4002, 4003, 4029])\n\nexport interface ConnectionConfig {\n baseUrl: string\n apiKey: string\n /**\n * HTTP client used as the cold-start fast path. When `call()` fires\n * before the WebSocket is open, it routes through this client so reads\n * don't pay the WS handshake latency. Subscriptions still always use WS.\n */\n httpClient: MrDogeHttpClient\n /** Default locale applied to method params. Per-call overrides win. */\n locale?: string\n /** Default timezone applied to method params. Per-call overrides win. */\n timezone?: string\n requestTimeoutMs: number\n maxReconnectAttempts: number\n reconnectBackoff: BackoffConfig\n compression: boolean\n /** Auth must complete (auth ack + welcome) within this many ms. */\n authTimeoutMs: number\n}\n\nexport const DEFAULT_CONFIG: Omit<\n ConnectionConfig,\n \"apiKey\" | \"baseUrl\" | \"httpClient\"\n> = {\n requestTimeoutMs: 10_000,\n maxReconnectAttempts: Infinity,\n reconnectBackoff: DEFAULT_BACKOFF,\n compression: true,\n authTimeoutMs: 10_000,\n}\n\nexport interface ConnectionEvents {\n connected: { welcome: WelcomeParams }\n disconnected: { reason: string; code: number }\n reconnecting: { attempt: number; delayMs: number }\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * Active subscriptions tracked by the connection. The handle's `subId` is\n * mutable — it changes on reconnect when the server issues a fresh id.\n */\nexport interface SubscriptionRegistration {\n /** Current server-issued sub id. Changes on reconnect. */\n subId: string\n method: MethodName\n params: unknown\n onEvent: (event: SubscriptionEventParams) => void\n onClosed: (params: SubscriptionClosedParams) => void\n /** Called by the connection when a reconnect resubscribe produced a fresh snapshot. */\n onSnapshot: (newSubId: string, snapshot: unknown) => void\n}\n\n/**\n * Long-lived WebSocket connection with JSON-RPC dispatch and automatic\n * reconnection. Subscriptions are resubscribed transparently on reconnect.\n */\nexport class Connection {\n private readonly emitter = new Emitter<ConnectionEvents>()\n private readonly config: ConnectionConfig\n private ws: WebSocket | null = null\n private nextRequestId = 1\n private readonly pending = new Map<string, PendingRequest>()\n private readonly subscriptions = new Map<string, SubscriptionRegistration>()\n private connectingPromise: Promise<WelcomeParams> | null = null\n private welcome: WelcomeParams | null = null\n private closed = false\n private reconnectAttempt = 0\n private reconnectAbort: AbortController | null = null\n\n constructor(config: ConnectionConfig) {\n this.config = config\n }\n\n on = this.emitter.on.bind(this.emitter)\n off = this.emitter.off.bind(this.emitter)\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.welcome !== null\n }\n\n /**\n * Idempotent. Returns the welcome payload once connected + authed.\n */\n async connect(): Promise<WelcomeParams> {\n if (this.closed) throw new ConnectionError(\"Connection is closed\")\n if (this.welcome && this.ws?.readyState === WebSocket.OPEN) return this.welcome\n if (this.connectingPromise) return this.connectingPromise\n\n this.connectingPromise = this.openAndAuth().finally(() => {\n this.connectingPromise = null\n })\n return this.connectingPromise\n }\n\n async call<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n options?: CallOptions,\n ): Promise<MethodResult<M>> {\n if (this.closed) {\n return Promise.reject(new DisconnectedError(\"Client closed\"))\n }\n // If WS isn't open, route reads through HTTP — saves the WS handshake\n // (~1s+) on cold start. Only customer-facing reads reach `call()`;\n // auth + subscription.cancel use `send()` directly. Subscriptions go\n // through `registerSubscription` which always opens WS.\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return this.config.httpClient.call(\n method as HttpMethodName,\n params as MethodParams<HttpMethodName>,\n options,\n ) as Promise<MethodResult<M>>\n }\n return this.send(method, params, options) as Promise<MethodResult<M>>\n }\n\n /**\n * Registers a subscription with the connection. The connection sends the\n * subscribe call, stores the registration for reconnect, and routes incoming\n * push events to the handler.\n */\n async registerSubscription<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n handlers: {\n onEvent: SubscriptionRegistration[\"onEvent\"]\n onClosed: SubscriptionRegistration[\"onClosed\"]\n onSnapshot: SubscriptionRegistration[\"onSnapshot\"]\n },\n options?: CallOptions,\n ): Promise<{ subId: string; snapshot: unknown }> {\n await this.connect()\n const result = (await this.send(method, params, options)) as { sub: string; snapshot: unknown }\n const registration: SubscriptionRegistration = {\n subId: result.sub,\n method,\n params,\n onEvent: handlers.onEvent,\n onClosed: handlers.onClosed,\n onSnapshot: handlers.onSnapshot,\n }\n this.subscriptions.set(result.sub, registration)\n return { subId: result.sub, snapshot: result.snapshot }\n }\n\n /**\n * Cancels a subscription server-side and removes the registration locally.\n */\n async cancelSubscription(subId: string): Promise<void> {\n const reg = this.subscriptions.get(subId)\n if (!reg) return\n this.subscriptions.delete(subId)\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n await this.send(\"subscription.cancel\" as MethodName, { sub: subId } as never)\n } catch {\n // Best-effort: even if server rejects, local cleanup is done.\n }\n }\n }\n\n async close(): Promise<void> {\n this.closed = true\n this.reconnectAbort?.abort()\n this.reconnectAbort = null\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(\"Connection closed by client\"))\n }\n this.pending.clear()\n this.subscriptions.clear()\n if (this.ws && this.ws.readyState <= WebSocket.OPEN) {\n this.ws.close(1000, \"client_close\")\n }\n this.ws = null\n this.welcome = null\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async openAndAuth(): Promise<WelcomeParams> {\n const ws = new WebSocket(this.config.baseUrl, [SUBPROTOCOL], {\n perMessageDeflate: this.config.compression\n ? { threshold: 1024 }\n : false,\n handshakeTimeout: 15_000,\n })\n this.ws = ws\n this.welcome = null\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup()\n resolve()\n }\n const onError = (err: Error) => {\n cleanup()\n reject(new ConnectionError(`Failed to open WebSocket: ${err.message}`))\n }\n const onClose = (code: number, reason: Buffer) => {\n cleanup()\n reject(new ConnectionError(`WebSocket closed before open (${code}): ${reason.toString()}`))\n }\n const cleanup = () => {\n ws.off(\"open\", onOpen)\n ws.off(\"error\", onError)\n ws.off(\"close\", onClose)\n }\n ws.once(\"open\", onOpen)\n ws.once(\"error\", onError)\n ws.once(\"close\", onClose)\n })\n\n // Attach long-lived listeners now that we're open.\n ws.on(\"message\", (data) => this.handleMessage(data))\n ws.on(\"close\", (code, reason) => this.handleClose(code, reason.toString()))\n ws.on(\"error\", (err) => this.handleSocketError(err))\n\n // Send auth as the first frame and await both the ack and the welcome.\n const welcome = await this.performAuth()\n this.welcome = welcome\n this.reconnectAttempt = 0\n this.emitter.emit(\"connected\", { welcome })\n\n // If this was a reconnect, resubscribe everything.\n if (this.subscriptions.size > 0) {\n await this.resubscribeAll()\n }\n return welcome\n }\n\n private async performAuth(): Promise<WelcomeParams> {\n const welcomePromise = new Promise<WelcomeParams>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new TimeoutError(\"Auth timed out waiting for welcome\"))\n }, this.config.authTimeoutMs)\n this.pendingWelcome = {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n }\n })\n\n const authAck = this.send(\"auth\" as MethodName, { apiKey: this.config.apiKey } as never).catch(\n (err: Error) => {\n // Surface auth-level error explicitly (server may close immediately).\n if (err instanceof MrDogeError) throw err\n throw new UnauthorizedError(`Authentication failed: ${err.message}`)\n },\n )\n\n await authAck\n return welcomePromise\n }\n\n /**\n * Set during `performAuth` so we can resolve when the `welcome` notification arrives.\n */\n private pendingWelcome: PendingRequest | null = null\n\n private send(\n method: string,\n params: unknown,\n options?: CallOptions,\n ): Promise<unknown> {\n if (options?.signal?.aborted) {\n return Promise.reject(new AbortError())\n }\n const ws = this.ws\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new DisconnectedError(\"Socket not open\"))\n }\n const id = String(this.nextRequestId++)\n const frame: RpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n }\n return new Promise((resolve, reject) => {\n const onAbort = () => {\n this.pending.delete(id)\n clearTimeout(timer)\n options!.signal!.removeEventListener(\"abort\", onAbort)\n reject(new AbortError())\n }\n const detachSignal = () => {\n options?.signal?.removeEventListener(\"abort\", onAbort)\n }\n const wrappedResolve = (val: unknown) => {\n detachSignal()\n resolve(val)\n }\n const wrappedReject = (err: Error) => {\n detachSignal()\n reject(err)\n }\n const timer = setTimeout(() => {\n this.pending.delete(id)\n detachSignal()\n reject(new TimeoutError(`Request \"${method}\" timed out after ${this.config.requestTimeoutMs}ms`))\n }, this.config.requestTimeoutMs)\n this.pending.set(id, { resolve: wrappedResolve, reject: wrappedReject, timer })\n options?.signal?.addEventListener(\"abort\", onAbort)\n try {\n ws.send(JSON.stringify(frame))\n } catch (err) {\n this.pending.delete(id)\n clearTimeout(timer)\n detachSignal()\n reject(new ConnectionError(`Failed to send frame: ${(err as Error).message}`))\n }\n })\n }\n\n private handleMessage(raw: RawData): void {\n let text: string\n if (typeof raw === \"string\") text = raw\n else if (Buffer.isBuffer(raw)) text = raw.toString(\"utf8\")\n else if (raw instanceof ArrayBuffer) text = Buffer.from(raw).toString(\"utf8\")\n else text = Buffer.concat(raw as Buffer[]).toString(\"utf8\")\n\n let frame: any\n try {\n frame = JSON.parse(text)\n } catch {\n // Drop unparseable frames — the protocol guarantees JSON.\n return\n }\n if (frame.jsonrpc !== \"2.0\") return\n\n // Response to a pending request?\n if (typeof frame.id === \"string\") {\n const p = this.pending.get(frame.id)\n if (!p) return\n this.pending.delete(frame.id)\n clearTimeout(p.timer)\n if (frame.error) {\n p.reject(rpcErrorToTyped(frame.error))\n } else {\n p.resolve(frame.result)\n }\n return\n }\n\n // Notification — `method` carries the event name.\n if (typeof frame.method === \"string\") {\n this.handleNotification(frame.method, frame.params)\n }\n }\n\n private handleNotification(method: string, params: unknown): void {\n if (method === \"welcome\") {\n const pending = this.pendingWelcome\n this.pendingWelcome = null\n if (pending) {\n clearTimeout(pending.timer)\n pending.resolve(params as WelcomeParams)\n }\n return\n }\n\n if (method === \"subscription.event\") {\n const p = params as SubscriptionEventParams\n const reg = this.subscriptions.get(p.sub)\n reg?.onEvent(p)\n return\n }\n\n if (method === \"subscription.closed\") {\n const p = params as SubscriptionClosedParams\n const reg = this.subscriptions.get(p.sub)\n if (reg) {\n this.subscriptions.delete(p.sub)\n reg.onClosed(p)\n }\n return\n }\n\n // Unknown notifications: ignore per the additive-future-changes rule.\n }\n\n private handleClose(code: number, reason: string): void {\n const wasConnected = this.welcome !== null\n this.welcome = null\n this.ws = null\n\n // Reject every in-flight request — they didn't complete.\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(`Connection closed (${code}): ${reason}`))\n }\n this.pending.clear()\n if (this.pendingWelcome) {\n clearTimeout(this.pendingWelcome.timer)\n this.pendingWelcome.reject(new DisconnectedError(`Connection closed during auth (${code})`))\n this.pendingWelcome = null\n }\n\n if (this.closed) return\n\n this.emitter.emit(\"disconnected\", { code, reason })\n\n if (TERMINAL_CLOSE_CODES.has(code)) {\n // Don't reconnect on terminal codes — let the caller surface it.\n this.closed = true\n return\n }\n\n if (wasConnected || this.subscriptions.size > 0) {\n // Try to reconnect.\n this.scheduleReconnect()\n }\n }\n\n private handleSocketError(_err: Error): void {\n // The \"close\" event always follows; let handleClose drive reconnection.\n }\n\n private async scheduleReconnect(): Promise<void> {\n if (this.closed) return\n if (this.reconnectAbort) return // already scheduled\n this.reconnectAbort = new AbortController()\n const signal = this.reconnectAbort.signal\n\n while (!this.closed && this.reconnectAttempt < this.config.maxReconnectAttempts) {\n this.reconnectAttempt += 1\n const delayMs = nextDelay(this.reconnectAttempt, this.config.reconnectBackoff)\n this.emitter.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs })\n try {\n await sleep(delayMs, signal)\n } catch {\n return // aborted\n }\n if (this.closed) return\n try {\n await this.openAndAuth()\n this.reconnectAbort = null\n return\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n this.closed = true\n this.reconnectAbort = null\n return\n }\n // Otherwise loop and try again with bigger backoff.\n }\n }\n this.reconnectAbort = null\n }\n\n private async resubscribeAll(): Promise<void> {\n const olds = Array.from(this.subscriptions.values())\n this.subscriptions.clear()\n for (const old of olds) {\n try {\n const result = (await this.send(old.method, old.params)) as {\n sub: string\n snapshot: unknown\n }\n old.subId = result.sub\n this.subscriptions.set(result.sub, old)\n old.onSnapshot(result.sub, result.snapshot)\n } catch (err) {\n old.onClosed({\n sub: old.subId,\n reason: \"internal_error\",\n message:\n err instanceof Error\n ? `Resubscribe failed: ${err.message}`\n : \"Resubscribe failed\",\n })\n }\n }\n }\n}\n\nexport { PROTOCOL_VERSION }\n","import type { ErrorCode, RpcError } from \"@mrdoge/protocol\"\n\n/**\n * Base class for every SDK-thrown error. Map by `instanceof` or by `code`.\n */\nexport class MrDogeError extends Error {\n readonly code: ErrorCode | \"connection_error\" | \"disconnected\" | \"timeout\" | \"aborted\" | \"unknown\"\n readonly data?: unknown\n\n constructor(\n code: MrDogeError[\"code\"],\n message: string,\n data?: unknown,\n ) {\n super(message)\n this.name = this.constructor.name\n this.code = code\n this.data = data\n }\n}\n\nexport class UnauthorizedError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unauthorized\", message, data)\n }\n}\n\nexport class ForbiddenError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"forbidden\", message, data)\n }\n}\n\nexport class NotFoundError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"not_found\", message, data)\n }\n}\n\nexport class ValidationError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"invalid_params\", message, data)\n }\n}\n\nexport class RateLimitError extends MrDogeError {\n readonly retryAfterMs: number\n readonly limit?: number\n readonly remaining?: number\n readonly resetAt?: Date\n\n constructor(message: string, data?: unknown) {\n super(\"rate_limited\", message, data)\n const d = (data ?? {}) as {\n retryAfterMs?: number\n limit?: number\n remaining?: number\n resetAt?: string\n }\n this.retryAfterMs = d.retryAfterMs ?? 0\n this.limit = d.limit\n this.remaining = d.remaining\n this.resetAt = d.resetAt ? new Date(d.resetAt) : undefined\n }\n}\n\nexport class SubscriptionLimitError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"subscription_limit_exceeded\", message, data)\n }\n}\n\nexport class ConnectionLimitError extends MrDogeError {\n readonly current?: number\n readonly max?: number\n\n constructor(message: string, data?: unknown) {\n super(\"connection_limit_exceeded\", message, data)\n const d = (data ?? {}) as { current?: number; max?: number }\n this.current = d.current\n this.max = d.max\n }\n}\n\nexport class UnavailableError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unavailable\", message, data)\n }\n}\n\nexport class InternalError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"internal_error\", message, data)\n }\n}\n\nexport class ProtocolError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"protocol_error\", message, data)\n }\n}\n\n/** Raised when the SDK can't reach or stay connected to the server. */\nexport class ConnectionError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"connection_error\", message, data)\n }\n}\n\n/** A request was in flight when the connection dropped. The caller should retry if safe. */\nexport class DisconnectedError extends MrDogeError {\n constructor(message = \"Connection dropped before response\", data?: unknown) {\n super(\"disconnected\", message, data)\n }\n}\n\nexport class TimeoutError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"timeout\", message, data)\n }\n}\n\n/**\n * Thrown when a request is aborted via the customer-supplied\n * `options.signal`. Matches `fetch` convention — `err.name === \"AbortError\"`.\n */\nexport class AbortError extends MrDogeError {\n constructor(message = \"Request aborted\") {\n super(\"aborted\", message)\n }\n}\n\nconst CODE_MAP: Record<ErrorCode, new (message: string, data?: unknown) => MrDogeError> = {\n invalid_request: ProtocolError,\n invalid_params: ValidationError,\n method_not_found: ProtocolError,\n unauthorized: UnauthorizedError,\n forbidden: ForbiddenError,\n not_found: NotFoundError,\n rate_limited: RateLimitError,\n subscription_limit_exceeded: SubscriptionLimitError,\n connection_limit_exceeded: ConnectionLimitError,\n unavailable: UnavailableError,\n internal_error: InternalError,\n protocol_error: ProtocolError,\n}\n\n/**\n * Convert a wire-format RpcError into the appropriate typed SDK error.\n */\nexport function rpcErrorToTyped(err: RpcError): MrDogeError {\n const Ctor = CODE_MAP[err.code]\n if (!Ctor) return new MrDogeError(\"unknown\", err.message, err.data)\n return new Ctor(err.message, err.data)\n}\n","/**\n * Tiny typed event emitter — avoids depending on Node's `events` module so\n * we can target browsers later without a polyfill.\n *\n * Listeners registered via `on` return an unsubscribe function for that\n * specific listener.\n */\nexport class Emitter<Events extends Record<string, any>> {\n private listeners = new Map<keyof Events, Set<(payload: any) => void>>()\n\n on<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): () => void {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(fn)\n return () => set!.delete(fn)\n }\n\n off<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): void {\n this.listeners.get(event)?.delete(fn)\n }\n\n emit<E extends keyof Events>(event: E, payload: Events[E]): void {\n const set = this.listeners.get(event)\n if (!set || set.size === 0) return\n for (const fn of [...set]) {\n try {\n fn(payload)\n } catch (err) {\n queueMicrotask(() => {\n throw err\n })\n }\n }\n }\n\n clear(): void {\n this.listeners.clear()\n }\n}\n","export interface BackoffConfig {\n minMs: number\n maxMs: number\n /** Jitter as a fraction of the computed delay (0.2 = ±20%). */\n jitter: number\n}\n\nexport const DEFAULT_BACKOFF: BackoffConfig = {\n minMs: 1_000,\n maxMs: 30_000,\n jitter: 0.2,\n}\n\n/**\n * Returns the delay (ms) for a given reconnect attempt (1-indexed). Capped\n * exponential growth with random jitter.\n */\nexport function nextDelay(attempt: number, cfg: BackoffConfig = DEFAULT_BACKOFF): number {\n const exp = Math.min(cfg.maxMs, cfg.minMs * 2 ** (attempt - 1))\n const jitter = exp * cfg.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(exp + jitter))\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"aborted\"))\n return\n }\n const t = setTimeout(resolve, ms)\n signal?.addEventListener(\"abort\", () => {\n clearTimeout(t)\n reject(new Error(\"aborted\"))\n })\n })\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Regions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"regions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"regions.list\">> {\n return this.conn.call(\n \"regions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Competitions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"competitions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"competitions.list\">> {\n return this.conn.call(\n \"competitions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Teams {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"teams.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.list\">> {\n return this.conn.call(\n \"teams.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n get(\n params: MethodParams<\"teams.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.get\">> {\n return this.conn.call(\n \"teams.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n form(\n params: MethodParams<\"teams.form\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.form\">> {\n return this.conn.call(\n \"teams.form\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type {\n SubscriptionEventParams,\n SubscriptionClosedReason,\n MethodResult,\n SubscriptionMethodName,\n PushEventsOf,\n} from \"@mrdoge/protocol\"\nimport type { Connection } from \"./connection\"\nimport { Emitter } from \"./internal/emitter\"\n\n/**\n * Maps each push event name to the typed `data` payload it carries.\n * Derived from the discriminated union in `@mrdoge/protocol`.\n */\ntype EventDataMap = {\n [E in SubscriptionEventParams as E[\"event\"]]: E[\"data\"]\n}\n\ntype SnapshotOf<M extends SubscriptionMethodName> = MethodResult<M> extends {\n snapshot: infer S\n}\n ? S\n : never\n\ntype SubEventMap<M extends SubscriptionMethodName> = {\n [E in PushEventsOf<M> & keyof EventDataMap]: EventDataMap[E]\n} & {\n snapshot: SnapshotOf<M>\n closed: { reason: SubscriptionClosedReason; message?: string }\n}\n\n/**\n * Sentinel subId used when the Subscription was constructed from an HTTP\n * cold-start snapshot before the WS subscribe response arrived. The real\n * subId replaces it via `_deliverSnapshot` once WS resolves.\n */\nexport const PENDING_SUB_ID = \"__pending_ws__\"\n\n/**\n * Handle returned by `mrdoge.matches.subscribe(...)` and `subscribeLive(...)`.\n *\n * Stable across reconnects: the underlying server-issued `sub` id may change,\n * but this handle and its listeners persist. On reconnect, the SDK refreshes\n * `snapshot` and emits a `snapshot` event so callers can replace their local\n * state.\n */\nexport class Subscription<M extends SubscriptionMethodName> {\n private readonly emitter = new Emitter<SubEventMap<M>>()\n private readonly connection: Connection\n private internalSubId: string\n private currentSnapshot: SnapshotOf<M>\n private cancelled = false\n /**\n * True when `cancel()` was called before the WS subscribe arrived (subId\n * still pending). Once WS resolves, `_deliverSnapshot` issues the\n * server-side cancel so we don't leak a registered subscription.\n */\n private pendingCancel = false\n\n /** @internal — constructed by the SDK, not by user code. */\n constructor(connection: Connection, subId: string, initialSnapshot: SnapshotOf<M>) {\n this.connection = connection\n this.internalSubId = subId\n this.currentSnapshot = initialSnapshot\n }\n\n /** The latest snapshot the server has emitted (initial, or post-reconnect). */\n get snapshot(): SnapshotOf<M> {\n return this.currentSnapshot\n }\n\n /** Current server-issued subscription id. Changes on reconnect. */\n get id(): string {\n return this.internalSubId\n }\n\n /**\n * Listen for a push event from this subscription. Returns an unsubscribe\n * function that removes only this listener.\n *\n * In addition to protocol push events, two synthetic events fire:\n * - `snapshot` — when a reconnect produced a fresh snapshot\n * - `closed` — when the server terminates the subscription (or cancel)\n */\n on<E extends keyof SubEventMap<M>>(\n event: E,\n fn: (payload: SubEventMap<M>[E]) => void,\n ): () => void {\n return this.emitter.on(event, fn)\n }\n\n /**\n * Cancel the subscription server-side. Idempotent — calling twice is safe.\n */\n async cancel(): Promise<void> {\n if (this.cancelled) return\n this.cancelled = true\n if (this.internalSubId === PENDING_SUB_ID) {\n // WS hasn't delivered the real subId yet — flag for cancellation when\n // it arrives. Don't await; `cancel()` returns immediately.\n this.pendingCancel = true\n this.emitter.clear()\n return\n }\n await this.connection.cancelSubscription(this.internalSubId)\n this.emitter.clear()\n }\n\n // ---------------------------------------------------------------------\n // Internal — invoked by Connection's routing layer.\n // ---------------------------------------------------------------------\n\n /** @internal */\n _deliverEvent(params: SubscriptionEventParams): void {\n if (this.cancelled) return\n this.emitter.emit(\n params.event as keyof SubEventMap<M>,\n params.data as SubEventMap<M>[keyof SubEventMap<M>],\n )\n }\n\n /** @internal */\n _deliverSnapshot(newSubId: string, snapshot: SnapshotOf<M>): void {\n this.internalSubId = newSubId\n // Customer cancelled while we were still waiting for WS. The server\n // registered the subscription anyway — release it now.\n if (this.pendingCancel) {\n this.pendingCancel = false\n this.connection.cancelSubscription(newSubId).catch(() => undefined)\n return\n }\n if (this.cancelled) return\n this.currentSnapshot = snapshot\n this.emitter.emit(\"snapshot\" as keyof SubEventMap<M>, snapshot as never)\n }\n\n /** @internal */\n _deliverClosed(reason: SubscriptionClosedReason, message?: string): void {\n if (this.cancelled) return\n this.cancelled = true\n this.emitter.emit(\n \"closed\" as keyof SubEventMap<M>,\n { reason, message } as never,\n )\n this.emitter.clear()\n }\n}\n","import type {\n Match,\n MethodParams,\n MethodResult,\n SubscriptionEventParams,\n SubscriptionClosedParams,\n} from \"@mrdoge/protocol\"\nimport type { MrDogeHttpClient } from \"@mrdoge/http\"\nimport type { CallOptions, Connection, ListAllOptions } from \"../connection\"\nimport { Subscription, PENDING_SUB_ID } from \"../subscription\"\n\ninterface Defaults {\n locale?: string\n timezone?: string\n}\n\nexport class Matches {\n constructor(\n private readonly conn: Connection,\n private readonly defaults: Defaults,\n private readonly http: MrDogeHttpClient,\n ) {}\n\n list(\n params: MethodParams<\"matches.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.list\">> {\n return this.conn.call(\n \"matches.list\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n /**\n * Walk every page of `matches.list` and return one combined array. The\n * helper drives the cursor for you — pass everything except `cursor`,\n * including `limit` for page size. AbortSignal aborts the whole walk.\n * `onPage` fires after each page for progressive rendering.\n *\n * Server-side keyset cursor pagination keeps the walk drift-safe (no\n * duplicate or missed IDs across page boundaries even when the underlying\n * set shifts mid-walk).\n */\n async listAll(\n params: Omit<MethodParams<\"matches.list\">, \"cursor\"> = {},\n options?: ListAllOptions<Match>,\n ): Promise<Match[]> {\n const { onPage, ...callOptions } = options ?? {}\n const result: Match[] = []\n let cursor: string | undefined\n do {\n const page = await this.list({ ...params, cursor }, callOptions)\n const pageData = page.data as Match[]\n result.push(...pageData)\n onPage?.(pageData, result)\n cursor = page.pagination.nextCursor ?? undefined\n } while (cursor)\n return result\n }\n\n get(\n params: MethodParams<\"matches.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.get\">> {\n return this.conn.call(\n \"matches.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n trending(\n params: MethodParams<\"matches.trending\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.trending\">> {\n return this.conn.call(\n \"matches.trending\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n search(\n params: MethodParams<\"matches.search\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.search\">> {\n return this.conn.call(\n \"matches.search\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n async subscribeLive(\n params: MethodParams<\"matches.subscribeLive\"> = {},\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribeLive\">> {\n const merged = { locale: this.defaults.locale, ...params }\n\n // Race HTTP `matches.getLive` against the WS subscribe. HTTP returns from\n // the server-side Redis cache in ~50-150ms; the WS path pays the TCP +\n // TLS + auth handshake on cold start (~1.5s). Whichever lands first\n // populates `.snapshot`. The WS path always continues — it's the source\n // of `match.upd` / `match.del` deltas after the initial snapshot.\n let handle: Subscription<\"matches.subscribeLive\">\n\n const wsPromise = this.conn.registerSubscription(\n \"matches.subscribeLive\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n\n const httpPromise = this.http\n .call(\n \"matches.getLive\",\n merged as MethodParams<\"matches.getLive\">,\n options,\n )\n .then((snapshot) => ({ kind: \"http\" as const, snapshot }))\n\n type Winner =\n | { kind: \"http\"; snapshot: MethodResult<\"matches.getLive\"> }\n | { kind: \"ws\"; subId: string; snapshot: MethodResult<\"matches.subscribeLive\">[\"snapshot\"] }\n\n const wsRace: Promise<Winner> = wsPromise.then((r) => ({\n kind: \"ws\",\n subId: r.subId,\n snapshot: r.snapshot as MethodResult<\"matches.subscribeLive\">[\"snapshot\"],\n }))\n\n let winner: Winner\n try {\n winner = await Promise.race<Winner>([httpPromise, wsRace])\n } catch {\n // HTTP rejected before WS resolved. Fall back to WS alone.\n const ws = await wsPromise\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n ws.subId,\n ws.snapshot as never,\n )\n return handle\n }\n\n if (winner.kind === \"ws\") {\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n winner.subId,\n winner.snapshot as never,\n )\n return handle\n }\n\n // HTTP won — build the Subscription with the HTTP snapshot and a pending\n // subId. The WS subscribe is still in flight; when it resolves, the\n // onSnapshot handler (or our tail handler) delivers the real subId +\n // canonical snapshot. If WS fails outright, deliver `closed` so the\n // caller can react.\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n PENDING_SUB_ID,\n winner.snapshot as never,\n )\n wsPromise\n .then((r) => {\n handle._deliverSnapshot(r.subId, r.snapshot as never)\n })\n .catch((err) => {\n handle._deliverClosed(\n \"internal_error\",\n err instanceof Error ? err.message : String(err),\n )\n })\n return handle\n }\n\n async subscribe(\n params: MethodParams<\"matches.subscribe\">,\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribe\">> {\n const merged = { locale: this.defaults.locale, ...params }\n let handle: Subscription<\"matches.subscribe\">\n const { subId, snapshot } = await this.conn.registerSubscription(\n \"matches.subscribe\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n handle = new Subscription<\"matches.subscribe\">(this.conn, subId, snapshot as never)\n return handle\n }\n}\n","import type { AiPick, MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection, ListAllOptions } from \"../connection\"\n\nclass Picks {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.picks.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.picks.list\">> {\n return this.conn.call(\n \"ai.picks.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n /**\n * Walk every page of `ai.picks.list` and return one combined array. Same\n * shape as `matches.listAll`. Server-side keyset pagination keeps the\n * walk drift-safe.\n */\n async listAll(\n params: Omit<MethodParams<\"ai.picks.list\">, \"cursor\"> = {},\n options?: ListAllOptions<AiPick>,\n ): Promise<AiPick[]> {\n const { onPage, ...callOptions } = options ?? {}\n const result: AiPick[] = []\n let cursor: string | undefined\n do {\n const page = await this.list({ ...params, cursor }, callOptions)\n const pageData = page.data as AiPick[]\n result.push(...pageData)\n onPage?.(pageData, result)\n cursor = page.pagination.nextCursor ?? undefined\n } while (cursor)\n return result\n }\n}\n\nclass Recommendations {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.recommendations.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.recommendations.list\">> {\n return this.conn.call(\n \"ai.recommendations.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nexport class Ai {\n readonly picks: Picks\n readonly recommendations: Recommendations\n\n constructor(conn: Connection, defaults: { locale?: string }) {\n this.picks = new Picks(conn, defaults)\n this.recommendations = new Recommendations(conn, defaults)\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\n/**\n * Server-side resource for minting short-lived auth tokens for client-side use.\n *\n * Typical use: customer's backend has the `sk_live_...` key and exposes an\n * HTTP route that mints tokens for their frontend (browser / React Native):\n *\n * ```ts\n * app.post(\"/api/mrdoge/token\", async (req, res) => {\n * const { token, expiresAt } = await mrdoge.tokens.create({ ttl: 600 })\n * res.json({ token, expiresAt })\n * })\n * ```\n *\n * The frontend uses these tokens with `@mrdoge/client` — the sk_live_... key\n * never leaves the backend.\n */\nexport class Tokens {\n constructor(private readonly conn: Connection) {}\n\n /**\n * Mint a short-lived JWT auth token.\n *\n * @param params.ttl Token lifetime in seconds. Default 600 (10 min).\n * Server-enforced bounds: min 60, max 86400 (24h).\n * @returns { token, expiresAt } — `token` is opaque to the customer; pass\n * it to `@mrdoge/client`. `expiresAt` is ISO-8601.\n */\n create(\n params: MethodParams<\"tokens.create\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"tokens.create\">> {\n return this.conn.call(\"tokens.create\", params, options)\n }\n}\n"],"mappings":"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","names":["WebSocket"]}
|
package/dist/index.mjs
CHANGED
|
@@ -706,6 +706,29 @@ var Matches = class {
|
|
|
706
706
|
options
|
|
707
707
|
);
|
|
708
708
|
}
|
|
709
|
+
/**
|
|
710
|
+
* Walk every page of `matches.list` and return one combined array. The
|
|
711
|
+
* helper drives the cursor for you — pass everything except `cursor`,
|
|
712
|
+
* including `limit` for page size. AbortSignal aborts the whole walk.
|
|
713
|
+
* `onPage` fires after each page for progressive rendering.
|
|
714
|
+
*
|
|
715
|
+
* Server-side keyset cursor pagination keeps the walk drift-safe (no
|
|
716
|
+
* duplicate or missed IDs across page boundaries even when the underlying
|
|
717
|
+
* set shifts mid-walk).
|
|
718
|
+
*/
|
|
719
|
+
async listAll(params = {}, options) {
|
|
720
|
+
const { onPage, ...callOptions } = options ?? {};
|
|
721
|
+
const result = [];
|
|
722
|
+
let cursor;
|
|
723
|
+
do {
|
|
724
|
+
const page = await this.list({ ...params, cursor }, callOptions);
|
|
725
|
+
const pageData = page.data;
|
|
726
|
+
result.push(...pageData);
|
|
727
|
+
onPage?.(pageData, result);
|
|
728
|
+
cursor = page.pagination.nextCursor ?? void 0;
|
|
729
|
+
} while (cursor);
|
|
730
|
+
return result;
|
|
731
|
+
}
|
|
709
732
|
get(params, options) {
|
|
710
733
|
return this.conn.call(
|
|
711
734
|
"matches.get",
|
|
@@ -822,6 +845,24 @@ var Picks = class {
|
|
|
822
845
|
options
|
|
823
846
|
);
|
|
824
847
|
}
|
|
848
|
+
/**
|
|
849
|
+
* Walk every page of `ai.picks.list` and return one combined array. Same
|
|
850
|
+
* shape as `matches.listAll`. Server-side keyset pagination keeps the
|
|
851
|
+
* walk drift-safe.
|
|
852
|
+
*/
|
|
853
|
+
async listAll(params = {}, options) {
|
|
854
|
+
const { onPage, ...callOptions } = options ?? {};
|
|
855
|
+
const result = [];
|
|
856
|
+
let cursor;
|
|
857
|
+
do {
|
|
858
|
+
const page = await this.list({ ...params, cursor }, callOptions);
|
|
859
|
+
const pageData = page.data;
|
|
860
|
+
result.push(...pageData);
|
|
861
|
+
onPage?.(pageData, result);
|
|
862
|
+
cursor = page.pagination.nextCursor ?? void 0;
|
|
863
|
+
} while (cursor);
|
|
864
|
+
return result;
|
|
865
|
+
}
|
|
825
866
|
};
|
|
826
867
|
var Recommendations = class {
|
|
827
868
|
constructor(conn, defaults) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/connection.ts","../src/errors.ts","../src/internal/emitter.ts","../src/internal/backoff.ts","../src/resources/regions.ts","../src/resources/competitions.ts","../src/resources/teams.ts","../src/subscription.ts","../src/resources/matches.ts","../src/resources/ai.ts","../src/resources/tokens.ts"],"sourcesContent":["import { createHttpClient, type MrDogeHttpClient } from \"@mrdoge/http\"\nimport { Connection, DEFAULT_CONFIG, type ConnectionConfig, type ConnectionEvents } from \"./connection\"\nimport { type BackoffConfig } from \"./internal/backoff\"\nimport { Regions } from \"./resources/regions\"\nimport { Competitions } from \"./resources/competitions\"\nimport { Teams } from \"./resources/teams\"\nimport { Matches } from \"./resources/matches\"\nimport { Ai } from \"./resources/ai\"\nimport { Tokens } from \"./resources/tokens\"\n\nexport const DEFAULT_BASE_URL = \"wss://api.mrdoge.co/sdk/v1\"\n\n/**\n * Derive the HTTP gateway URL from the configured WS URL by swapping the\n * scheme. One `baseUrl` config drives both transports.\n */\nfunction wsToHttp(url: string): string {\n if (url.startsWith(\"wss://\")) return \"https://\" + url.slice(\"wss://\".length)\n if (url.startsWith(\"ws://\")) return \"http://\" + url.slice(\"ws://\".length)\n return url\n}\n\nexport interface MrDogeOptions {\n apiKey: string\n\n /** Override the server URL (e.g. for local dev). Defaults to production. */\n baseUrl?: string\n\n /** Default locale applied to every call; overridable per-call. */\n locale?: string\n\n /** Default timezone applied to every call; overridable per-call. */\n timezone?: string\n\n /** Request-level timeout in milliseconds. Default 10s. */\n requestTimeoutMs?: number\n\n /** Max reconnect attempts on transient disconnects. Default Infinity. */\n maxReconnectAttempts?: number\n\n /** Exponential backoff config for reconnects. */\n reconnectBackoff?: Partial<BackoffConfig>\n\n /**\n * Whether to negotiate `permessage-deflate` compression at the WS handshake.\n * Default `true`. Disable for CPU-constrained environments.\n */\n compression?: boolean\n}\n\n/**\n * Mr. Doge SDK entrypoint.\n *\n * ```ts\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n *\n * The constructor does not open a connection. The WebSocket is opened lazily\n * on the first method call and reused for the lifetime of the client.\n */\nexport class MrDoge {\n readonly regions: Regions\n readonly competitions: Competitions\n readonly teams: Teams\n readonly matches: Matches\n readonly ai: Ai\n readonly tokens: Tokens\n\n private readonly connection: Connection\n private readonly http: MrDogeHttpClient\n\n constructor(options: MrDogeOptions) {\n if (!options?.apiKey) throw new Error(\"MrDoge: `apiKey` is required\")\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL\n const requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs\n\n this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n })\n\n const config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl,\n apiKey: options.apiKey,\n httpClient: this.http,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n maxReconnectAttempts:\n options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,\n reconnectBackoff: {\n ...DEFAULT_CONFIG.reconnectBackoff,\n ...options.reconnectBackoff,\n },\n compression: options.compression ?? DEFAULT_CONFIG.compression,\n }\n\n this.connection = new Connection(config)\n\n const defaults = { locale: options.locale, timezone: options.timezone }\n this.regions = new Regions(this.connection, defaults)\n this.competitions = new Competitions(this.connection, defaults)\n this.teams = new Teams(this.connection, defaults)\n this.matches = new Matches(this.connection, defaults, this.http)\n this.ai = new Ai(this.connection, defaults)\n this.tokens = new Tokens(this.connection)\n }\n\n /**\n * Listen to connection lifecycle events.\n */\n on<E extends keyof ConnectionEvents>(\n event: E,\n fn: (payload: ConnectionEvents[E]) => void,\n ): () => void {\n return this.connection.on(event, fn)\n }\n\n /**\n * Force-open the connection now instead of waiting for the first call.\n * Returns the welcome payload from the server.\n */\n async connect() {\n return this.connection.connect()\n }\n\n /**\n * Close the connection and cancel every active subscription. The client is\n * unusable after `close()`.\n */\n async close(): Promise<void> {\n await this.connection.close()\n }\n}\n","import WebSocket, { type RawData } from \"ws\"\nimport {\n PROTOCOL_VERSION,\n SUBPROTOCOL,\n type MethodName,\n type MethodParams,\n type MethodResult,\n type WelcomeParams,\n type SubscriptionEventParams,\n type SubscriptionClosedParams,\n type RpcRequest,\n} from \"@mrdoge/protocol\"\nimport type { HttpMethodName, MrDogeHttpClient } from \"@mrdoge/http\"\nimport {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\n\n/**\n * Per-call options accepted by every method that makes a request. Mirrors\n * the `fetch` convention so callers can plug in a standard `AbortController`.\n *\n * When `signal` fires, the in-flight request is dropped client-side and the\n * returned promise rejects with `AbortError` (`err.name === \"AbortError\"`).\n */\nexport interface CallOptions {\n signal?: AbortSignal\n}\n\n// Terminal close codes — see PROTOCOL.md §10.\nconst TERMINAL_CLOSE_CODES = new Set([4001, 4002, 4003, 4029])\n\nexport interface ConnectionConfig {\n baseUrl: string\n apiKey: string\n /**\n * HTTP client used as the cold-start fast path. When `call()` fires\n * before the WebSocket is open, it routes through this client so reads\n * don't pay the WS handshake latency. Subscriptions still always use WS.\n */\n httpClient: MrDogeHttpClient\n /** Default locale applied to method params. Per-call overrides win. */\n locale?: string\n /** Default timezone applied to method params. Per-call overrides win. */\n timezone?: string\n requestTimeoutMs: number\n maxReconnectAttempts: number\n reconnectBackoff: BackoffConfig\n compression: boolean\n /** Auth must complete (auth ack + welcome) within this many ms. */\n authTimeoutMs: number\n}\n\nexport const DEFAULT_CONFIG: Omit<\n ConnectionConfig,\n \"apiKey\" | \"baseUrl\" | \"httpClient\"\n> = {\n requestTimeoutMs: 10_000,\n maxReconnectAttempts: Infinity,\n reconnectBackoff: DEFAULT_BACKOFF,\n compression: true,\n authTimeoutMs: 10_000,\n}\n\nexport interface ConnectionEvents {\n connected: { welcome: WelcomeParams }\n disconnected: { reason: string; code: number }\n reconnecting: { attempt: number; delayMs: number }\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * Active subscriptions tracked by the connection. The handle's `subId` is\n * mutable — it changes on reconnect when the server issues a fresh id.\n */\nexport interface SubscriptionRegistration {\n /** Current server-issued sub id. Changes on reconnect. */\n subId: string\n method: MethodName\n params: unknown\n onEvent: (event: SubscriptionEventParams) => void\n onClosed: (params: SubscriptionClosedParams) => void\n /** Called by the connection when a reconnect resubscribe produced a fresh snapshot. */\n onSnapshot: (newSubId: string, snapshot: unknown) => void\n}\n\n/**\n * Long-lived WebSocket connection with JSON-RPC dispatch and automatic\n * reconnection. Subscriptions are resubscribed transparently on reconnect.\n */\nexport class Connection {\n private readonly emitter = new Emitter<ConnectionEvents>()\n private readonly config: ConnectionConfig\n private ws: WebSocket | null = null\n private nextRequestId = 1\n private readonly pending = new Map<string, PendingRequest>()\n private readonly subscriptions = new Map<string, SubscriptionRegistration>()\n private connectingPromise: Promise<WelcomeParams> | null = null\n private welcome: WelcomeParams | null = null\n private closed = false\n private reconnectAttempt = 0\n private reconnectAbort: AbortController | null = null\n\n constructor(config: ConnectionConfig) {\n this.config = config\n }\n\n on = this.emitter.on.bind(this.emitter)\n off = this.emitter.off.bind(this.emitter)\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.welcome !== null\n }\n\n /**\n * Idempotent. Returns the welcome payload once connected + authed.\n */\n async connect(): Promise<WelcomeParams> {\n if (this.closed) throw new ConnectionError(\"Connection is closed\")\n if (this.welcome && this.ws?.readyState === WebSocket.OPEN) return this.welcome\n if (this.connectingPromise) return this.connectingPromise\n\n this.connectingPromise = this.openAndAuth().finally(() => {\n this.connectingPromise = null\n })\n return this.connectingPromise\n }\n\n async call<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n options?: CallOptions,\n ): Promise<MethodResult<M>> {\n if (this.closed) {\n return Promise.reject(new DisconnectedError(\"Client closed\"))\n }\n // If WS isn't open, route reads through HTTP — saves the WS handshake\n // (~1s+) on cold start. Only customer-facing reads reach `call()`;\n // auth + subscription.cancel use `send()` directly. Subscriptions go\n // through `registerSubscription` which always opens WS.\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return this.config.httpClient.call(\n method as HttpMethodName,\n params as MethodParams<HttpMethodName>,\n options,\n ) as Promise<MethodResult<M>>\n }\n return this.send(method, params, options) as Promise<MethodResult<M>>\n }\n\n /**\n * Registers a subscription with the connection. The connection sends the\n * subscribe call, stores the registration for reconnect, and routes incoming\n * push events to the handler.\n */\n async registerSubscription<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n handlers: {\n onEvent: SubscriptionRegistration[\"onEvent\"]\n onClosed: SubscriptionRegistration[\"onClosed\"]\n onSnapshot: SubscriptionRegistration[\"onSnapshot\"]\n },\n options?: CallOptions,\n ): Promise<{ subId: string; snapshot: unknown }> {\n await this.connect()\n const result = (await this.send(method, params, options)) as { sub: string; snapshot: unknown }\n const registration: SubscriptionRegistration = {\n subId: result.sub,\n method,\n params,\n onEvent: handlers.onEvent,\n onClosed: handlers.onClosed,\n onSnapshot: handlers.onSnapshot,\n }\n this.subscriptions.set(result.sub, registration)\n return { subId: result.sub, snapshot: result.snapshot }\n }\n\n /**\n * Cancels a subscription server-side and removes the registration locally.\n */\n async cancelSubscription(subId: string): Promise<void> {\n const reg = this.subscriptions.get(subId)\n if (!reg) return\n this.subscriptions.delete(subId)\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n await this.send(\"subscription.cancel\" as MethodName, { sub: subId } as never)\n } catch {\n // Best-effort: even if server rejects, local cleanup is done.\n }\n }\n }\n\n async close(): Promise<void> {\n this.closed = true\n this.reconnectAbort?.abort()\n this.reconnectAbort = null\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(\"Connection closed by client\"))\n }\n this.pending.clear()\n this.subscriptions.clear()\n if (this.ws && this.ws.readyState <= WebSocket.OPEN) {\n this.ws.close(1000, \"client_close\")\n }\n this.ws = null\n this.welcome = null\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async openAndAuth(): Promise<WelcomeParams> {\n const ws = new WebSocket(this.config.baseUrl, [SUBPROTOCOL], {\n perMessageDeflate: this.config.compression\n ? { threshold: 1024 }\n : false,\n handshakeTimeout: 15_000,\n })\n this.ws = ws\n this.welcome = null\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup()\n resolve()\n }\n const onError = (err: Error) => {\n cleanup()\n reject(new ConnectionError(`Failed to open WebSocket: ${err.message}`))\n }\n const onClose = (code: number, reason: Buffer) => {\n cleanup()\n reject(new ConnectionError(`WebSocket closed before open (${code}): ${reason.toString()}`))\n }\n const cleanup = () => {\n ws.off(\"open\", onOpen)\n ws.off(\"error\", onError)\n ws.off(\"close\", onClose)\n }\n ws.once(\"open\", onOpen)\n ws.once(\"error\", onError)\n ws.once(\"close\", onClose)\n })\n\n // Attach long-lived listeners now that we're open.\n ws.on(\"message\", (data) => this.handleMessage(data))\n ws.on(\"close\", (code, reason) => this.handleClose(code, reason.toString()))\n ws.on(\"error\", (err) => this.handleSocketError(err))\n\n // Send auth as the first frame and await both the ack and the welcome.\n const welcome = await this.performAuth()\n this.welcome = welcome\n this.reconnectAttempt = 0\n this.emitter.emit(\"connected\", { welcome })\n\n // If this was a reconnect, resubscribe everything.\n if (this.subscriptions.size > 0) {\n await this.resubscribeAll()\n }\n return welcome\n }\n\n private async performAuth(): Promise<WelcomeParams> {\n const welcomePromise = new Promise<WelcomeParams>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new TimeoutError(\"Auth timed out waiting for welcome\"))\n }, this.config.authTimeoutMs)\n this.pendingWelcome = {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n }\n })\n\n const authAck = this.send(\"auth\" as MethodName, { apiKey: this.config.apiKey } as never).catch(\n (err: Error) => {\n // Surface auth-level error explicitly (server may close immediately).\n if (err instanceof MrDogeError) throw err\n throw new UnauthorizedError(`Authentication failed: ${err.message}`)\n },\n )\n\n await authAck\n return welcomePromise\n }\n\n /**\n * Set during `performAuth` so we can resolve when the `welcome` notification arrives.\n */\n private pendingWelcome: PendingRequest | null = null\n\n private send(\n method: string,\n params: unknown,\n options?: CallOptions,\n ): Promise<unknown> {\n if (options?.signal?.aborted) {\n return Promise.reject(new AbortError())\n }\n const ws = this.ws\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new DisconnectedError(\"Socket not open\"))\n }\n const id = String(this.nextRequestId++)\n const frame: RpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n }\n return new Promise((resolve, reject) => {\n const onAbort = () => {\n this.pending.delete(id)\n clearTimeout(timer)\n options!.signal!.removeEventListener(\"abort\", onAbort)\n reject(new AbortError())\n }\n const detachSignal = () => {\n options?.signal?.removeEventListener(\"abort\", onAbort)\n }\n const wrappedResolve = (val: unknown) => {\n detachSignal()\n resolve(val)\n }\n const wrappedReject = (err: Error) => {\n detachSignal()\n reject(err)\n }\n const timer = setTimeout(() => {\n this.pending.delete(id)\n detachSignal()\n reject(new TimeoutError(`Request \"${method}\" timed out after ${this.config.requestTimeoutMs}ms`))\n }, this.config.requestTimeoutMs)\n this.pending.set(id, { resolve: wrappedResolve, reject: wrappedReject, timer })\n options?.signal?.addEventListener(\"abort\", onAbort)\n try {\n ws.send(JSON.stringify(frame))\n } catch (err) {\n this.pending.delete(id)\n clearTimeout(timer)\n detachSignal()\n reject(new ConnectionError(`Failed to send frame: ${(err as Error).message}`))\n }\n })\n }\n\n private handleMessage(raw: RawData): void {\n let text: string\n if (typeof raw === \"string\") text = raw\n else if (Buffer.isBuffer(raw)) text = raw.toString(\"utf8\")\n else if (raw instanceof ArrayBuffer) text = Buffer.from(raw).toString(\"utf8\")\n else text = Buffer.concat(raw as Buffer[]).toString(\"utf8\")\n\n let frame: any\n try {\n frame = JSON.parse(text)\n } catch {\n // Drop unparseable frames — the protocol guarantees JSON.\n return\n }\n if (frame.jsonrpc !== \"2.0\") return\n\n // Response to a pending request?\n if (typeof frame.id === \"string\") {\n const p = this.pending.get(frame.id)\n if (!p) return\n this.pending.delete(frame.id)\n clearTimeout(p.timer)\n if (frame.error) {\n p.reject(rpcErrorToTyped(frame.error))\n } else {\n p.resolve(frame.result)\n }\n return\n }\n\n // Notification — `method` carries the event name.\n if (typeof frame.method === \"string\") {\n this.handleNotification(frame.method, frame.params)\n }\n }\n\n private handleNotification(method: string, params: unknown): void {\n if (method === \"welcome\") {\n const pending = this.pendingWelcome\n this.pendingWelcome = null\n if (pending) {\n clearTimeout(pending.timer)\n pending.resolve(params as WelcomeParams)\n }\n return\n }\n\n if (method === \"subscription.event\") {\n const p = params as SubscriptionEventParams\n const reg = this.subscriptions.get(p.sub)\n reg?.onEvent(p)\n return\n }\n\n if (method === \"subscription.closed\") {\n const p = params as SubscriptionClosedParams\n const reg = this.subscriptions.get(p.sub)\n if (reg) {\n this.subscriptions.delete(p.sub)\n reg.onClosed(p)\n }\n return\n }\n\n // Unknown notifications: ignore per the additive-future-changes rule.\n }\n\n private handleClose(code: number, reason: string): void {\n const wasConnected = this.welcome !== null\n this.welcome = null\n this.ws = null\n\n // Reject every in-flight request — they didn't complete.\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(`Connection closed (${code}): ${reason}`))\n }\n this.pending.clear()\n if (this.pendingWelcome) {\n clearTimeout(this.pendingWelcome.timer)\n this.pendingWelcome.reject(new DisconnectedError(`Connection closed during auth (${code})`))\n this.pendingWelcome = null\n }\n\n if (this.closed) return\n\n this.emitter.emit(\"disconnected\", { code, reason })\n\n if (TERMINAL_CLOSE_CODES.has(code)) {\n // Don't reconnect on terminal codes — let the caller surface it.\n this.closed = true\n return\n }\n\n if (wasConnected || this.subscriptions.size > 0) {\n // Try to reconnect.\n this.scheduleReconnect()\n }\n }\n\n private handleSocketError(_err: Error): void {\n // The \"close\" event always follows; let handleClose drive reconnection.\n }\n\n private async scheduleReconnect(): Promise<void> {\n if (this.closed) return\n if (this.reconnectAbort) return // already scheduled\n this.reconnectAbort = new AbortController()\n const signal = this.reconnectAbort.signal\n\n while (!this.closed && this.reconnectAttempt < this.config.maxReconnectAttempts) {\n this.reconnectAttempt += 1\n const delayMs = nextDelay(this.reconnectAttempt, this.config.reconnectBackoff)\n this.emitter.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs })\n try {\n await sleep(delayMs, signal)\n } catch {\n return // aborted\n }\n if (this.closed) return\n try {\n await this.openAndAuth()\n this.reconnectAbort = null\n return\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n this.closed = true\n this.reconnectAbort = null\n return\n }\n // Otherwise loop and try again with bigger backoff.\n }\n }\n this.reconnectAbort = null\n }\n\n private async resubscribeAll(): Promise<void> {\n const olds = Array.from(this.subscriptions.values())\n this.subscriptions.clear()\n for (const old of olds) {\n try {\n const result = (await this.send(old.method, old.params)) as {\n sub: string\n snapshot: unknown\n }\n old.subId = result.sub\n this.subscriptions.set(result.sub, old)\n old.onSnapshot(result.sub, result.snapshot)\n } catch (err) {\n old.onClosed({\n sub: old.subId,\n reason: \"internal_error\",\n message:\n err instanceof Error\n ? `Resubscribe failed: ${err.message}`\n : \"Resubscribe failed\",\n })\n }\n }\n }\n}\n\nexport { PROTOCOL_VERSION }\n","import type { ErrorCode, RpcError } from \"@mrdoge/protocol\"\n\n/**\n * Base class for every SDK-thrown error. Map by `instanceof` or by `code`.\n */\nexport class MrDogeError extends Error {\n readonly code: ErrorCode | \"connection_error\" | \"disconnected\" | \"timeout\" | \"aborted\" | \"unknown\"\n readonly data?: unknown\n\n constructor(\n code: MrDogeError[\"code\"],\n message: string,\n data?: unknown,\n ) {\n super(message)\n this.name = this.constructor.name\n this.code = code\n this.data = data\n }\n}\n\nexport class UnauthorizedError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unauthorized\", message, data)\n }\n}\n\nexport class ForbiddenError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"forbidden\", message, data)\n }\n}\n\nexport class NotFoundError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"not_found\", message, data)\n }\n}\n\nexport class ValidationError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"invalid_params\", message, data)\n }\n}\n\nexport class RateLimitError extends MrDogeError {\n readonly retryAfterMs: number\n readonly limit?: number\n readonly remaining?: number\n readonly resetAt?: Date\n\n constructor(message: string, data?: unknown) {\n super(\"rate_limited\", message, data)\n const d = (data ?? {}) as {\n retryAfterMs?: number\n limit?: number\n remaining?: number\n resetAt?: string\n }\n this.retryAfterMs = d.retryAfterMs ?? 0\n this.limit = d.limit\n this.remaining = d.remaining\n this.resetAt = d.resetAt ? new Date(d.resetAt) : undefined\n }\n}\n\nexport class SubscriptionLimitError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"subscription_limit_exceeded\", message, data)\n }\n}\n\nexport class ConnectionLimitError extends MrDogeError {\n readonly current?: number\n readonly max?: number\n\n constructor(message: string, data?: unknown) {\n super(\"connection_limit_exceeded\", message, data)\n const d = (data ?? {}) as { current?: number; max?: number }\n this.current = d.current\n this.max = d.max\n }\n}\n\nexport class UnavailableError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unavailable\", message, data)\n }\n}\n\nexport class InternalError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"internal_error\", message, data)\n }\n}\n\nexport class ProtocolError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"protocol_error\", message, data)\n }\n}\n\n/** Raised when the SDK can't reach or stay connected to the server. */\nexport class ConnectionError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"connection_error\", message, data)\n }\n}\n\n/** A request was in flight when the connection dropped. The caller should retry if safe. */\nexport class DisconnectedError extends MrDogeError {\n constructor(message = \"Connection dropped before response\", data?: unknown) {\n super(\"disconnected\", message, data)\n }\n}\n\nexport class TimeoutError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"timeout\", message, data)\n }\n}\n\n/**\n * Thrown when a request is aborted via the customer-supplied\n * `options.signal`. Matches `fetch` convention — `err.name === \"AbortError\"`.\n */\nexport class AbortError extends MrDogeError {\n constructor(message = \"Request aborted\") {\n super(\"aborted\", message)\n }\n}\n\nconst CODE_MAP: Record<ErrorCode, new (message: string, data?: unknown) => MrDogeError> = {\n invalid_request: ProtocolError,\n invalid_params: ValidationError,\n method_not_found: ProtocolError,\n unauthorized: UnauthorizedError,\n forbidden: ForbiddenError,\n not_found: NotFoundError,\n rate_limited: RateLimitError,\n subscription_limit_exceeded: SubscriptionLimitError,\n connection_limit_exceeded: ConnectionLimitError,\n unavailable: UnavailableError,\n internal_error: InternalError,\n protocol_error: ProtocolError,\n}\n\n/**\n * Convert a wire-format RpcError into the appropriate typed SDK error.\n */\nexport function rpcErrorToTyped(err: RpcError): MrDogeError {\n const Ctor = CODE_MAP[err.code]\n if (!Ctor) return new MrDogeError(\"unknown\", err.message, err.data)\n return new Ctor(err.message, err.data)\n}\n","/**\n * Tiny typed event emitter — avoids depending on Node's `events` module so\n * we can target browsers later without a polyfill.\n *\n * Listeners registered via `on` return an unsubscribe function for that\n * specific listener.\n */\nexport class Emitter<Events extends Record<string, any>> {\n private listeners = new Map<keyof Events, Set<(payload: any) => void>>()\n\n on<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): () => void {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(fn)\n return () => set!.delete(fn)\n }\n\n off<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): void {\n this.listeners.get(event)?.delete(fn)\n }\n\n emit<E extends keyof Events>(event: E, payload: Events[E]): void {\n const set = this.listeners.get(event)\n if (!set || set.size === 0) return\n for (const fn of [...set]) {\n try {\n fn(payload)\n } catch (err) {\n queueMicrotask(() => {\n throw err\n })\n }\n }\n }\n\n clear(): void {\n this.listeners.clear()\n }\n}\n","export interface BackoffConfig {\n minMs: number\n maxMs: number\n /** Jitter as a fraction of the computed delay (0.2 = ±20%). */\n jitter: number\n}\n\nexport const DEFAULT_BACKOFF: BackoffConfig = {\n minMs: 1_000,\n maxMs: 30_000,\n jitter: 0.2,\n}\n\n/**\n * Returns the delay (ms) for a given reconnect attempt (1-indexed). Capped\n * exponential growth with random jitter.\n */\nexport function nextDelay(attempt: number, cfg: BackoffConfig = DEFAULT_BACKOFF): number {\n const exp = Math.min(cfg.maxMs, cfg.minMs * 2 ** (attempt - 1))\n const jitter = exp * cfg.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(exp + jitter))\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"aborted\"))\n return\n }\n const t = setTimeout(resolve, ms)\n signal?.addEventListener(\"abort\", () => {\n clearTimeout(t)\n reject(new Error(\"aborted\"))\n })\n })\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Regions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"regions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"regions.list\">> {\n return this.conn.call(\n \"regions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Competitions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"competitions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"competitions.list\">> {\n return this.conn.call(\n \"competitions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Teams {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"teams.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.list\">> {\n return this.conn.call(\n \"teams.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n get(\n params: MethodParams<\"teams.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.get\">> {\n return this.conn.call(\n \"teams.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n form(\n params: MethodParams<\"teams.form\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.form\">> {\n return this.conn.call(\n \"teams.form\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type {\n SubscriptionEventParams,\n SubscriptionClosedReason,\n MethodResult,\n SubscriptionMethodName,\n PushEventsOf,\n} from \"@mrdoge/protocol\"\nimport type { Connection } from \"./connection\"\nimport { Emitter } from \"./internal/emitter\"\n\n/**\n * Maps each push event name to the typed `data` payload it carries.\n * Derived from the discriminated union in `@mrdoge/protocol`.\n */\ntype EventDataMap = {\n [E in SubscriptionEventParams as E[\"event\"]]: E[\"data\"]\n}\n\ntype SnapshotOf<M extends SubscriptionMethodName> = MethodResult<M> extends {\n snapshot: infer S\n}\n ? S\n : never\n\ntype SubEventMap<M extends SubscriptionMethodName> = {\n [E in PushEventsOf<M> & keyof EventDataMap]: EventDataMap[E]\n} & {\n snapshot: SnapshotOf<M>\n closed: { reason: SubscriptionClosedReason; message?: string }\n}\n\n/**\n * Sentinel subId used when the Subscription was constructed from an HTTP\n * cold-start snapshot before the WS subscribe response arrived. The real\n * subId replaces it via `_deliverSnapshot` once WS resolves.\n */\nexport const PENDING_SUB_ID = \"__pending_ws__\"\n\n/**\n * Handle returned by `mrdoge.matches.subscribe(...)` and `subscribeLive(...)`.\n *\n * Stable across reconnects: the underlying server-issued `sub` id may change,\n * but this handle and its listeners persist. On reconnect, the SDK refreshes\n * `snapshot` and emits a `snapshot` event so callers can replace their local\n * state.\n */\nexport class Subscription<M extends SubscriptionMethodName> {\n private readonly emitter = new Emitter<SubEventMap<M>>()\n private readonly connection: Connection\n private internalSubId: string\n private currentSnapshot: SnapshotOf<M>\n private cancelled = false\n /**\n * True when `cancel()` was called before the WS subscribe arrived (subId\n * still pending). Once WS resolves, `_deliverSnapshot` issues the\n * server-side cancel so we don't leak a registered subscription.\n */\n private pendingCancel = false\n\n /** @internal — constructed by the SDK, not by user code. */\n constructor(connection: Connection, subId: string, initialSnapshot: SnapshotOf<M>) {\n this.connection = connection\n this.internalSubId = subId\n this.currentSnapshot = initialSnapshot\n }\n\n /** The latest snapshot the server has emitted (initial, or post-reconnect). */\n get snapshot(): SnapshotOf<M> {\n return this.currentSnapshot\n }\n\n /** Current server-issued subscription id. Changes on reconnect. */\n get id(): string {\n return this.internalSubId\n }\n\n /**\n * Listen for a push event from this subscription. Returns an unsubscribe\n * function that removes only this listener.\n *\n * In addition to protocol push events, two synthetic events fire:\n * - `snapshot` — when a reconnect produced a fresh snapshot\n * - `closed` — when the server terminates the subscription (or cancel)\n */\n on<E extends keyof SubEventMap<M>>(\n event: E,\n fn: (payload: SubEventMap<M>[E]) => void,\n ): () => void {\n return this.emitter.on(event, fn)\n }\n\n /**\n * Cancel the subscription server-side. Idempotent — calling twice is safe.\n */\n async cancel(): Promise<void> {\n if (this.cancelled) return\n this.cancelled = true\n if (this.internalSubId === PENDING_SUB_ID) {\n // WS hasn't delivered the real subId yet — flag for cancellation when\n // it arrives. Don't await; `cancel()` returns immediately.\n this.pendingCancel = true\n this.emitter.clear()\n return\n }\n await this.connection.cancelSubscription(this.internalSubId)\n this.emitter.clear()\n }\n\n // ---------------------------------------------------------------------\n // Internal — invoked by Connection's routing layer.\n // ---------------------------------------------------------------------\n\n /** @internal */\n _deliverEvent(params: SubscriptionEventParams): void {\n if (this.cancelled) return\n this.emitter.emit(\n params.event as keyof SubEventMap<M>,\n params.data as SubEventMap<M>[keyof SubEventMap<M>],\n )\n }\n\n /** @internal */\n _deliverSnapshot(newSubId: string, snapshot: SnapshotOf<M>): void {\n this.internalSubId = newSubId\n // Customer cancelled while we were still waiting for WS. The server\n // registered the subscription anyway — release it now.\n if (this.pendingCancel) {\n this.pendingCancel = false\n this.connection.cancelSubscription(newSubId).catch(() => undefined)\n return\n }\n if (this.cancelled) return\n this.currentSnapshot = snapshot\n this.emitter.emit(\"snapshot\" as keyof SubEventMap<M>, snapshot as never)\n }\n\n /** @internal */\n _deliverClosed(reason: SubscriptionClosedReason, message?: string): void {\n if (this.cancelled) return\n this.cancelled = true\n this.emitter.emit(\n \"closed\" as keyof SubEventMap<M>,\n { reason, message } as never,\n )\n this.emitter.clear()\n }\n}\n","import type {\n MethodParams,\n MethodResult,\n SubscriptionEventParams,\n SubscriptionClosedParams,\n} from \"@mrdoge/protocol\"\nimport type { MrDogeHttpClient } from \"@mrdoge/http\"\nimport type { CallOptions, Connection } from \"../connection\"\nimport { Subscription, PENDING_SUB_ID } from \"../subscription\"\n\ninterface Defaults {\n locale?: string\n timezone?: string\n}\n\nexport class Matches {\n constructor(\n private readonly conn: Connection,\n private readonly defaults: Defaults,\n private readonly http: MrDogeHttpClient,\n ) {}\n\n list(\n params: MethodParams<\"matches.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.list\">> {\n return this.conn.call(\n \"matches.list\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n get(\n params: MethodParams<\"matches.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.get\">> {\n return this.conn.call(\n \"matches.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n trending(\n params: MethodParams<\"matches.trending\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.trending\">> {\n return this.conn.call(\n \"matches.trending\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n search(\n params: MethodParams<\"matches.search\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.search\">> {\n return this.conn.call(\n \"matches.search\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n async subscribeLive(\n params: MethodParams<\"matches.subscribeLive\"> = {},\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribeLive\">> {\n const merged = { locale: this.defaults.locale, ...params }\n\n // Race HTTP `matches.getLive` against the WS subscribe. HTTP returns from\n // the server-side Redis cache in ~50-150ms; the WS path pays the TCP +\n // TLS + auth handshake on cold start (~1.5s). Whichever lands first\n // populates `.snapshot`. The WS path always continues — it's the source\n // of `match.upd` / `match.del` deltas after the initial snapshot.\n let handle: Subscription<\"matches.subscribeLive\">\n\n const wsPromise = this.conn.registerSubscription(\n \"matches.subscribeLive\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n\n const httpPromise = this.http\n .call(\n \"matches.getLive\",\n merged as MethodParams<\"matches.getLive\">,\n options,\n )\n .then((snapshot) => ({ kind: \"http\" as const, snapshot }))\n\n type Winner =\n | { kind: \"http\"; snapshot: MethodResult<\"matches.getLive\"> }\n | { kind: \"ws\"; subId: string; snapshot: MethodResult<\"matches.subscribeLive\">[\"snapshot\"] }\n\n const wsRace: Promise<Winner> = wsPromise.then((r) => ({\n kind: \"ws\",\n subId: r.subId,\n snapshot: r.snapshot as MethodResult<\"matches.subscribeLive\">[\"snapshot\"],\n }))\n\n let winner: Winner\n try {\n winner = await Promise.race<Winner>([httpPromise, wsRace])\n } catch {\n // HTTP rejected before WS resolved. Fall back to WS alone.\n const ws = await wsPromise\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n ws.subId,\n ws.snapshot as never,\n )\n return handle\n }\n\n if (winner.kind === \"ws\") {\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n winner.subId,\n winner.snapshot as never,\n )\n return handle\n }\n\n // HTTP won — build the Subscription with the HTTP snapshot and a pending\n // subId. The WS subscribe is still in flight; when it resolves, the\n // onSnapshot handler (or our tail handler) delivers the real subId +\n // canonical snapshot. If WS fails outright, deliver `closed` so the\n // caller can react.\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n PENDING_SUB_ID,\n winner.snapshot as never,\n )\n wsPromise\n .then((r) => {\n handle._deliverSnapshot(r.subId, r.snapshot as never)\n })\n .catch((err) => {\n handle._deliverClosed(\n \"internal_error\",\n err instanceof Error ? err.message : String(err),\n )\n })\n return handle\n }\n\n async subscribe(\n params: MethodParams<\"matches.subscribe\">,\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribe\">> {\n const merged = { locale: this.defaults.locale, ...params }\n let handle: Subscription<\"matches.subscribe\">\n const { subId, snapshot } = await this.conn.registerSubscription(\n \"matches.subscribe\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n handle = new Subscription<\"matches.subscribe\">(this.conn, subId, snapshot as never)\n return handle\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nclass Picks {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.picks.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.picks.list\">> {\n return this.conn.call(\n \"ai.picks.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nclass Recommendations {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.recommendations.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.recommendations.list\">> {\n return this.conn.call(\n \"ai.recommendations.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nexport class Ai {\n readonly picks: Picks\n readonly recommendations: Recommendations\n\n constructor(conn: Connection, defaults: { locale?: string }) {\n this.picks = new Picks(conn, defaults)\n this.recommendations = new Recommendations(conn, defaults)\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\n/**\n * Server-side resource for minting short-lived auth tokens for client-side use.\n *\n * Typical use: customer's backend has the `sk_live_...` key and exposes an\n * HTTP route that mints tokens for their frontend (browser / React Native):\n *\n * ```ts\n * app.post(\"/api/mrdoge/token\", async (req, res) => {\n * const { token, expiresAt } = await mrdoge.tokens.create({ ttl: 600 })\n * res.json({ token, expiresAt })\n * })\n * ```\n *\n * The frontend uses these tokens with `@mrdoge/client` — the sk_live_... key\n * never leaves the backend.\n */\nexport class Tokens {\n constructor(private readonly conn: Connection) {}\n\n /**\n * Mint a short-lived JWT auth token.\n *\n * @param params.ttl Token lifetime in seconds. Default 600 (10 min).\n * Server-enforced bounds: min 60, max 86400 (24h).\n * @returns { token, expiresAt } — `token` is opaque to the customer; pass\n * it to `@mrdoge/client`. `expiresAt` is ISO-8601.\n */\n create(\n params: MethodParams<\"tokens.create\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"tokens.create\">> {\n return this.conn.call(\"tokens.create\", params, options)\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/connection.ts","../src/errors.ts","../src/internal/emitter.ts","../src/internal/backoff.ts","../src/resources/regions.ts","../src/resources/competitions.ts","../src/resources/teams.ts","../src/subscription.ts","../src/resources/matches.ts","../src/resources/ai.ts","../src/resources/tokens.ts"],"sourcesContent":["import { createHttpClient, type MrDogeHttpClient } from \"@mrdoge/http\"\nimport { Connection, DEFAULT_CONFIG, type ConnectionConfig, type ConnectionEvents } from \"./connection\"\nimport { type BackoffConfig } from \"./internal/backoff\"\nimport { Regions } from \"./resources/regions\"\nimport { Competitions } from \"./resources/competitions\"\nimport { Teams } from \"./resources/teams\"\nimport { Matches } from \"./resources/matches\"\nimport { Ai } from \"./resources/ai\"\nimport { Tokens } from \"./resources/tokens\"\n\nexport const DEFAULT_BASE_URL = \"wss://api.mrdoge.co/sdk/v1\"\n\n/**\n * Derive the HTTP gateway URL from the configured WS URL by swapping the\n * scheme. One `baseUrl` config drives both transports.\n */\nfunction wsToHttp(url: string): string {\n if (url.startsWith(\"wss://\")) return \"https://\" + url.slice(\"wss://\".length)\n if (url.startsWith(\"ws://\")) return \"http://\" + url.slice(\"ws://\".length)\n return url\n}\n\nexport interface MrDogeOptions {\n apiKey: string\n\n /** Override the server URL (e.g. for local dev). Defaults to production. */\n baseUrl?: string\n\n /** Default locale applied to every call; overridable per-call. */\n locale?: string\n\n /** Default timezone applied to every call; overridable per-call. */\n timezone?: string\n\n /** Request-level timeout in milliseconds. Default 10s. */\n requestTimeoutMs?: number\n\n /** Max reconnect attempts on transient disconnects. Default Infinity. */\n maxReconnectAttempts?: number\n\n /** Exponential backoff config for reconnects. */\n reconnectBackoff?: Partial<BackoffConfig>\n\n /**\n * Whether to negotiate `permessage-deflate` compression at the WS handshake.\n * Default `true`. Disable for CPU-constrained environments.\n */\n compression?: boolean\n}\n\n/**\n * Mr. Doge SDK entrypoint.\n *\n * ```ts\n * const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! })\n * const matches = await mrdoge.matches.list({ date: \"2026-05-12\" })\n * ```\n *\n * The constructor does not open a connection. The WebSocket is opened lazily\n * on the first method call and reused for the lifetime of the client.\n */\nexport class MrDoge {\n readonly regions: Regions\n readonly competitions: Competitions\n readonly teams: Teams\n readonly matches: Matches\n readonly ai: Ai\n readonly tokens: Tokens\n\n private readonly connection: Connection\n private readonly http: MrDogeHttpClient\n\n constructor(options: MrDogeOptions) {\n if (!options?.apiKey) throw new Error(\"MrDoge: `apiKey` is required\")\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL\n const requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs\n\n this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n })\n\n const config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl,\n apiKey: options.apiKey,\n httpClient: this.http,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs,\n maxReconnectAttempts:\n options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,\n reconnectBackoff: {\n ...DEFAULT_CONFIG.reconnectBackoff,\n ...options.reconnectBackoff,\n },\n compression: options.compression ?? DEFAULT_CONFIG.compression,\n }\n\n this.connection = new Connection(config)\n\n const defaults = { locale: options.locale, timezone: options.timezone }\n this.regions = new Regions(this.connection, defaults)\n this.competitions = new Competitions(this.connection, defaults)\n this.teams = new Teams(this.connection, defaults)\n this.matches = new Matches(this.connection, defaults, this.http)\n this.ai = new Ai(this.connection, defaults)\n this.tokens = new Tokens(this.connection)\n }\n\n /**\n * Listen to connection lifecycle events.\n */\n on<E extends keyof ConnectionEvents>(\n event: E,\n fn: (payload: ConnectionEvents[E]) => void,\n ): () => void {\n return this.connection.on(event, fn)\n }\n\n /**\n * Force-open the connection now instead of waiting for the first call.\n * Returns the welcome payload from the server.\n */\n async connect() {\n return this.connection.connect()\n }\n\n /**\n * Close the connection and cancel every active subscription. The client is\n * unusable after `close()`.\n */\n async close(): Promise<void> {\n await this.connection.close()\n }\n}\n","import WebSocket, { type RawData } from \"ws\"\nimport {\n PROTOCOL_VERSION,\n SUBPROTOCOL,\n type MethodName,\n type MethodParams,\n type MethodResult,\n type WelcomeParams,\n type SubscriptionEventParams,\n type SubscriptionClosedParams,\n type RpcRequest,\n} from \"@mrdoge/protocol\"\nimport type { HttpMethodName, MrDogeHttpClient } from \"@mrdoge/http\"\nimport {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\n\n/**\n * Per-call options accepted by every method that makes a request. Mirrors\n * the `fetch` convention so callers can plug in a standard `AbortController`.\n *\n * When `signal` fires, the in-flight request is dropped client-side and the\n * returned promise rejects with `AbortError` (`err.name === \"AbortError\"`).\n */\nexport interface CallOptions {\n signal?: AbortSignal\n}\n\n/**\n * Options for `listAll` cursor-walk helpers. `signal` aborts the in-flight\n * page; the helper rethrows the `AbortError`. `onPage` fires after every\n * page lands — pass it to stream partial results into your store while the\n * walk continues.\n */\nexport interface ListAllOptions<T> extends CallOptions {\n onPage?: (page: T[], accumulated: T[]) => void\n}\n\n// Terminal close codes — see PROTOCOL.md §10.\nconst TERMINAL_CLOSE_CODES = new Set([4001, 4002, 4003, 4029])\n\nexport interface ConnectionConfig {\n baseUrl: string\n apiKey: string\n /**\n * HTTP client used as the cold-start fast path. When `call()` fires\n * before the WebSocket is open, it routes through this client so reads\n * don't pay the WS handshake latency. Subscriptions still always use WS.\n */\n httpClient: MrDogeHttpClient\n /** Default locale applied to method params. Per-call overrides win. */\n locale?: string\n /** Default timezone applied to method params. Per-call overrides win. */\n timezone?: string\n requestTimeoutMs: number\n maxReconnectAttempts: number\n reconnectBackoff: BackoffConfig\n compression: boolean\n /** Auth must complete (auth ack + welcome) within this many ms. */\n authTimeoutMs: number\n}\n\nexport const DEFAULT_CONFIG: Omit<\n ConnectionConfig,\n \"apiKey\" | \"baseUrl\" | \"httpClient\"\n> = {\n requestTimeoutMs: 10_000,\n maxReconnectAttempts: Infinity,\n reconnectBackoff: DEFAULT_BACKOFF,\n compression: true,\n authTimeoutMs: 10_000,\n}\n\nexport interface ConnectionEvents {\n connected: { welcome: WelcomeParams }\n disconnected: { reason: string; code: number }\n reconnecting: { attempt: number; delayMs: number }\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * Active subscriptions tracked by the connection. The handle's `subId` is\n * mutable — it changes on reconnect when the server issues a fresh id.\n */\nexport interface SubscriptionRegistration {\n /** Current server-issued sub id. Changes on reconnect. */\n subId: string\n method: MethodName\n params: unknown\n onEvent: (event: SubscriptionEventParams) => void\n onClosed: (params: SubscriptionClosedParams) => void\n /** Called by the connection when a reconnect resubscribe produced a fresh snapshot. */\n onSnapshot: (newSubId: string, snapshot: unknown) => void\n}\n\n/**\n * Long-lived WebSocket connection with JSON-RPC dispatch and automatic\n * reconnection. Subscriptions are resubscribed transparently on reconnect.\n */\nexport class Connection {\n private readonly emitter = new Emitter<ConnectionEvents>()\n private readonly config: ConnectionConfig\n private ws: WebSocket | null = null\n private nextRequestId = 1\n private readonly pending = new Map<string, PendingRequest>()\n private readonly subscriptions = new Map<string, SubscriptionRegistration>()\n private connectingPromise: Promise<WelcomeParams> | null = null\n private welcome: WelcomeParams | null = null\n private closed = false\n private reconnectAttempt = 0\n private reconnectAbort: AbortController | null = null\n\n constructor(config: ConnectionConfig) {\n this.config = config\n }\n\n on = this.emitter.on.bind(this.emitter)\n off = this.emitter.off.bind(this.emitter)\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.welcome !== null\n }\n\n /**\n * Idempotent. Returns the welcome payload once connected + authed.\n */\n async connect(): Promise<WelcomeParams> {\n if (this.closed) throw new ConnectionError(\"Connection is closed\")\n if (this.welcome && this.ws?.readyState === WebSocket.OPEN) return this.welcome\n if (this.connectingPromise) return this.connectingPromise\n\n this.connectingPromise = this.openAndAuth().finally(() => {\n this.connectingPromise = null\n })\n return this.connectingPromise\n }\n\n async call<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n options?: CallOptions,\n ): Promise<MethodResult<M>> {\n if (this.closed) {\n return Promise.reject(new DisconnectedError(\"Client closed\"))\n }\n // If WS isn't open, route reads through HTTP — saves the WS handshake\n // (~1s+) on cold start. Only customer-facing reads reach `call()`;\n // auth + subscription.cancel use `send()` directly. Subscriptions go\n // through `registerSubscription` which always opens WS.\n if (this.ws?.readyState !== WebSocket.OPEN) {\n return this.config.httpClient.call(\n method as HttpMethodName,\n params as MethodParams<HttpMethodName>,\n options,\n ) as Promise<MethodResult<M>>\n }\n return this.send(method, params, options) as Promise<MethodResult<M>>\n }\n\n /**\n * Registers a subscription with the connection. The connection sends the\n * subscribe call, stores the registration for reconnect, and routes incoming\n * push events to the handler.\n */\n async registerSubscription<M extends MethodName>(\n method: M,\n params: MethodParams<M>,\n handlers: {\n onEvent: SubscriptionRegistration[\"onEvent\"]\n onClosed: SubscriptionRegistration[\"onClosed\"]\n onSnapshot: SubscriptionRegistration[\"onSnapshot\"]\n },\n options?: CallOptions,\n ): Promise<{ subId: string; snapshot: unknown }> {\n await this.connect()\n const result = (await this.send(method, params, options)) as { sub: string; snapshot: unknown }\n const registration: SubscriptionRegistration = {\n subId: result.sub,\n method,\n params,\n onEvent: handlers.onEvent,\n onClosed: handlers.onClosed,\n onSnapshot: handlers.onSnapshot,\n }\n this.subscriptions.set(result.sub, registration)\n return { subId: result.sub, snapshot: result.snapshot }\n }\n\n /**\n * Cancels a subscription server-side and removes the registration locally.\n */\n async cancelSubscription(subId: string): Promise<void> {\n const reg = this.subscriptions.get(subId)\n if (!reg) return\n this.subscriptions.delete(subId)\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n await this.send(\"subscription.cancel\" as MethodName, { sub: subId } as never)\n } catch {\n // Best-effort: even if server rejects, local cleanup is done.\n }\n }\n }\n\n async close(): Promise<void> {\n this.closed = true\n this.reconnectAbort?.abort()\n this.reconnectAbort = null\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(\"Connection closed by client\"))\n }\n this.pending.clear()\n this.subscriptions.clear()\n if (this.ws && this.ws.readyState <= WebSocket.OPEN) {\n this.ws.close(1000, \"client_close\")\n }\n this.ws = null\n this.welcome = null\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async openAndAuth(): Promise<WelcomeParams> {\n const ws = new WebSocket(this.config.baseUrl, [SUBPROTOCOL], {\n perMessageDeflate: this.config.compression\n ? { threshold: 1024 }\n : false,\n handshakeTimeout: 15_000,\n })\n this.ws = ws\n this.welcome = null\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup()\n resolve()\n }\n const onError = (err: Error) => {\n cleanup()\n reject(new ConnectionError(`Failed to open WebSocket: ${err.message}`))\n }\n const onClose = (code: number, reason: Buffer) => {\n cleanup()\n reject(new ConnectionError(`WebSocket closed before open (${code}): ${reason.toString()}`))\n }\n const cleanup = () => {\n ws.off(\"open\", onOpen)\n ws.off(\"error\", onError)\n ws.off(\"close\", onClose)\n }\n ws.once(\"open\", onOpen)\n ws.once(\"error\", onError)\n ws.once(\"close\", onClose)\n })\n\n // Attach long-lived listeners now that we're open.\n ws.on(\"message\", (data) => this.handleMessage(data))\n ws.on(\"close\", (code, reason) => this.handleClose(code, reason.toString()))\n ws.on(\"error\", (err) => this.handleSocketError(err))\n\n // Send auth as the first frame and await both the ack and the welcome.\n const welcome = await this.performAuth()\n this.welcome = welcome\n this.reconnectAttempt = 0\n this.emitter.emit(\"connected\", { welcome })\n\n // If this was a reconnect, resubscribe everything.\n if (this.subscriptions.size > 0) {\n await this.resubscribeAll()\n }\n return welcome\n }\n\n private async performAuth(): Promise<WelcomeParams> {\n const welcomePromise = new Promise<WelcomeParams>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new TimeoutError(\"Auth timed out waiting for welcome\"))\n }, this.config.authTimeoutMs)\n this.pendingWelcome = {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n }\n })\n\n const authAck = this.send(\"auth\" as MethodName, { apiKey: this.config.apiKey } as never).catch(\n (err: Error) => {\n // Surface auth-level error explicitly (server may close immediately).\n if (err instanceof MrDogeError) throw err\n throw new UnauthorizedError(`Authentication failed: ${err.message}`)\n },\n )\n\n await authAck\n return welcomePromise\n }\n\n /**\n * Set during `performAuth` so we can resolve when the `welcome` notification arrives.\n */\n private pendingWelcome: PendingRequest | null = null\n\n private send(\n method: string,\n params: unknown,\n options?: CallOptions,\n ): Promise<unknown> {\n if (options?.signal?.aborted) {\n return Promise.reject(new AbortError())\n }\n const ws = this.ws\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new DisconnectedError(\"Socket not open\"))\n }\n const id = String(this.nextRequestId++)\n const frame: RpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n }\n return new Promise((resolve, reject) => {\n const onAbort = () => {\n this.pending.delete(id)\n clearTimeout(timer)\n options!.signal!.removeEventListener(\"abort\", onAbort)\n reject(new AbortError())\n }\n const detachSignal = () => {\n options?.signal?.removeEventListener(\"abort\", onAbort)\n }\n const wrappedResolve = (val: unknown) => {\n detachSignal()\n resolve(val)\n }\n const wrappedReject = (err: Error) => {\n detachSignal()\n reject(err)\n }\n const timer = setTimeout(() => {\n this.pending.delete(id)\n detachSignal()\n reject(new TimeoutError(`Request \"${method}\" timed out after ${this.config.requestTimeoutMs}ms`))\n }, this.config.requestTimeoutMs)\n this.pending.set(id, { resolve: wrappedResolve, reject: wrappedReject, timer })\n options?.signal?.addEventListener(\"abort\", onAbort)\n try {\n ws.send(JSON.stringify(frame))\n } catch (err) {\n this.pending.delete(id)\n clearTimeout(timer)\n detachSignal()\n reject(new ConnectionError(`Failed to send frame: ${(err as Error).message}`))\n }\n })\n }\n\n private handleMessage(raw: RawData): void {\n let text: string\n if (typeof raw === \"string\") text = raw\n else if (Buffer.isBuffer(raw)) text = raw.toString(\"utf8\")\n else if (raw instanceof ArrayBuffer) text = Buffer.from(raw).toString(\"utf8\")\n else text = Buffer.concat(raw as Buffer[]).toString(\"utf8\")\n\n let frame: any\n try {\n frame = JSON.parse(text)\n } catch {\n // Drop unparseable frames — the protocol guarantees JSON.\n return\n }\n if (frame.jsonrpc !== \"2.0\") return\n\n // Response to a pending request?\n if (typeof frame.id === \"string\") {\n const p = this.pending.get(frame.id)\n if (!p) return\n this.pending.delete(frame.id)\n clearTimeout(p.timer)\n if (frame.error) {\n p.reject(rpcErrorToTyped(frame.error))\n } else {\n p.resolve(frame.result)\n }\n return\n }\n\n // Notification — `method` carries the event name.\n if (typeof frame.method === \"string\") {\n this.handleNotification(frame.method, frame.params)\n }\n }\n\n private handleNotification(method: string, params: unknown): void {\n if (method === \"welcome\") {\n const pending = this.pendingWelcome\n this.pendingWelcome = null\n if (pending) {\n clearTimeout(pending.timer)\n pending.resolve(params as WelcomeParams)\n }\n return\n }\n\n if (method === \"subscription.event\") {\n const p = params as SubscriptionEventParams\n const reg = this.subscriptions.get(p.sub)\n reg?.onEvent(p)\n return\n }\n\n if (method === \"subscription.closed\") {\n const p = params as SubscriptionClosedParams\n const reg = this.subscriptions.get(p.sub)\n if (reg) {\n this.subscriptions.delete(p.sub)\n reg.onClosed(p)\n }\n return\n }\n\n // Unknown notifications: ignore per the additive-future-changes rule.\n }\n\n private handleClose(code: number, reason: string): void {\n const wasConnected = this.welcome !== null\n this.welcome = null\n this.ws = null\n\n // Reject every in-flight request — they didn't complete.\n for (const [, p] of this.pending) {\n clearTimeout(p.timer)\n p.reject(new DisconnectedError(`Connection closed (${code}): ${reason}`))\n }\n this.pending.clear()\n if (this.pendingWelcome) {\n clearTimeout(this.pendingWelcome.timer)\n this.pendingWelcome.reject(new DisconnectedError(`Connection closed during auth (${code})`))\n this.pendingWelcome = null\n }\n\n if (this.closed) return\n\n this.emitter.emit(\"disconnected\", { code, reason })\n\n if (TERMINAL_CLOSE_CODES.has(code)) {\n // Don't reconnect on terminal codes — let the caller surface it.\n this.closed = true\n return\n }\n\n if (wasConnected || this.subscriptions.size > 0) {\n // Try to reconnect.\n this.scheduleReconnect()\n }\n }\n\n private handleSocketError(_err: Error): void {\n // The \"close\" event always follows; let handleClose drive reconnection.\n }\n\n private async scheduleReconnect(): Promise<void> {\n if (this.closed) return\n if (this.reconnectAbort) return // already scheduled\n this.reconnectAbort = new AbortController()\n const signal = this.reconnectAbort.signal\n\n while (!this.closed && this.reconnectAttempt < this.config.maxReconnectAttempts) {\n this.reconnectAttempt += 1\n const delayMs = nextDelay(this.reconnectAttempt, this.config.reconnectBackoff)\n this.emitter.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs })\n try {\n await sleep(delayMs, signal)\n } catch {\n return // aborted\n }\n if (this.closed) return\n try {\n await this.openAndAuth()\n this.reconnectAbort = null\n return\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n this.closed = true\n this.reconnectAbort = null\n return\n }\n // Otherwise loop and try again with bigger backoff.\n }\n }\n this.reconnectAbort = null\n }\n\n private async resubscribeAll(): Promise<void> {\n const olds = Array.from(this.subscriptions.values())\n this.subscriptions.clear()\n for (const old of olds) {\n try {\n const result = (await this.send(old.method, old.params)) as {\n sub: string\n snapshot: unknown\n }\n old.subId = result.sub\n this.subscriptions.set(result.sub, old)\n old.onSnapshot(result.sub, result.snapshot)\n } catch (err) {\n old.onClosed({\n sub: old.subId,\n reason: \"internal_error\",\n message:\n err instanceof Error\n ? `Resubscribe failed: ${err.message}`\n : \"Resubscribe failed\",\n })\n }\n }\n }\n}\n\nexport { PROTOCOL_VERSION }\n","import type { ErrorCode, RpcError } from \"@mrdoge/protocol\"\n\n/**\n * Base class for every SDK-thrown error. Map by `instanceof` or by `code`.\n */\nexport class MrDogeError extends Error {\n readonly code: ErrorCode | \"connection_error\" | \"disconnected\" | \"timeout\" | \"aborted\" | \"unknown\"\n readonly data?: unknown\n\n constructor(\n code: MrDogeError[\"code\"],\n message: string,\n data?: unknown,\n ) {\n super(message)\n this.name = this.constructor.name\n this.code = code\n this.data = data\n }\n}\n\nexport class UnauthorizedError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unauthorized\", message, data)\n }\n}\n\nexport class ForbiddenError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"forbidden\", message, data)\n }\n}\n\nexport class NotFoundError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"not_found\", message, data)\n }\n}\n\nexport class ValidationError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"invalid_params\", message, data)\n }\n}\n\nexport class RateLimitError extends MrDogeError {\n readonly retryAfterMs: number\n readonly limit?: number\n readonly remaining?: number\n readonly resetAt?: Date\n\n constructor(message: string, data?: unknown) {\n super(\"rate_limited\", message, data)\n const d = (data ?? {}) as {\n retryAfterMs?: number\n limit?: number\n remaining?: number\n resetAt?: string\n }\n this.retryAfterMs = d.retryAfterMs ?? 0\n this.limit = d.limit\n this.remaining = d.remaining\n this.resetAt = d.resetAt ? new Date(d.resetAt) : undefined\n }\n}\n\nexport class SubscriptionLimitError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"subscription_limit_exceeded\", message, data)\n }\n}\n\nexport class ConnectionLimitError extends MrDogeError {\n readonly current?: number\n readonly max?: number\n\n constructor(message: string, data?: unknown) {\n super(\"connection_limit_exceeded\", message, data)\n const d = (data ?? {}) as { current?: number; max?: number }\n this.current = d.current\n this.max = d.max\n }\n}\n\nexport class UnavailableError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"unavailable\", message, data)\n }\n}\n\nexport class InternalError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"internal_error\", message, data)\n }\n}\n\nexport class ProtocolError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"protocol_error\", message, data)\n }\n}\n\n/** Raised when the SDK can't reach or stay connected to the server. */\nexport class ConnectionError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"connection_error\", message, data)\n }\n}\n\n/** A request was in flight when the connection dropped. The caller should retry if safe. */\nexport class DisconnectedError extends MrDogeError {\n constructor(message = \"Connection dropped before response\", data?: unknown) {\n super(\"disconnected\", message, data)\n }\n}\n\nexport class TimeoutError extends MrDogeError {\n constructor(message: string, data?: unknown) {\n super(\"timeout\", message, data)\n }\n}\n\n/**\n * Thrown when a request is aborted via the customer-supplied\n * `options.signal`. Matches `fetch` convention — `err.name === \"AbortError\"`.\n */\nexport class AbortError extends MrDogeError {\n constructor(message = \"Request aborted\") {\n super(\"aborted\", message)\n }\n}\n\nconst CODE_MAP: Record<ErrorCode, new (message: string, data?: unknown) => MrDogeError> = {\n invalid_request: ProtocolError,\n invalid_params: ValidationError,\n method_not_found: ProtocolError,\n unauthorized: UnauthorizedError,\n forbidden: ForbiddenError,\n not_found: NotFoundError,\n rate_limited: RateLimitError,\n subscription_limit_exceeded: SubscriptionLimitError,\n connection_limit_exceeded: ConnectionLimitError,\n unavailable: UnavailableError,\n internal_error: InternalError,\n protocol_error: ProtocolError,\n}\n\n/**\n * Convert a wire-format RpcError into the appropriate typed SDK error.\n */\nexport function rpcErrorToTyped(err: RpcError): MrDogeError {\n const Ctor = CODE_MAP[err.code]\n if (!Ctor) return new MrDogeError(\"unknown\", err.message, err.data)\n return new Ctor(err.message, err.data)\n}\n","/**\n * Tiny typed event emitter — avoids depending on Node's `events` module so\n * we can target browsers later without a polyfill.\n *\n * Listeners registered via `on` return an unsubscribe function for that\n * specific listener.\n */\nexport class Emitter<Events extends Record<string, any>> {\n private listeners = new Map<keyof Events, Set<(payload: any) => void>>()\n\n on<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): () => void {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(fn)\n return () => set!.delete(fn)\n }\n\n off<E extends keyof Events>(event: E, fn: (payload: Events[E]) => void): void {\n this.listeners.get(event)?.delete(fn)\n }\n\n emit<E extends keyof Events>(event: E, payload: Events[E]): void {\n const set = this.listeners.get(event)\n if (!set || set.size === 0) return\n for (const fn of [...set]) {\n try {\n fn(payload)\n } catch (err) {\n queueMicrotask(() => {\n throw err\n })\n }\n }\n }\n\n clear(): void {\n this.listeners.clear()\n }\n}\n","export interface BackoffConfig {\n minMs: number\n maxMs: number\n /** Jitter as a fraction of the computed delay (0.2 = ±20%). */\n jitter: number\n}\n\nexport const DEFAULT_BACKOFF: BackoffConfig = {\n minMs: 1_000,\n maxMs: 30_000,\n jitter: 0.2,\n}\n\n/**\n * Returns the delay (ms) for a given reconnect attempt (1-indexed). Capped\n * exponential growth with random jitter.\n */\nexport function nextDelay(attempt: number, cfg: BackoffConfig = DEFAULT_BACKOFF): number {\n const exp = Math.min(cfg.maxMs, cfg.minMs * 2 ** (attempt - 1))\n const jitter = exp * cfg.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(exp + jitter))\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"aborted\"))\n return\n }\n const t = setTimeout(resolve, ms)\n signal?.addEventListener(\"abort\", () => {\n clearTimeout(t)\n reject(new Error(\"aborted\"))\n })\n })\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Regions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"regions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"regions.list\">> {\n return this.conn.call(\n \"regions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Competitions {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"competitions.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"competitions.list\">> {\n return this.conn.call(\n \"competitions.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\nexport class Teams {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"teams.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.list\">> {\n return this.conn.call(\n \"teams.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n get(\n params: MethodParams<\"teams.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.get\">> {\n return this.conn.call(\n \"teams.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n form(\n params: MethodParams<\"teams.form\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"teams.form\">> {\n return this.conn.call(\n \"teams.form\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n","import type {\n SubscriptionEventParams,\n SubscriptionClosedReason,\n MethodResult,\n SubscriptionMethodName,\n PushEventsOf,\n} from \"@mrdoge/protocol\"\nimport type { Connection } from \"./connection\"\nimport { Emitter } from \"./internal/emitter\"\n\n/**\n * Maps each push event name to the typed `data` payload it carries.\n * Derived from the discriminated union in `@mrdoge/protocol`.\n */\ntype EventDataMap = {\n [E in SubscriptionEventParams as E[\"event\"]]: E[\"data\"]\n}\n\ntype SnapshotOf<M extends SubscriptionMethodName> = MethodResult<M> extends {\n snapshot: infer S\n}\n ? S\n : never\n\ntype SubEventMap<M extends SubscriptionMethodName> = {\n [E in PushEventsOf<M> & keyof EventDataMap]: EventDataMap[E]\n} & {\n snapshot: SnapshotOf<M>\n closed: { reason: SubscriptionClosedReason; message?: string }\n}\n\n/**\n * Sentinel subId used when the Subscription was constructed from an HTTP\n * cold-start snapshot before the WS subscribe response arrived. The real\n * subId replaces it via `_deliverSnapshot` once WS resolves.\n */\nexport const PENDING_SUB_ID = \"__pending_ws__\"\n\n/**\n * Handle returned by `mrdoge.matches.subscribe(...)` and `subscribeLive(...)`.\n *\n * Stable across reconnects: the underlying server-issued `sub` id may change,\n * but this handle and its listeners persist. On reconnect, the SDK refreshes\n * `snapshot` and emits a `snapshot` event so callers can replace their local\n * state.\n */\nexport class Subscription<M extends SubscriptionMethodName> {\n private readonly emitter = new Emitter<SubEventMap<M>>()\n private readonly connection: Connection\n private internalSubId: string\n private currentSnapshot: SnapshotOf<M>\n private cancelled = false\n /**\n * True when `cancel()` was called before the WS subscribe arrived (subId\n * still pending). Once WS resolves, `_deliverSnapshot` issues the\n * server-side cancel so we don't leak a registered subscription.\n */\n private pendingCancel = false\n\n /** @internal — constructed by the SDK, not by user code. */\n constructor(connection: Connection, subId: string, initialSnapshot: SnapshotOf<M>) {\n this.connection = connection\n this.internalSubId = subId\n this.currentSnapshot = initialSnapshot\n }\n\n /** The latest snapshot the server has emitted (initial, or post-reconnect). */\n get snapshot(): SnapshotOf<M> {\n return this.currentSnapshot\n }\n\n /** Current server-issued subscription id. Changes on reconnect. */\n get id(): string {\n return this.internalSubId\n }\n\n /**\n * Listen for a push event from this subscription. Returns an unsubscribe\n * function that removes only this listener.\n *\n * In addition to protocol push events, two synthetic events fire:\n * - `snapshot` — when a reconnect produced a fresh snapshot\n * - `closed` — when the server terminates the subscription (or cancel)\n */\n on<E extends keyof SubEventMap<M>>(\n event: E,\n fn: (payload: SubEventMap<M>[E]) => void,\n ): () => void {\n return this.emitter.on(event, fn)\n }\n\n /**\n * Cancel the subscription server-side. Idempotent — calling twice is safe.\n */\n async cancel(): Promise<void> {\n if (this.cancelled) return\n this.cancelled = true\n if (this.internalSubId === PENDING_SUB_ID) {\n // WS hasn't delivered the real subId yet — flag for cancellation when\n // it arrives. Don't await; `cancel()` returns immediately.\n this.pendingCancel = true\n this.emitter.clear()\n return\n }\n await this.connection.cancelSubscription(this.internalSubId)\n this.emitter.clear()\n }\n\n // ---------------------------------------------------------------------\n // Internal — invoked by Connection's routing layer.\n // ---------------------------------------------------------------------\n\n /** @internal */\n _deliverEvent(params: SubscriptionEventParams): void {\n if (this.cancelled) return\n this.emitter.emit(\n params.event as keyof SubEventMap<M>,\n params.data as SubEventMap<M>[keyof SubEventMap<M>],\n )\n }\n\n /** @internal */\n _deliverSnapshot(newSubId: string, snapshot: SnapshotOf<M>): void {\n this.internalSubId = newSubId\n // Customer cancelled while we were still waiting for WS. The server\n // registered the subscription anyway — release it now.\n if (this.pendingCancel) {\n this.pendingCancel = false\n this.connection.cancelSubscription(newSubId).catch(() => undefined)\n return\n }\n if (this.cancelled) return\n this.currentSnapshot = snapshot\n this.emitter.emit(\"snapshot\" as keyof SubEventMap<M>, snapshot as never)\n }\n\n /** @internal */\n _deliverClosed(reason: SubscriptionClosedReason, message?: string): void {\n if (this.cancelled) return\n this.cancelled = true\n this.emitter.emit(\n \"closed\" as keyof SubEventMap<M>,\n { reason, message } as never,\n )\n this.emitter.clear()\n }\n}\n","import type {\n Match,\n MethodParams,\n MethodResult,\n SubscriptionEventParams,\n SubscriptionClosedParams,\n} from \"@mrdoge/protocol\"\nimport type { MrDogeHttpClient } from \"@mrdoge/http\"\nimport type { CallOptions, Connection, ListAllOptions } from \"../connection\"\nimport { Subscription, PENDING_SUB_ID } from \"../subscription\"\n\ninterface Defaults {\n locale?: string\n timezone?: string\n}\n\nexport class Matches {\n constructor(\n private readonly conn: Connection,\n private readonly defaults: Defaults,\n private readonly http: MrDogeHttpClient,\n ) {}\n\n list(\n params: MethodParams<\"matches.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.list\">> {\n return this.conn.call(\n \"matches.list\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n /**\n * Walk every page of `matches.list` and return one combined array. The\n * helper drives the cursor for you — pass everything except `cursor`,\n * including `limit` for page size. AbortSignal aborts the whole walk.\n * `onPage` fires after each page for progressive rendering.\n *\n * Server-side keyset cursor pagination keeps the walk drift-safe (no\n * duplicate or missed IDs across page boundaries even when the underlying\n * set shifts mid-walk).\n */\n async listAll(\n params: Omit<MethodParams<\"matches.list\">, \"cursor\"> = {},\n options?: ListAllOptions<Match>,\n ): Promise<Match[]> {\n const { onPage, ...callOptions } = options ?? {}\n const result: Match[] = []\n let cursor: string | undefined\n do {\n const page = await this.list({ ...params, cursor }, callOptions)\n const pageData = page.data as Match[]\n result.push(...pageData)\n onPage?.(pageData, result)\n cursor = page.pagination.nextCursor ?? undefined\n } while (cursor)\n return result\n }\n\n get(\n params: MethodParams<\"matches.get\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.get\">> {\n return this.conn.call(\n \"matches.get\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n trending(\n params: MethodParams<\"matches.trending\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.trending\">> {\n return this.conn.call(\n \"matches.trending\",\n {\n locale: this.defaults.locale,\n timezone: this.defaults.timezone,\n ...params,\n },\n options,\n )\n }\n\n search(\n params: MethodParams<\"matches.search\">,\n options?: CallOptions,\n ): Promise<MethodResult<\"matches.search\">> {\n return this.conn.call(\n \"matches.search\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n async subscribeLive(\n params: MethodParams<\"matches.subscribeLive\"> = {},\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribeLive\">> {\n const merged = { locale: this.defaults.locale, ...params }\n\n // Race HTTP `matches.getLive` against the WS subscribe. HTTP returns from\n // the server-side Redis cache in ~50-150ms; the WS path pays the TCP +\n // TLS + auth handshake on cold start (~1.5s). Whichever lands first\n // populates `.snapshot`. The WS path always continues — it's the source\n // of `match.upd` / `match.del` deltas after the initial snapshot.\n let handle: Subscription<\"matches.subscribeLive\">\n\n const wsPromise = this.conn.registerSubscription(\n \"matches.subscribeLive\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n\n const httpPromise = this.http\n .call(\n \"matches.getLive\",\n merged as MethodParams<\"matches.getLive\">,\n options,\n )\n .then((snapshot) => ({ kind: \"http\" as const, snapshot }))\n\n type Winner =\n | { kind: \"http\"; snapshot: MethodResult<\"matches.getLive\"> }\n | { kind: \"ws\"; subId: string; snapshot: MethodResult<\"matches.subscribeLive\">[\"snapshot\"] }\n\n const wsRace: Promise<Winner> = wsPromise.then((r) => ({\n kind: \"ws\",\n subId: r.subId,\n snapshot: r.snapshot as MethodResult<\"matches.subscribeLive\">[\"snapshot\"],\n }))\n\n let winner: Winner\n try {\n winner = await Promise.race<Winner>([httpPromise, wsRace])\n } catch {\n // HTTP rejected before WS resolved. Fall back to WS alone.\n const ws = await wsPromise\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n ws.subId,\n ws.snapshot as never,\n )\n return handle\n }\n\n if (winner.kind === \"ws\") {\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n winner.subId,\n winner.snapshot as never,\n )\n return handle\n }\n\n // HTTP won — build the Subscription with the HTTP snapshot and a pending\n // subId. The WS subscribe is still in flight; when it resolves, the\n // onSnapshot handler (or our tail handler) delivers the real subId +\n // canonical snapshot. If WS fails outright, deliver `closed` so the\n // caller can react.\n handle = new Subscription<\"matches.subscribeLive\">(\n this.conn,\n PENDING_SUB_ID,\n winner.snapshot as never,\n )\n wsPromise\n .then((r) => {\n handle._deliverSnapshot(r.subId, r.snapshot as never)\n })\n .catch((err) => {\n handle._deliverClosed(\n \"internal_error\",\n err instanceof Error ? err.message : String(err),\n )\n })\n return handle\n }\n\n async subscribe(\n params: MethodParams<\"matches.subscribe\">,\n options?: CallOptions,\n ): Promise<Subscription<\"matches.subscribe\">> {\n const merged = { locale: this.defaults.locale, ...params }\n let handle: Subscription<\"matches.subscribe\">\n const { subId, snapshot } = await this.conn.registerSubscription(\n \"matches.subscribe\",\n merged,\n {\n onEvent: (event: SubscriptionEventParams) => handle?._deliverEvent(event),\n onClosed: (p: SubscriptionClosedParams) => handle?._deliverClosed(p.reason, p.message),\n onSnapshot: (newSubId: string, newSnap: unknown) =>\n handle?._deliverSnapshot(newSubId, newSnap as never),\n },\n options,\n )\n handle = new Subscription<\"matches.subscribe\">(this.conn, subId, snapshot as never)\n return handle\n }\n}\n","import type { AiPick, MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection, ListAllOptions } from \"../connection\"\n\nclass Picks {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.picks.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.picks.list\">> {\n return this.conn.call(\n \"ai.picks.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n\n /**\n * Walk every page of `ai.picks.list` and return one combined array. Same\n * shape as `matches.listAll`. Server-side keyset pagination keeps the\n * walk drift-safe.\n */\n async listAll(\n params: Omit<MethodParams<\"ai.picks.list\">, \"cursor\"> = {},\n options?: ListAllOptions<AiPick>,\n ): Promise<AiPick[]> {\n const { onPage, ...callOptions } = options ?? {}\n const result: AiPick[] = []\n let cursor: string | undefined\n do {\n const page = await this.list({ ...params, cursor }, callOptions)\n const pageData = page.data as AiPick[]\n result.push(...pageData)\n onPage?.(pageData, result)\n cursor = page.pagination.nextCursor ?? undefined\n } while (cursor)\n return result\n }\n}\n\nclass Recommendations {\n constructor(private readonly conn: Connection, private readonly defaults: { locale?: string }) {}\n\n list(\n params: MethodParams<\"ai.recommendations.list\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"ai.recommendations.list\">> {\n return this.conn.call(\n \"ai.recommendations.list\",\n { locale: this.defaults.locale, ...params },\n options,\n )\n }\n}\n\nexport class Ai {\n readonly picks: Picks\n readonly recommendations: Recommendations\n\n constructor(conn: Connection, defaults: { locale?: string }) {\n this.picks = new Picks(conn, defaults)\n this.recommendations = new Recommendations(conn, defaults)\n }\n}\n","import type { MethodParams, MethodResult } from \"@mrdoge/protocol\"\nimport type { CallOptions, Connection } from \"../connection\"\n\n/**\n * Server-side resource for minting short-lived auth tokens for client-side use.\n *\n * Typical use: customer's backend has the `sk_live_...` key and exposes an\n * HTTP route that mints tokens for their frontend (browser / React Native):\n *\n * ```ts\n * app.post(\"/api/mrdoge/token\", async (req, res) => {\n * const { token, expiresAt } = await mrdoge.tokens.create({ ttl: 600 })\n * res.json({ token, expiresAt })\n * })\n * ```\n *\n * The frontend uses these tokens with `@mrdoge/client` — the sk_live_... key\n * never leaves the backend.\n */\nexport class Tokens {\n constructor(private readonly conn: Connection) {}\n\n /**\n * Mint a short-lived JWT auth token.\n *\n * @param params.ttl Token lifetime in seconds. Default 600 (10 min).\n * Server-enforced bounds: min 60, max 86400 (24h).\n * @returns { token, expiresAt } — `token` is opaque to the customer; pass\n * it to `@mrdoge/client`. `expiresAt` is ISO-8601.\n */\n create(\n params: MethodParams<\"tokens.create\"> = {},\n options?: CallOptions,\n ): Promise<MethodResult<\"tokens.create\">> {\n return this.conn.call(\"tokens.create\", params, options)\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrdoge/node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Mr. Doge Node SDK — server-side WebSocket + HTTP client. Authenticate with an `sk_live_...` API key and stream live sports data.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/mrdogeco/sdk/tree/main/packages/node",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"ws": "^8.18.0",
|
|
40
40
|
"zod": "^3.23.0",
|
|
41
|
-
"@mrdoge/http": "0.1.
|
|
42
|
-
"@mrdoge/protocol": "0.1.
|
|
41
|
+
"@mrdoge/http": "0.1.2",
|
|
42
|
+
"@mrdoge/protocol": "0.1.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^20.14.0",
|