@sensiblestats/widget-sdk 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @sensiblestats/widget-sdk
2
2
 
3
+ ## 0.33.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Adds a Today tab showing live and today's fixtures grouped by competition, and makes the tab
8
+ strip content-driven: Chat, Today, Following and Odds each render only when they have something.
9
+ The `tabMatches` UI string is renamed `tabFollowing`.
10
+
3
11
  ## 0.32.0
4
12
 
5
13
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -166,6 +166,26 @@ async function postMarketOdds(cfg, matchId, marketDeveloperName) {
166
166
  if (!res.ok) throw new Error(`live-monitor/market ${res.status}`);
167
167
  return await res.json();
168
168
  }
169
+ async function postSchedule(cfg, localDate, utcOffsetMinutes) {
170
+ const res = await cfg.fetch(endpoint(cfg, "live-monitor/schedule"), {
171
+ method: "POST",
172
+ headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
173
+ body: JSON.stringify({ localDate, utcOffsetMinutes })
174
+ });
175
+ if (res.status === 404) return null;
176
+ if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`);
177
+ return await res.json();
178
+ }
179
+ async function postStates(cfg, matchIds) {
180
+ const res = await cfg.fetch(endpoint(cfg, "live-monitor/states"), {
181
+ method: "POST",
182
+ headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
183
+ body: JSON.stringify({ matchIds })
184
+ });
185
+ if (res.status === 404) return null;
186
+ if (!res.ok) throw new Error(`live-monitor/states ${res.status}`);
187
+ return await res.json();
188
+ }
169
189
 
170
190
  // src/ndjson.ts
171
191
  function parseLine(line) {
@@ -378,6 +398,12 @@ var Conversation = class {
378
398
  getMarketOdds(matchId, marketDeveloperName) {
379
399
  return postMarketOdds(this.cfg, matchId, marketDeveloperName);
380
400
  }
401
+ getSchedule(localDate, utcOffsetMinutes) {
402
+ return postSchedule(this.cfg, localDate, utcOffsetMinutes);
403
+ }
404
+ getStates(matchIds) {
405
+ return postStates(this.cfg, matchIds);
406
+ }
381
407
  };
382
408
 
383
409
  // src/eventLog.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export { StatsWidgetClient } from './client'\nexport { Conversation } from './conversation'\nexport type { ChatCallbacks, ChatHandle } from './chat'\nexport { SIGNAL_TYPE_CODES, ENTITY_TYPE_CODES } from './signals'\nexport {\n WidgetSdkError, AuthError, ForbiddenError, RateLimitError, UpstreamError, NetworkError, ParseError,\n} from './errors'\nexport type {\n StatsWidgetClientOptions, FetchLike, UserContext, ChatInput, ChatGrounding,\n SignalType, SignalEntityType, SignalInput,\n SlipSelection, AddToSlipRejectReason, AddToSlipResult, AddToSlipHandler,\n} from './types'\nexport { isAddToSlipResult } from './types'\nexport { createNdjsonParser } from './ndjson'\nexport type { NdjsonParser } from './ndjson'\nexport { createEventLogger } from './eventLog'\nexport type {\n WidgetEventName, WidgetEntityType, WidgetEventInput, WireEvent, EventBatch, EventLoggerOptions, EventLogger,\n} from './eventLog'\nexport type {\n ChatEvent, ProgressEventData, AnswerEventData, EntityCard, EntityCardStat, EntityCardScope, EntityCardEventData,\n ActionButtonEventData, IntentChipEventData, ActionsLoadingEventData,\n TurnCompleteEventData, StreamErrorEventData,\n BettingInsight, BettingInsightOdds, BettingInsightStat, BettingInsightEventData,\n MarketOddsRow, MarketOddsCard, MarketOddsEventData,\n OddsMovementPoint, OddsMovementCard, OddsMovementEventData,\n GreetingDashboard, GreetingDashboardTile, GreetingDashboardLayout, GreetingDashboardSpan, GreetingDashboardSignalRef,\n ClubFanDashboardPayload, ClubFanDashboardCard, ClubFanDashboardHeadToHead,\n FixtureCard, FixtureCardData, FormMatch, CountdownCard, CountdownData,\n InjuriesCard, InjuriesCardData, InjuryRow,\n ReasonToBetCard, ReasonToBetData, WhereToWatchCard, WhereToWatchData,\n CongestedWeekCard, CongestedWeekData, CongestedWeekEntry,\n TransfersCard, TransfersData, TransferRow,\n LinksCard, LinksData, LinkRow,\n PostMatchResultCard, PostMatchResultData,\n PostMatchGoalsCard, PostMatchGoalsData, PostMatchGoalLine,\n PostMatchStatsCard, PostMatchStatsData, PostMatchStatRow,\n PostMatchTopPerformerCard, PostMatchTopPerformerData,\n PostMatchNextCard, PostMatchNextData,\n RestingNextCard, RestingNextData,\n RestingStandingsCard, RestingStandingsData,\n RestingSeasonCard, RestingSeasonData,\n RestingFormCard, RestingFormData,\n LiveScoreCard, LiveScoreData, LiveTimelineCard, LiveTimelineData, LiveEventLine,\n LiveStatsCard, LiveStatsData, LiveStatRow, MomentumPoint,\n PinKind, PinRef, MonitorPhase,\n LiveMonitorStatPrice, LiveMonitorStatRow, LiveMonitorEvent,\n LiveMonitorMatch, LiveMonitorMarket, LiveMonitorSnapshot,\n AvailableMarket, MarketOddsBlock,\n} from './events'\n","export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\nexport class UpstreamError extends WidgetSdkError {\n constructor(status: number, message = 'Upstream error') { super(message, 'upstream_error', status) }\n}\nexport class NetworkError extends WidgetSdkError {\n readonly cause?: unknown\n constructor(message = 'Network request failed', cause?: unknown) { super(message, 'network_error'); this.cause = cause }\n}\nexport class ParseError extends WidgetSdkError {\n readonly line?: string\n constructor(message = 'Malformed NDJSON line', line?: string) { super(message, 'parse_error'); this.line = line }\n}\n","import { AuthError, ForbiddenError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type { ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError'\n}\n\nasync function send(cfg: ResolvedConfig, path: string, body: object, signal?: AbortSignal): Promise<Response> {\n try {\n return await cfg.fetch(endpoint(cfg, path), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n signal,\n })\n } catch (error) {\n if (isAbort(error)) throw error\n throw new NetworkError('Network request failed', error)\n }\n}\n\nexport async function postChat(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): Promise<Response> {\n const res = await send(cfg, 'chat', input, signal)\n if (!res.ok || res.body == null) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ pins }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type { ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from './events'\nimport { getLiveDashboard, postLiveMonitor, postMarketOdds, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n}\n","export type WidgetEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n}\n\nexport interface WireEvent extends WidgetEventInput {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetEventInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set(['pin_add', 'pin_remove', 'slip_click', 'slip_result'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetEventInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\nexport interface ChatInput {\n message: string\n conversationId?: string\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap). Authoritative over `message` when present. */\n actionRef?: string\n userContext?: UserContext\n grounding?: ChatGrounding\n}\n\nexport type SignalType =\n | 'MatchPageView' | 'PlayerPageView' | 'TeamPageView' | 'MarketView'\n | 'SearchQuery' | 'SessionDepth' | 'TimeOnPage' | 'InsightViewed'\n | 'InsightMarketClicked' | 'BetPlacedFromInsight' | 'InsightScrollDepth'\n | 'ToolCall' | 'EntityMention' | 'Handoff' | 'FollowUpQuery' | 'RecommendationDismissed'\n\nexport type SignalEntityType =\n | 'Match' | 'Team' | 'Player' | 'Competition' | 'Market'\n | 'Article' | 'Session' | 'Query' | 'Conversation'\n\nexport interface SignalInput {\n signalType: SignalType\n entityType: SignalEntityType\n /** Either this or entityId is required -- an operator's UI mostly knows a display name. */\n entityName?: string\n /** Either this or entityName is required -- a dashboard tile knows its entity by id. */\n entityId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /** Greeting dashboard layout this signal came from, when it is a dashboard tap. */\n dashboardLayout?: string\n /** Zero-based tile position within the dashboard, when it is a dashboard tap. */\n tileIndex?: number\n}\n\nexport interface SlipSelection {\n matchOddsId: number\n matchId: number\n oddsDecimal: number\n quotedAtUtc?: string\n insightId?: string\n conversationId?: string\n}\n\nexport type AddToSlipRejectReason =\n | 'suspended' | 'closed' | 'login_required'\n | 'not_found' | 'limit' | 'unsupported'\n\nexport type AddToSlipResult =\n | { status: 'added'; slip?: { selectionCount: number; totalOddsDecimal?: number } }\n | { status: 'duplicate' }\n | { status: 'price_changed'; newOddsDecimal: number; accepted: boolean }\n | { status: 'rejected'; reason: AddToSlipRejectReason; message?: string }\n\nexport type AddToSlipHandler = (\n selection: SlipSelection,\n) => Promise<AddToSlipResult | void> | AddToSlipResult | void\n\nconst REJECT_REASONS = ['suspended', 'closed', 'login_required', 'not_found', 'limit', 'unsupported']\n\nexport function isAddToSlipResult(v: unknown): v is AddToSlipResult {\n if (typeof v !== 'object' || v === null) return false\n const o = v as Record<string, unknown>\n switch (o.status) {\n case 'added':\n case 'duplicate':\n return true\n case 'price_changed':\n return typeof o.newOddsDecimal === 'number'\n && Number.isFinite(o.newOddsDecimal)\n && typeof o.accepted === 'boolean'\n case 'rejected':\n return typeof o.reason === 'string'\n && REJECT_REASONS.includes(o.reason)\n default:\n return false\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export { StatsWidgetClient } from './client'\nexport { Conversation } from './conversation'\nexport type { ChatCallbacks, ChatHandle } from './chat'\nexport { SIGNAL_TYPE_CODES, ENTITY_TYPE_CODES } from './signals'\nexport {\n WidgetSdkError, AuthError, ForbiddenError, RateLimitError, UpstreamError, NetworkError, ParseError,\n} from './errors'\nexport type {\n StatsWidgetClientOptions, FetchLike, UserContext, ChatInput, ChatGrounding,\n SignalType, SignalEntityType, SignalInput,\n SlipSelection, AddToSlipRejectReason, AddToSlipResult, AddToSlipHandler,\n} from './types'\nexport { isAddToSlipResult } from './types'\nexport { createNdjsonParser } from './ndjson'\nexport type { NdjsonParser } from './ndjson'\nexport { createEventLogger } from './eventLog'\nexport type {\n WidgetEventName, WidgetEntityType, WidgetEventInput, WireEvent, EventBatch, EventLoggerOptions, EventLogger,\n} from './eventLog'\nexport type {\n ChatEvent, ProgressEventData, AnswerEventData, EntityCard, EntityCardStat, EntityCardScope, EntityCardEventData,\n ActionButtonEventData, IntentChipEventData, ActionsLoadingEventData,\n TurnCompleteEventData, StreamErrorEventData,\n BettingInsight, BettingInsightOdds, BettingInsightStat, BettingInsightEventData,\n MarketOddsRow, MarketOddsCard, MarketOddsEventData,\n OddsMovementPoint, OddsMovementCard, OddsMovementEventData,\n GreetingDashboard, GreetingDashboardTile, GreetingDashboardLayout, GreetingDashboardSpan, GreetingDashboardSignalRef,\n ClubFanDashboardPayload, ClubFanDashboardCard, ClubFanDashboardHeadToHead,\n FixtureCard, FixtureCardData, FormMatch, CountdownCard, CountdownData,\n InjuriesCard, InjuriesCardData, InjuryRow,\n ReasonToBetCard, ReasonToBetData, WhereToWatchCard, WhereToWatchData,\n CongestedWeekCard, CongestedWeekData, CongestedWeekEntry,\n TransfersCard, TransfersData, TransferRow,\n LinksCard, LinksData, LinkRow,\n PostMatchResultCard, PostMatchResultData,\n PostMatchGoalsCard, PostMatchGoalsData, PostMatchGoalLine,\n PostMatchStatsCard, PostMatchStatsData, PostMatchStatRow,\n PostMatchTopPerformerCard, PostMatchTopPerformerData,\n PostMatchNextCard, PostMatchNextData,\n RestingNextCard, RestingNextData,\n RestingStandingsCard, RestingStandingsData,\n RestingSeasonCard, RestingSeasonData,\n RestingFormCard, RestingFormData,\n LiveScoreCard, LiveScoreData, LiveTimelineCard, LiveTimelineData, LiveEventLine,\n LiveStatsCard, LiveStatsData, LiveStatRow, MomentumPoint,\n PinKind, PinRef, MonitorPhase,\n LiveMonitorStatPrice, LiveMonitorStatRow, LiveMonitorEvent,\n LiveMonitorMatch, LiveMonitorMarket, LiveMonitorSnapshot,\n AvailableMarket, MarketOddsBlock,\n ScheduleMatch, ScheduleGroup, SchedulePayload, MatchState, StatesPayload,\n} from './events'\n","export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\nexport class UpstreamError extends WidgetSdkError {\n constructor(status: number, message = 'Upstream error') { super(message, 'upstream_error', status) }\n}\nexport class NetworkError extends WidgetSdkError {\n readonly cause?: unknown\n constructor(message = 'Network request failed', cause?: unknown) { super(message, 'network_error'); this.cause = cause }\n}\nexport class ParseError extends WidgetSdkError {\n readonly line?: string\n constructor(message = 'Malformed NDJSON line', line?: string) { super(message, 'parse_error'); this.line = line }\n}\n","import { AuthError, ForbiddenError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef, SchedulePayload, StatesPayload,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError'\n}\n\nasync function send(cfg: ResolvedConfig, path: string, body: object, signal?: AbortSignal): Promise<Response> {\n try {\n return await cfg.fetch(endpoint(cfg, path), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n signal,\n })\n } catch (error) {\n if (isAbort(error)) throw error\n throw new NetworkError('Network request failed', error)\n }\n}\n\nexport async function postChat(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): Promise<Response> {\n const res = await send(cfg, 'chat', input, signal)\n if (!res.ok || res.body == null) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ pins }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ localDate, utcOffsetMinutes }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef, SchedulePayload, StatesPayload,\n} from './events'\nimport {\n getLiveDashboard, postLiveMonitor, postMarketOdds, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getSchedule(localDate: string, utcOffsetMinutes: number): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n}\n","export type WidgetEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n}\n\nexport interface WireEvent extends WidgetEventInput {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetEventInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set(['pin_add', 'pin_remove', 'slip_click', 'slip_result'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetEventInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\nexport interface ChatInput {\n message: string\n conversationId?: string\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap). Authoritative over `message` when present. */\n actionRef?: string\n userContext?: UserContext\n grounding?: ChatGrounding\n}\n\nexport type SignalType =\n | 'MatchPageView' | 'PlayerPageView' | 'TeamPageView' | 'MarketView'\n | 'SearchQuery' | 'SessionDepth' | 'TimeOnPage' | 'InsightViewed'\n | 'InsightMarketClicked' | 'BetPlacedFromInsight' | 'InsightScrollDepth'\n | 'ToolCall' | 'EntityMention' | 'Handoff' | 'FollowUpQuery' | 'RecommendationDismissed'\n\nexport type SignalEntityType =\n | 'Match' | 'Team' | 'Player' | 'Competition' | 'Market'\n | 'Article' | 'Session' | 'Query' | 'Conversation'\n\nexport interface SignalInput {\n signalType: SignalType\n entityType: SignalEntityType\n /** Either this or entityId is required -- an operator's UI mostly knows a display name. */\n entityName?: string\n /** Either this or entityName is required -- a dashboard tile knows its entity by id. */\n entityId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /** Greeting dashboard layout this signal came from, when it is a dashboard tap. */\n dashboardLayout?: string\n /** Zero-based tile position within the dashboard, when it is a dashboard tap. */\n tileIndex?: number\n}\n\nexport interface SlipSelection {\n matchOddsId: number\n matchId: number\n oddsDecimal: number\n quotedAtUtc?: string\n insightId?: string\n conversationId?: string\n}\n\nexport type AddToSlipRejectReason =\n | 'suspended' | 'closed' | 'login_required'\n | 'not_found' | 'limit' | 'unsupported'\n\nexport type AddToSlipResult =\n | { status: 'added'; slip?: { selectionCount: number; totalOddsDecimal?: number } }\n | { status: 'duplicate' }\n | { status: 'price_changed'; newOddsDecimal: number; accepted: boolean }\n | { status: 'rejected'; reason: AddToSlipRejectReason; message?: string }\n\nexport type AddToSlipHandler = (\n selection: SlipSelection,\n) => Promise<AddToSlipResult | void> | AddToSlipResult | void\n\nconst REJECT_REASONS = ['suspended', 'closed', 'login_required', 'not_found', 'limit', 'unsupported']\n\nexport function isAddToSlipResult(v: unknown): v is AddToSlipResult {\n if (typeof v !== 'object' || v === null) return false\n const o = v as Record<string, unknown>\n switch (o.status) {\n case 'added':\n case 'duplicate':\n return true\n case 'price_changed':\n return typeof o.newOddsDecimal === 'number'\n && Number.isFinite(o.newOddsDecimal)\n && typeof o.accepted === 'boolean'\n case 'rejected':\n return typeof o.reason === 'string'\n && REJECT_REASONS.includes(o.reason)\n default:\n return false\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -632,6 +632,36 @@ interface LiveMonitorSnapshot {
632
632
  serverNowUtc: string;
633
633
  nextPollSeconds: number;
634
634
  }
635
+ interface ScheduleMatch {
636
+ matchId: number;
637
+ homeTeamName: string;
638
+ awayTeamName: string;
639
+ homeTeamImagePath?: string | null;
640
+ awayTeamImagePath?: string | null;
641
+ kickoffUnix: number;
642
+ }
643
+ interface ScheduleGroup {
644
+ competitionId: number;
645
+ competitionName: string;
646
+ competitionImagePath?: string | null;
647
+ rank: number;
648
+ expandedByDefault: boolean;
649
+ matches: ScheduleMatch[];
650
+ }
651
+ interface SchedulePayload {
652
+ localDate: string;
653
+ groups: ScheduleGroup[];
654
+ }
655
+ interface MatchState {
656
+ matchId: number;
657
+ phase: MonitorPhase;
658
+ minuteLabel?: string | null;
659
+ homeScore?: number | null;
660
+ awayScore?: number | null;
661
+ }
662
+ interface StatesPayload {
663
+ states: MatchState[];
664
+ }
635
665
  interface EventEnvelope<TType extends string, TData> {
636
666
  type: TType;
637
667
  requestId: string;
@@ -748,6 +778,8 @@ declare class Conversation {
748
778
  getLiveDashboard(): Promise<ClubFanDashboardPayload | null>;
749
779
  getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null>;
750
780
  getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null>;
781
+ getSchedule(localDate: string, utcOffsetMinutes: number): Promise<SchedulePayload | null>;
782
+ getStates(matchIds: number[]): Promise<StatesPayload | null>;
751
783
  }
752
784
 
753
785
  type WidgetEventName = 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result' | 'insight_expand' | 'tile_tap' | 'chip_tap';
@@ -830,4 +862,4 @@ interface NdjsonParser {
830
862
  }
831
863
  declare function createNdjsonParser(): NdjsonParser;
832
864
 
833
- export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, type AvailableMarket, type BettingInsight, type BettingInsightEventData, type BettingInsightOdds, type BettingInsightStat, type ChatCallbacks, type ChatEvent, type ChatGrounding, type ChatHandle, type ChatInput, type ClubFanDashboardCard, type ClubFanDashboardHeadToHead, type ClubFanDashboardPayload, type CongestedWeekCard, type CongestedWeekData, type CongestedWeekEntry, Conversation, type CountdownCard, type CountdownData, ENTITY_TYPE_CODES, type EntityCard, type EntityCardEventData, type EntityCardScope, type EntityCardStat, type EventBatch, type EventLogger, type EventLoggerOptions, type FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, type FormMatch, type GreetingDashboard, type GreetingDashboardLayout, type GreetingDashboardSignalRef, type GreetingDashboardSpan, type GreetingDashboardTile, type InjuriesCard, type InjuriesCardData, type InjuryRow, type IntentChipEventData, type LinkRow, type LinksCard, type LinksData, type LiveEventLine, type LiveMonitorEvent, type LiveMonitorMarket, type LiveMonitorMatch, type LiveMonitorSnapshot, type LiveMonitorStatPrice, type LiveMonitorStatRow, type LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsBlock, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type MomentumPoint, type MonitorPhase, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, type PinKind, type PinRef, type PostMatchGoalLine, type PostMatchGoalsCard, type PostMatchGoalsData, type PostMatchNextCard, type PostMatchNextData, type PostMatchResultCard, type PostMatchResultData, type PostMatchStatRow, type PostMatchStatsCard, type PostMatchStatsData, type PostMatchTopPerformerCard, type PostMatchTopPerformerData, type ProgressEventData, RateLimitError, type ReasonToBetCard, type ReasonToBetData, type RestingFormCard, type RestingFormData, type RestingNextCard, type RestingNextData, type RestingSeasonCard, type RestingSeasonData, type RestingStandingsCard, type RestingStandingsData, SIGNAL_TYPE_CODES, type SignalEntityType, type SignalInput, type SignalType, type SlipSelection, StatsWidgetClient, type StatsWidgetClientOptions, type StreamErrorEventData, type TransferRow, type TransfersCard, type TransfersData, type TurnCompleteEventData, UpstreamError, type UserContext, type WhereToWatchCard, type WhereToWatchData, type WidgetEntityType, type WidgetEventInput, type WidgetEventName, WidgetSdkError, type WireEvent, createEventLogger, createNdjsonParser, isAddToSlipResult };
865
+ export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, type AvailableMarket, type BettingInsight, type BettingInsightEventData, type BettingInsightOdds, type BettingInsightStat, type ChatCallbacks, type ChatEvent, type ChatGrounding, type ChatHandle, type ChatInput, type ClubFanDashboardCard, type ClubFanDashboardHeadToHead, type ClubFanDashboardPayload, type CongestedWeekCard, type CongestedWeekData, type CongestedWeekEntry, Conversation, type CountdownCard, type CountdownData, ENTITY_TYPE_CODES, type EntityCard, type EntityCardEventData, type EntityCardScope, type EntityCardStat, type EventBatch, type EventLogger, type EventLoggerOptions, type FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, type FormMatch, type GreetingDashboard, type GreetingDashboardLayout, type GreetingDashboardSignalRef, type GreetingDashboardSpan, type GreetingDashboardTile, type InjuriesCard, type InjuriesCardData, type InjuryRow, type IntentChipEventData, type LinkRow, type LinksCard, type LinksData, type LiveEventLine, type LiveMonitorEvent, type LiveMonitorMarket, type LiveMonitorMatch, type LiveMonitorSnapshot, type LiveMonitorStatPrice, type LiveMonitorStatRow, type LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsBlock, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type MatchState, type MomentumPoint, type MonitorPhase, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, type PinKind, type PinRef, type PostMatchGoalLine, type PostMatchGoalsCard, type PostMatchGoalsData, type PostMatchNextCard, type PostMatchNextData, type PostMatchResultCard, type PostMatchResultData, type PostMatchStatRow, type PostMatchStatsCard, type PostMatchStatsData, type PostMatchTopPerformerCard, type PostMatchTopPerformerData, type ProgressEventData, RateLimitError, type ReasonToBetCard, type ReasonToBetData, type RestingFormCard, type RestingFormData, type RestingNextCard, type RestingNextData, type RestingSeasonCard, type RestingSeasonData, type RestingStandingsCard, type RestingStandingsData, SIGNAL_TYPE_CODES, type ScheduleGroup, type ScheduleMatch, type SchedulePayload, type SignalEntityType, type SignalInput, type SignalType, type SlipSelection, type StatesPayload, StatsWidgetClient, type StatsWidgetClientOptions, type StreamErrorEventData, type TransferRow, type TransfersCard, type TransfersData, type TurnCompleteEventData, UpstreamError, type UserContext, type WhereToWatchCard, type WhereToWatchData, type WidgetEntityType, type WidgetEventInput, type WidgetEventName, WidgetSdkError, type WireEvent, createEventLogger, createNdjsonParser, isAddToSlipResult };
package/dist/index.d.ts CHANGED
@@ -632,6 +632,36 @@ interface LiveMonitorSnapshot {
632
632
  serverNowUtc: string;
633
633
  nextPollSeconds: number;
634
634
  }
635
+ interface ScheduleMatch {
636
+ matchId: number;
637
+ homeTeamName: string;
638
+ awayTeamName: string;
639
+ homeTeamImagePath?: string | null;
640
+ awayTeamImagePath?: string | null;
641
+ kickoffUnix: number;
642
+ }
643
+ interface ScheduleGroup {
644
+ competitionId: number;
645
+ competitionName: string;
646
+ competitionImagePath?: string | null;
647
+ rank: number;
648
+ expandedByDefault: boolean;
649
+ matches: ScheduleMatch[];
650
+ }
651
+ interface SchedulePayload {
652
+ localDate: string;
653
+ groups: ScheduleGroup[];
654
+ }
655
+ interface MatchState {
656
+ matchId: number;
657
+ phase: MonitorPhase;
658
+ minuteLabel?: string | null;
659
+ homeScore?: number | null;
660
+ awayScore?: number | null;
661
+ }
662
+ interface StatesPayload {
663
+ states: MatchState[];
664
+ }
635
665
  interface EventEnvelope<TType extends string, TData> {
636
666
  type: TType;
637
667
  requestId: string;
@@ -748,6 +778,8 @@ declare class Conversation {
748
778
  getLiveDashboard(): Promise<ClubFanDashboardPayload | null>;
749
779
  getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null>;
750
780
  getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null>;
781
+ getSchedule(localDate: string, utcOffsetMinutes: number): Promise<SchedulePayload | null>;
782
+ getStates(matchIds: number[]): Promise<StatesPayload | null>;
751
783
  }
752
784
 
753
785
  type WidgetEventName = 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result' | 'insight_expand' | 'tile_tap' | 'chip_tap';
@@ -830,4 +862,4 @@ interface NdjsonParser {
830
862
  }
831
863
  declare function createNdjsonParser(): NdjsonParser;
832
864
 
833
- export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, type AvailableMarket, type BettingInsight, type BettingInsightEventData, type BettingInsightOdds, type BettingInsightStat, type ChatCallbacks, type ChatEvent, type ChatGrounding, type ChatHandle, type ChatInput, type ClubFanDashboardCard, type ClubFanDashboardHeadToHead, type ClubFanDashboardPayload, type CongestedWeekCard, type CongestedWeekData, type CongestedWeekEntry, Conversation, type CountdownCard, type CountdownData, ENTITY_TYPE_CODES, type EntityCard, type EntityCardEventData, type EntityCardScope, type EntityCardStat, type EventBatch, type EventLogger, type EventLoggerOptions, type FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, type FormMatch, type GreetingDashboard, type GreetingDashboardLayout, type GreetingDashboardSignalRef, type GreetingDashboardSpan, type GreetingDashboardTile, type InjuriesCard, type InjuriesCardData, type InjuryRow, type IntentChipEventData, type LinkRow, type LinksCard, type LinksData, type LiveEventLine, type LiveMonitorEvent, type LiveMonitorMarket, type LiveMonitorMatch, type LiveMonitorSnapshot, type LiveMonitorStatPrice, type LiveMonitorStatRow, type LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsBlock, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type MomentumPoint, type MonitorPhase, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, type PinKind, type PinRef, type PostMatchGoalLine, type PostMatchGoalsCard, type PostMatchGoalsData, type PostMatchNextCard, type PostMatchNextData, type PostMatchResultCard, type PostMatchResultData, type PostMatchStatRow, type PostMatchStatsCard, type PostMatchStatsData, type PostMatchTopPerformerCard, type PostMatchTopPerformerData, type ProgressEventData, RateLimitError, type ReasonToBetCard, type ReasonToBetData, type RestingFormCard, type RestingFormData, type RestingNextCard, type RestingNextData, type RestingSeasonCard, type RestingSeasonData, type RestingStandingsCard, type RestingStandingsData, SIGNAL_TYPE_CODES, type SignalEntityType, type SignalInput, type SignalType, type SlipSelection, StatsWidgetClient, type StatsWidgetClientOptions, type StreamErrorEventData, type TransferRow, type TransfersCard, type TransfersData, type TurnCompleteEventData, UpstreamError, type UserContext, type WhereToWatchCard, type WhereToWatchData, type WidgetEntityType, type WidgetEventInput, type WidgetEventName, WidgetSdkError, type WireEvent, createEventLogger, createNdjsonParser, isAddToSlipResult };
865
+ export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, type AvailableMarket, type BettingInsight, type BettingInsightEventData, type BettingInsightOdds, type BettingInsightStat, type ChatCallbacks, type ChatEvent, type ChatGrounding, type ChatHandle, type ChatInput, type ClubFanDashboardCard, type ClubFanDashboardHeadToHead, type ClubFanDashboardPayload, type CongestedWeekCard, type CongestedWeekData, type CongestedWeekEntry, Conversation, type CountdownCard, type CountdownData, ENTITY_TYPE_CODES, type EntityCard, type EntityCardEventData, type EntityCardScope, type EntityCardStat, type EventBatch, type EventLogger, type EventLoggerOptions, type FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, type FormMatch, type GreetingDashboard, type GreetingDashboardLayout, type GreetingDashboardSignalRef, type GreetingDashboardSpan, type GreetingDashboardTile, type InjuriesCard, type InjuriesCardData, type InjuryRow, type IntentChipEventData, type LinkRow, type LinksCard, type LinksData, type LiveEventLine, type LiveMonitorEvent, type LiveMonitorMarket, type LiveMonitorMatch, type LiveMonitorSnapshot, type LiveMonitorStatPrice, type LiveMonitorStatRow, type LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsBlock, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type MatchState, type MomentumPoint, type MonitorPhase, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, type PinKind, type PinRef, type PostMatchGoalLine, type PostMatchGoalsCard, type PostMatchGoalsData, type PostMatchNextCard, type PostMatchNextData, type PostMatchResultCard, type PostMatchResultData, type PostMatchStatRow, type PostMatchStatsCard, type PostMatchStatsData, type PostMatchTopPerformerCard, type PostMatchTopPerformerData, type ProgressEventData, RateLimitError, type ReasonToBetCard, type ReasonToBetData, type RestingFormCard, type RestingFormData, type RestingNextCard, type RestingNextData, type RestingSeasonCard, type RestingSeasonData, type RestingStandingsCard, type RestingStandingsData, SIGNAL_TYPE_CODES, type ScheduleGroup, type ScheduleMatch, type SchedulePayload, type SignalEntityType, type SignalInput, type SignalType, type SlipSelection, type StatesPayload, StatsWidgetClient, type StatsWidgetClientOptions, type StreamErrorEventData, type TransferRow, type TransfersCard, type TransfersData, type TurnCompleteEventData, UpstreamError, type UserContext, type WhereToWatchCard, type WhereToWatchData, type WidgetEntityType, type WidgetEventInput, type WidgetEventName, WidgetSdkError, type WireEvent, createEventLogger, createNdjsonParser, isAddToSlipResult };
package/dist/index.js CHANGED
@@ -127,6 +127,26 @@ async function postMarketOdds(cfg, matchId, marketDeveloperName) {
127
127
  if (!res.ok) throw new Error(`live-monitor/market ${res.status}`);
128
128
  return await res.json();
129
129
  }
130
+ async function postSchedule(cfg, localDate, utcOffsetMinutes) {
131
+ const res = await cfg.fetch(endpoint(cfg, "live-monitor/schedule"), {
132
+ method: "POST",
133
+ headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
134
+ body: JSON.stringify({ localDate, utcOffsetMinutes })
135
+ });
136
+ if (res.status === 404) return null;
137
+ if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`);
138
+ return await res.json();
139
+ }
140
+ async function postStates(cfg, matchIds) {
141
+ const res = await cfg.fetch(endpoint(cfg, "live-monitor/states"), {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
144
+ body: JSON.stringify({ matchIds })
145
+ });
146
+ if (res.status === 404) return null;
147
+ if (!res.ok) throw new Error(`live-monitor/states ${res.status}`);
148
+ return await res.json();
149
+ }
130
150
 
131
151
  // src/ndjson.ts
132
152
  function parseLine(line) {
@@ -339,6 +359,12 @@ var Conversation = class {
339
359
  getMarketOdds(matchId, marketDeveloperName) {
340
360
  return postMarketOdds(this.cfg, matchId, marketDeveloperName);
341
361
  }
362
+ getSchedule(localDate, utcOffsetMinutes) {
363
+ return postSchedule(this.cfg, localDate, utcOffsetMinutes);
364
+ }
365
+ getStates(matchIds) {
366
+ return postStates(this.cfg, matchIds);
367
+ }
342
368
  };
343
369
 
344
370
  // src/eventLog.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\nexport class UpstreamError extends WidgetSdkError {\n constructor(status: number, message = 'Upstream error') { super(message, 'upstream_error', status) }\n}\nexport class NetworkError extends WidgetSdkError {\n readonly cause?: unknown\n constructor(message = 'Network request failed', cause?: unknown) { super(message, 'network_error'); this.cause = cause }\n}\nexport class ParseError extends WidgetSdkError {\n readonly line?: string\n constructor(message = 'Malformed NDJSON line', line?: string) { super(message, 'parse_error'); this.line = line }\n}\n","import { AuthError, ForbiddenError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type { ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError'\n}\n\nasync function send(cfg: ResolvedConfig, path: string, body: object, signal?: AbortSignal): Promise<Response> {\n try {\n return await cfg.fetch(endpoint(cfg, path), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n signal,\n })\n } catch (error) {\n if (isAbort(error)) throw error\n throw new NetworkError('Network request failed', error)\n }\n}\n\nexport async function postChat(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): Promise<Response> {\n const res = await send(cfg, 'chat', input, signal)\n if (!res.ok || res.body == null) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ pins }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type { ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from './events'\nimport { getLiveDashboard, postLiveMonitor, postMarketOdds, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n}\n","export type WidgetEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n}\n\nexport interface WireEvent extends WidgetEventInput {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetEventInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set(['pin_add', 'pin_remove', 'slip_click', 'slip_result'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetEventInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\nexport interface ChatInput {\n message: string\n conversationId?: string\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap). Authoritative over `message` when present. */\n actionRef?: string\n userContext?: UserContext\n grounding?: ChatGrounding\n}\n\nexport type SignalType =\n | 'MatchPageView' | 'PlayerPageView' | 'TeamPageView' | 'MarketView'\n | 'SearchQuery' | 'SessionDepth' | 'TimeOnPage' | 'InsightViewed'\n | 'InsightMarketClicked' | 'BetPlacedFromInsight' | 'InsightScrollDepth'\n | 'ToolCall' | 'EntityMention' | 'Handoff' | 'FollowUpQuery' | 'RecommendationDismissed'\n\nexport type SignalEntityType =\n | 'Match' | 'Team' | 'Player' | 'Competition' | 'Market'\n | 'Article' | 'Session' | 'Query' | 'Conversation'\n\nexport interface SignalInput {\n signalType: SignalType\n entityType: SignalEntityType\n /** Either this or entityId is required -- an operator's UI mostly knows a display name. */\n entityName?: string\n /** Either this or entityName is required -- a dashboard tile knows its entity by id. */\n entityId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /** Greeting dashboard layout this signal came from, when it is a dashboard tap. */\n dashboardLayout?: string\n /** Zero-based tile position within the dashboard, when it is a dashboard tap. */\n tileIndex?: number\n}\n\nexport interface SlipSelection {\n matchOddsId: number\n matchId: number\n oddsDecimal: number\n quotedAtUtc?: string\n insightId?: string\n conversationId?: string\n}\n\nexport type AddToSlipRejectReason =\n | 'suspended' | 'closed' | 'login_required'\n | 'not_found' | 'limit' | 'unsupported'\n\nexport type AddToSlipResult =\n | { status: 'added'; slip?: { selectionCount: number; totalOddsDecimal?: number } }\n | { status: 'duplicate' }\n | { status: 'price_changed'; newOddsDecimal: number; accepted: boolean }\n | { status: 'rejected'; reason: AddToSlipRejectReason; message?: string }\n\nexport type AddToSlipHandler = (\n selection: SlipSelection,\n) => Promise<AddToSlipResult | void> | AddToSlipResult | void\n\nconst REJECT_REASONS = ['suspended', 'closed', 'login_required', 'not_found', 'limit', 'unsupported']\n\nexport function isAddToSlipResult(v: unknown): v is AddToSlipResult {\n if (typeof v !== 'object' || v === null) return false\n const o = v as Record<string, unknown>\n switch (o.status) {\n case 'added':\n case 'duplicate':\n return true\n case 'price_changed':\n return typeof o.newOddsDecimal === 'number'\n && Number.isFinite(o.newOddsDecimal)\n && typeof o.accepted === 'boolean'\n case 'rejected':\n return typeof o.reason === 'string'\n && REJECT_REASONS.includes(o.reason)\n default:\n return false\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\nexport class UpstreamError extends WidgetSdkError {\n constructor(status: number, message = 'Upstream error') { super(message, 'upstream_error', status) }\n}\nexport class NetworkError extends WidgetSdkError {\n readonly cause?: unknown\n constructor(message = 'Network request failed', cause?: unknown) { super(message, 'network_error'); this.cause = cause }\n}\nexport class ParseError extends WidgetSdkError {\n readonly line?: string\n constructor(message = 'Malformed NDJSON line', line?: string) { super(message, 'parse_error'); this.line = line }\n}\n","import { AuthError, ForbiddenError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef, SchedulePayload, StatesPayload,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError'\n}\n\nasync function send(cfg: ResolvedConfig, path: string, body: object, signal?: AbortSignal): Promise<Response> {\n try {\n return await cfg.fetch(endpoint(cfg, path), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n signal,\n })\n } catch (error) {\n if (isAbort(error)) throw error\n throw new NetworkError('Network request failed', error)\n }\n}\n\nexport async function postChat(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): Promise<Response> {\n const res = await send(cfg, 'chat', input, signal)\n if (!res.ok || res.body == null) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ pins }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ localDate, utcOffsetMinutes }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, LiveMonitorSnapshot, MarketOddsBlock, PinRef, SchedulePayload, StatesPayload,\n} from './events'\nimport {\n getLiveDashboard, postLiveMonitor, postMarketOdds, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getSchedule(localDate: string, utcOffsetMinutes: number): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n}\n","export type WidgetEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n}\n\nexport interface WireEvent extends WidgetEventInput {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetEventInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set(['pin_add', 'pin_remove', 'slip_click', 'slip_result'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetEventInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\nexport interface ChatInput {\n message: string\n conversationId?: string\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap). Authoritative over `message` when present. */\n actionRef?: string\n userContext?: UserContext\n grounding?: ChatGrounding\n}\n\nexport type SignalType =\n | 'MatchPageView' | 'PlayerPageView' | 'TeamPageView' | 'MarketView'\n | 'SearchQuery' | 'SessionDepth' | 'TimeOnPage' | 'InsightViewed'\n | 'InsightMarketClicked' | 'BetPlacedFromInsight' | 'InsightScrollDepth'\n | 'ToolCall' | 'EntityMention' | 'Handoff' | 'FollowUpQuery' | 'RecommendationDismissed'\n\nexport type SignalEntityType =\n | 'Match' | 'Team' | 'Player' | 'Competition' | 'Market'\n | 'Article' | 'Session' | 'Query' | 'Conversation'\n\nexport interface SignalInput {\n signalType: SignalType\n entityType: SignalEntityType\n /** Either this or entityId is required -- an operator's UI mostly knows a display name. */\n entityName?: string\n /** Either this or entityName is required -- a dashboard tile knows its entity by id. */\n entityId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /** Greeting dashboard layout this signal came from, when it is a dashboard tap. */\n dashboardLayout?: string\n /** Zero-based tile position within the dashboard, when it is a dashboard tap. */\n tileIndex?: number\n}\n\nexport interface SlipSelection {\n matchOddsId: number\n matchId: number\n oddsDecimal: number\n quotedAtUtc?: string\n insightId?: string\n conversationId?: string\n}\n\nexport type AddToSlipRejectReason =\n | 'suspended' | 'closed' | 'login_required'\n | 'not_found' | 'limit' | 'unsupported'\n\nexport type AddToSlipResult =\n | { status: 'added'; slip?: { selectionCount: number; totalOddsDecimal?: number } }\n | { status: 'duplicate' }\n | { status: 'price_changed'; newOddsDecimal: number; accepted: boolean }\n | { status: 'rejected'; reason: AddToSlipRejectReason; message?: string }\n\nexport type AddToSlipHandler = (\n selection: SlipSelection,\n) => Promise<AddToSlipResult | void> | AddToSlipResult | void\n\nconst REJECT_REASONS = ['suspended', 'closed', 'login_required', 'not_found', 'limit', 'unsupported']\n\nexport function isAddToSlipResult(v: unknown): v is AddToSlipResult {\n if (typeof v !== 'object' || v === null) return false\n const o = v as Record<string, unknown>\n switch (o.status) {\n case 'added':\n case 'duplicate':\n return true\n case 'price_changed':\n return typeof o.newOddsDecimal === 'number'\n && Number.isFinite(o.newOddsDecimal)\n && typeof o.accepted === 'boolean'\n case 'rejected':\n return typeof o.reason === 'string'\n && REJECT_REASONS.includes(o.reason)\n default:\n return false\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensiblestats/widget-sdk",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Headless browser SDK for the SensibleStats chat widget gateway.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",