@mrdoge/node 0.1.0 → 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 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,10 +19,24 @@ interface BackoffConfig {
19
19
  interface CallOptions {
20
20
  signal?: AbortSignal;
21
21
  }
22
-
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
+ }
23
31
  interface ConnectionConfig {
24
32
  baseUrl: string;
25
33
  apiKey: string;
34
+ /**
35
+ * HTTP client used as the cold-start fast path. When `call()` fires
36
+ * before the WebSocket is open, it routes through this client so reads
37
+ * don't pay the WS handshake latency. Subscriptions still always use WS.
38
+ */
39
+ httpClient: MrDogeHttpClient;
26
40
  /** Default locale applied to method params. Per-call overrides win. */
27
41
  locale?: string;
28
42
  /** Default timezone applied to method params. Per-call overrides win. */
@@ -224,6 +238,17 @@ declare class Matches {
224
238
  private readonly http;
225
239
  constructor(conn: Connection, defaults: Defaults, http: MrDogeHttpClient);
226
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[]>;
227
252
  get(params: MethodParams<"matches.get">, options?: CallOptions): Promise<MethodResult<"matches.get">>;
228
253
  trending(params?: MethodParams<"matches.trending">, options?: CallOptions): Promise<MethodResult<"matches.trending">>;
229
254
  search(params: MethodParams<"matches.search">, options?: CallOptions): Promise<MethodResult<"matches.search">>;
@@ -238,6 +263,12 @@ declare class Picks {
238
263
  locale?: string;
239
264
  });
240
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[]>;
241
272
  }
242
273
  declare class Recommendations {
243
274
  private readonly conn;
@@ -414,4 +445,4 @@ declare class AbortError extends MrDogeError {
414
445
  constructor(message?: string);
415
446
  }
416
447
 
417
- 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,10 +19,24 @@ interface BackoffConfig {
19
19
  interface CallOptions {
20
20
  signal?: AbortSignal;
21
21
  }
22
-
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
+ }
23
31
  interface ConnectionConfig {
24
32
  baseUrl: string;
25
33
  apiKey: string;
34
+ /**
35
+ * HTTP client used as the cold-start fast path. When `call()` fires
36
+ * before the WebSocket is open, it routes through this client so reads
37
+ * don't pay the WS handshake latency. Subscriptions still always use WS.
38
+ */
39
+ httpClient: MrDogeHttpClient;
26
40
  /** Default locale applied to method params. Per-call overrides win. */
27
41
  locale?: string;
28
42
  /** Default timezone applied to method params. Per-call overrides win. */
@@ -224,6 +238,17 @@ declare class Matches {
224
238
  private readonly http;
225
239
  constructor(conn: Connection, defaults: Defaults, http: MrDogeHttpClient);
226
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[]>;
227
252
  get(params: MethodParams<"matches.get">, options?: CallOptions): Promise<MethodResult<"matches.get">>;
228
253
  trending(params?: MethodParams<"matches.trending">, options?: CallOptions): Promise<MethodResult<"matches.trending">>;
229
254
  search(params: MethodParams<"matches.search">, options?: CallOptions): Promise<MethodResult<"matches.search">>;
@@ -238,6 +263,12 @@ declare class Picks {
238
263
  locale?: string;
239
264
  });
240
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[]>;
241
272
  }
242
273
  declare class Recommendations {
243
274
  private readonly conn;
@@ -414,4 +445,4 @@ declare class AbortError extends MrDogeError {
414
445
  constructor(message?: string);
415
446
  }
416
447
 
417
- 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
@@ -273,7 +273,16 @@ var Connection = class {
273
273
  return this.connectingPromise;
274
274
  }
275
275
  async call(method, params, options) {
276
- await this.connect();
276
+ if (this.closed) {
277
+ return Promise.reject(new DisconnectedError("Client closed"));
278
+ }
279
+ if (this.ws?.readyState !== import_ws.default.OPEN) {
280
+ return this.config.httpClient.call(
281
+ method,
282
+ params,
283
+ options
284
+ );
285
+ }
277
286
  return this.send(method, params, options);
278
287
  }
279
288
  /**
@@ -747,6 +756,29 @@ var Matches = class {
747
756
  options
748
757
  );
749
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
+ }
750
782
  get(params, options) {
751
783
  return this.conn.call(
752
784
  "matches.get",
@@ -863,6 +895,24 @@ var Picks = class {
863
895
  options
864
896
  );
865
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
+ }
866
916
  };
867
917
  var Recommendations = class {
868
918
  constructor(conn, defaults) {
@@ -925,13 +975,23 @@ var MrDoge = class {
925
975
  http;
926
976
  constructor(options) {
927
977
  if (!options?.apiKey) throw new Error("MrDoge: `apiKey` is required");
978
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
979
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs;
980
+ this.http = (0, import_http.createHttpClient)({
981
+ apiKey: options.apiKey,
982
+ baseUrl: wsToHttp(baseUrl),
983
+ locale: options.locale,
984
+ timezone: options.timezone,
985
+ requestTimeoutMs
986
+ });
928
987
  const config = {
929
988
  ...DEFAULT_CONFIG,
930
- baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
989
+ baseUrl,
931
990
  apiKey: options.apiKey,
991
+ httpClient: this.http,
932
992
  locale: options.locale,
933
993
  timezone: options.timezone,
934
- requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs,
994
+ requestTimeoutMs,
935
995
  maxReconnectAttempts: options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,
936
996
  reconnectBackoff: {
937
997
  ...DEFAULT_CONFIG.reconnectBackoff,
@@ -940,13 +1000,6 @@ var MrDoge = class {
940
1000
  compression: options.compression ?? DEFAULT_CONFIG.compression
941
1001
  };
942
1002
  this.connection = new Connection(config);
943
- this.http = (0, import_http.createHttpClient)({
944
- apiKey: options.apiKey,
945
- baseUrl: wsToHttp(config.baseUrl),
946
- locale: options.locale,
947
- timezone: options.timezone,
948
- requestTimeoutMs: config.requestTimeoutMs
949
- });
950
1003
  const defaults = { locale: options.locale, timezone: options.timezone };
951
1004
  this.regions = new Regions(this.connection, defaults);
952
1005
  this.competitions = new Competitions(this.connection, 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 config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_CONFIG.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 this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(config.baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs: config.requestTimeoutMs,\n })\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 {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\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}\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\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 /** 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<ConnectionConfig, \"apiKey\" | \"baseUrl\"> = {\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 await this.connect()\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
@@ -223,7 +223,16 @@ var Connection = class {
223
223
  return this.connectingPromise;
224
224
  }
225
225
  async call(method, params, options) {
226
- await this.connect();
226
+ if (this.closed) {
227
+ return Promise.reject(new DisconnectedError("Client closed"));
228
+ }
229
+ if (this.ws?.readyState !== WebSocket.OPEN) {
230
+ return this.config.httpClient.call(
231
+ method,
232
+ params,
233
+ options
234
+ );
235
+ }
227
236
  return this.send(method, params, options);
228
237
  }
229
238
  /**
@@ -697,6 +706,29 @@ var Matches = class {
697
706
  options
698
707
  );
699
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
+ }
700
732
  get(params, options) {
701
733
  return this.conn.call(
702
734
  "matches.get",
@@ -813,6 +845,24 @@ var Picks = class {
813
845
  options
814
846
  );
815
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
+ }
816
866
  };
817
867
  var Recommendations = class {
818
868
  constructor(conn, defaults) {
@@ -875,13 +925,23 @@ var MrDoge = class {
875
925
  http;
876
926
  constructor(options) {
877
927
  if (!options?.apiKey) throw new Error("MrDoge: `apiKey` is required");
928
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
929
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs;
930
+ this.http = createHttpClient({
931
+ apiKey: options.apiKey,
932
+ baseUrl: wsToHttp(baseUrl),
933
+ locale: options.locale,
934
+ timezone: options.timezone,
935
+ requestTimeoutMs
936
+ });
878
937
  const config = {
879
938
  ...DEFAULT_CONFIG,
880
- baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
939
+ baseUrl,
881
940
  apiKey: options.apiKey,
941
+ httpClient: this.http,
882
942
  locale: options.locale,
883
943
  timezone: options.timezone,
884
- requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_CONFIG.requestTimeoutMs,
944
+ requestTimeoutMs,
885
945
  maxReconnectAttempts: options.maxReconnectAttempts ?? DEFAULT_CONFIG.maxReconnectAttempts,
886
946
  reconnectBackoff: {
887
947
  ...DEFAULT_CONFIG.reconnectBackoff,
@@ -890,13 +950,6 @@ var MrDoge = class {
890
950
  compression: options.compression ?? DEFAULT_CONFIG.compression
891
951
  };
892
952
  this.connection = new Connection(config);
893
- this.http = createHttpClient({
894
- apiKey: options.apiKey,
895
- baseUrl: wsToHttp(config.baseUrl),
896
- locale: options.locale,
897
- timezone: options.timezone,
898
- requestTimeoutMs: config.requestTimeoutMs
899
- });
900
953
  const defaults = { locale: options.locale, timezone: options.timezone };
901
954
  this.regions = new Regions(this.connection, defaults);
902
955
  this.competitions = new Competitions(this.connection, defaults);
@@ -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 config: ConnectionConfig = {\n ...DEFAULT_CONFIG,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_CONFIG.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 this.http = createHttpClient({\n apiKey: options.apiKey,\n baseUrl: wsToHttp(config.baseUrl),\n locale: options.locale,\n timezone: options.timezone,\n requestTimeoutMs: config.requestTimeoutMs,\n })\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 {\n AbortError,\n ConnectionError,\n DisconnectedError,\n ProtocolError,\n TimeoutError,\n UnauthorizedError,\n rpcErrorToTyped,\n MrDogeError,\n} from \"./errors\"\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}\nimport { Emitter } from \"./internal/emitter\"\nimport { DEFAULT_BACKOFF, type BackoffConfig, nextDelay, sleep } from \"./internal/backoff\"\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 /** 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<ConnectionConfig, \"apiKey\" | \"baseUrl\"> = {\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 await this.connect()\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.0",
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.0",
42
- "@mrdoge/protocol": "0.1.0"
41
+ "@mrdoge/http": "0.1.2",
42
+ "@mrdoge/protocol": "0.1.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^20.14.0",