@sensiblestats/widget-sdk 0.25.3 → 0.27.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 +12 -0
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -3
- package/dist/index.d.ts +96 -3
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @sensiblestats/widget-sdk
|
|
2
2
|
|
|
3
|
+
## 0.27.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Live monitor tabs (u322): pin markets/matches from betting cards into Matches/Odds tabs with a batched live poll; pinEnabled flag on betting cards; monitor types + /live-monitor transport.
|
|
8
|
+
|
|
9
|
+
## 0.26.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 9d0b409: Replace the pre-match fixture card's W/D/L letter pills with a two-column "Team form" card: each of the last five results renders as a coloured scoreline card (subject crest, score, opponent crest), oriented by which side the team played on. `FixtureCardData.homeForm`/`awayForm` change from `string[]` to a new `FormMatch[]` shape (`result`, `teamScore`, `oppScore`, `teamIsHome`, `opponentCrestUrl`).
|
|
14
|
+
|
|
3
15
|
## 0.25.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -129,6 +129,16 @@ async function getLiveDashboard(cfg) {
|
|
|
129
129
|
if (!res.ok) throw new Error(`live-dashboard ${res.status}`);
|
|
130
130
|
return await res.json();
|
|
131
131
|
}
|
|
132
|
+
async function postLiveMonitor(cfg, pins) {
|
|
133
|
+
const res = await cfg.fetch(endpoint(cfg, "live-monitor"), {
|
|
134
|
+
method: "POST",
|
|
135
|
+
headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
|
|
136
|
+
body: JSON.stringify({ pins })
|
|
137
|
+
});
|
|
138
|
+
if (res.status === 404) return null;
|
|
139
|
+
if (!res.ok) throw new Error(`live-monitor ${res.status}`);
|
|
140
|
+
return await res.json();
|
|
141
|
+
}
|
|
132
142
|
|
|
133
143
|
// src/ndjson.ts
|
|
134
144
|
function parseLine(line) {
|
|
@@ -335,6 +345,9 @@ var Conversation = class {
|
|
|
335
345
|
getLiveDashboard() {
|
|
336
346
|
return getLiveDashboard(this.cfg);
|
|
337
347
|
}
|
|
348
|
+
getLiveMonitor(pins) {
|
|
349
|
+
return postLiveMonitor(this.cfg, pins);
|
|
350
|
+
}
|
|
338
351
|
};
|
|
339
352
|
|
|
340
353
|
// src/client.ts
|
package/dist/index.cjs.map
CHANGED
|
@@ -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/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 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, 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,\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 } 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 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","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 } from './events'\nimport { getLiveDashboard, 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","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { 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","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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAGxC,YAAY,SAAiB,MAAc,QAAiB;AAC1D,UAAM,OAAO;AACb,SAAK,OAAO,WAAW;AACvB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,WAAO,eAAe,MAAM,WAAW,SAAS;AAAA,EAClD;AACF;AACO,IAAM,YAAN,cAAwB,eAAe;AAAA,EAC5C,YAAY,UAAU,iCAAiC;AAAE,UAAM,SAAS,gBAAgB,GAAG;AAAA,EAAE;AAC/F;AACO,IAAM,iBAAN,cAA6B,eAAe;AAAA,EACjD,YAAY,UAAU,yCAAyC;AAAE,UAAM,SAAS,aAAa,GAAG;AAAA,EAAE;AACpG;AACO,IAAM,iBAAN,cAA6B,eAAe;AAAA,EAEjD,YAAY,YAAqB,UAAU,gBAAgB;AAAE,UAAM,SAAS,gBAAgB,GAAG;AAAG,SAAK,aAAa;AAAA,EAAW;AACjI;AACO,IAAM,gBAAN,cAA4B,eAAe;AAAA,EAChD,YAAY,QAAgB,UAAU,kBAAkB;AAAE,UAAM,SAAS,kBAAkB,MAAM;AAAA,EAAE;AACrG;AACO,IAAM,eAAN,cAA2B,eAAe;AAAA,EAE/C,YAAY,UAAU,0BAA0B,OAAiB;AAAE,UAAM,SAAS,eAAe;AAAG,SAAK,QAAQ;AAAA,EAAM;AACzH;AACO,IAAM,aAAN,cAAyB,eAAe;AAAA,EAE7C,YAAY,UAAU,yBAAyB,MAAe;AAAE,UAAM,SAAS,aAAa;AAAG,SAAK,OAAO;AAAA,EAAK;AAClH;;;ACpBA,SAAS,SAAS,KAAqB,MAAsB;AAC3D,SAAO,GAAG,IAAI,QAAQ,QAAQ,QAAQ,EAAE,CAAC,OAAO,mBAAmB,IAAI,UAAU,CAAC,IAAI,IAAI;AAC5F;AAEO,SAAS,cAAc,QAAgB,kBAAiD;AAC7F,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAK,aAAO,IAAI,UAAU;AAAA,IAC/B,KAAK;AAAK,aAAO,IAAI,eAAe;AAAA,IACpC,KAAK,KAAK;AACR,YAAM,IAAI,oBAAoB,OAAO,OAAO,gBAAgB,IAAI;AAChE,aAAO,IAAI,eAAe,OAAO,SAAS,CAAC,IAAK,IAAe,MAAS;AAAA,IAC1E;AAAA,IACA;AAAS,aAAO,IAAI,cAAc,MAAM;AAAA,EAC1C;AACF;AAEA,SAAS,QAAQ,OAAyB;AACxC,SAAO,iBAAiB,SAAS,MAAM,SAAS;AAClD;AAEA,eAAe,KAAK,KAAqB,MAAc,MAAc,QAAyC;AAC5G,MAAI;AACF,WAAO,MAAM,IAAI,MAAM,SAAS,KAAK,IAAI,GAAG;AAAA,MAC1C,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,MAChF,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,QAAQ,KAAK,EAAG,OAAM;AAC1B,UAAM,IAAI,aAAa,0BAA0B,KAAK;AAAA,EACxD;AACF;AAEA,eAAsB,SAAS,KAAqB,OAAkB,QAAwC;AAC5G,QAAM,MAAM,MAAM,KAAK,KAAK,QAAQ,OAAO,MAAM;AACjD,MAAI,CAAC,IAAI,MAAM,IAAI,QAAQ,KAAM,OAAM,cAAc,IAAI,QAAQ,IAAI,QAAQ,IAAI,aAAa,CAAC;AAC/F,SAAO;AACT;AAEA,eAAsB,WAAW,KAAqB,UAAkB,QAAqC;AAC3G,QAAM,MAAM,MAAM,KAAK,KAAK,WAAW,UAAU,MAAM;AACvD,MAAI,CAAC,IAAI,GAAI,OAAM,cAAc,IAAI,QAAQ,IAAI,QAAQ,IAAI,aAAa,CAAC;AAC7E;AAEA,eAAsB,iBAAiB,KAA8D;AACnG,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,gBAAgB,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAI7H,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,EAAE;AAC3D,SAAQ,MAAM,IAAI,KAAK;AACzB;;;ACzDA,SAAS,UAAU,MAAmC;AACpD,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,UAAM,IAAI,WAAW,yBAAyB,IAAI;AAAA,EACpD;AACF;AAEO,SAAS,qBAAmC;AACjD,MAAI,SAAS;AACb,SAAO;AAAA,IACL,KAAK,MAAyB;AAC5B,gBAAU;AACV,YAAM,MAAiB,CAAC;AACxB,UAAI;AACJ,cAAQ,MAAM,OAAO,QAAQ,IAAI,MAAM,GAAG;AACxC,cAAM,OAAO,OAAO,MAAM,GAAG,GAAG;AAChC,iBAAS,OAAO,MAAM,MAAM,CAAC;AAC7B,cAAM,SAAS,UAAU,IAAI;AAC7B,YAAI,WAAW,OAAW,KAAI,KAAK,MAAM;AAAA,MAC3C;AACA,aAAO;AAAA,IACT;AAAA,IACA,QAAmB;AACjB,YAAM,OAAO;AACb,eAAS;AACT,YAAM,SAAS,UAAU,IAAI;AAC7B,aAAO,WAAW,SAAY,CAAC,IAAI,CAAC,MAAM;AAAA,IAC5C;AAAA,EACF;AACF;;;ACfA,SAAS,SAAS,IAAe,IAAyB;AACxD,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AAAY,SAAG,aAAa,GAAG,IAAI;AAAG;AAAA,IAC3C,KAAK;AAAU,SAAG,WAAW,GAAG,IAAI;AAAG;AAAA,IACvC,KAAK;AAAe,SAAG,eAAe,GAAG,IAAI;AAAG;AAAA,IAChD,KAAK;AAAiB,SAAG,iBAAiB,GAAG,IAAI;AAAG;AAAA,IACpD,KAAK;AAAe,SAAG,eAAe,GAAG,IAAI;AAAG;AAAA,IAChD,KAAK;AAAmB,SAAG,mBAAmB,GAAG,IAAI;AAAG;AAAA,IACxD,KAAK;AAAiB,SAAG,aAAa,GAAG,IAAI;AAAG;AAAA,IAChD,KAAK;AAAS,SAAG,UAAU,GAAG,IAAI;AAAG;AAAA,EACvC;AACF;AAEA,gBAAgB,aAAa,KAAqB,OAAkB,QAAgD;AAClH,QAAM,MAAM,MAAM,SAAS,KAAK,OAAO,MAAM;AAC7C,QAAM,SAAS,IAAI,KAAM,UAAU;AACnC,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,SAAS,mBAAmB;AAClC,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,iBAAW,OAAO,OAAO,KAAK,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC,EAAG,OAAM;AAAA,IAChF;AACA,eAAW,OAAO,OAAO,MAAM,EAAG,OAAM;AAAA,EAC1C,UAAE;AACA,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtC;AACF;AAEO,SAAS,QACd,KACA,OACA,WACA,MACY;AACZ,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,WAAW,MAAM;AACvB,MAAI,UAAU;AACZ,QAAI,SAAS,QAAS,YAAW,MAAM;AAAA,QAClC,UAAS,iBAAiB,SAAS,MAAM,WAAW,MAAM,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,EAClF;AAEA,kBAAgB,SAAoC;AAClD,qBAAiB,MAAM,aAAa,KAAK,OAAO,WAAW,MAAM,GAAG;AAClE,YAAM,MAAM,EAAE;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,WAAW,OAAO;AACxB,MAAI,WAAW;AAEf,iBAAe,QAAuB;AACpC,QAAI;AACF,uBAAiB,MAAM,UAAU;AAAE,YAAI,UAAW,UAAS,IAAI,SAAS;AAAA,MAAE;AAAA,IAC5E,SAAS,OAAO;AACd,UAAI,WAAW,WAAW,iBAAiB,gBAAgB;AAAE,kBAAU,QAAQ,KAAK;AAAG;AAAA,MAAO;AAC9F,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,CAAC,OAAO,aAAa,IAA8B;AACjD,UAAI,SAAU,OAAM,IAAI,MAAM,8BAA8B;AAC5D,iBAAW;AACX,aAAO;AAAA,IACT;AAAA,IACA,KACE,aACA,YACkC;AAClC,UAAI,SAAU,QAAO,QAAQ,QAAQ,EAAE,KAAK,aAAa,UAAU;AACnE,iBAAW;AACX,aAAO,MAAM,EAAE,KAAK,aAAa,UAAU;AAAA,IAC7C;AAAA,IACA,SAAe;AAAE,iBAAW,MAAM;AAAA,IAAE;AAAA,EACtC;AACF;;;ACpGO,IAAM,oBAAgD;AAAA,EAC3D,eAAe;AAAA,EAAG,gBAAgB;AAAA,EAAG,cAAc;AAAA,EAAG,YAAY;AAAA,EAClE,aAAa;AAAA,EAAG,cAAc;AAAA,EAAG,YAAY;AAAA,EAAG,eAAe;AAAA,EAC/D,sBAAsB;AAAA,EAAG,sBAAsB;AAAA,EAAI,oBAAoB;AAAA,EACvE,UAAU;AAAA,EAAI,eAAe;AAAA,EAAI,SAAS;AAAA,EAAI,eAAe;AAAA,EAAI,yBAAyB;AAC5F;AAEO,IAAM,oBAAsD;AAAA,EACjE,OAAO;AAAA,EAAG,MAAM;AAAA,EAAG,QAAQ;AAAA,EAAG,aAAa;AAAA,EAAG,QAAQ;AAAA,EACtD,SAAS;AAAA,EAAG,SAAS;AAAA,EAAG,OAAO;AAAA,EAAG,cAAc;AAClD;AAEO,SAAS,iBAAiB,OAG/B;AACA,QAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,QAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,MAAI,eAAe,OAAW,OAAM,IAAI,MAAM,uBAAuB,OAAO,MAAM,UAAU,CAAC,EAAE;AAC/F,MAAI,eAAe,OAAW,OAAM,IAAI,MAAM,uBAAuB,OAAO,MAAM,UAAU,CAAC,EAAE;AAC/F,SAAO;AAAA,IACL;AAAA,IAAY;AAAA,IAAY,YAAY,MAAM;AAAA,IAAY,UAAU,MAAM;AAAA,IACtE,gBAAgB,MAAM;AAAA,IAAgB,iBAAiB,MAAM;AAAA,IAC7D,iBAAiB,MAAM;AAAA,IAAiB,WAAW,MAAM;AAAA,EAC3D;AACF;;;ACrBO,IAAM,eAAN,MAAmB;AAAA,EAGxB,YAA6B,KAAsC,SAAuB;AAA7D;AAAsC;AAAA,EAAwB;AAAA,EAE3F,KAAK,OAAkB,WAAuC;AAC5D,UAAM,gBAA6B,EAAE,GAAG,KAAK,SAAS,GAAG,MAAM,YAAY;AAC3E,UAAM,OAAkB;AAAA,MACtB,GAAG;AAAA,MACH,gBAAgB,MAAM,kBAAkB,KAAK;AAAA,MAC7C,aAAa,OAAO,KAAK,aAAa,EAAE,SAAS,IAAI,gBAAgB;AAAA,IACvE;AACA,WAAO,QAAQ,KAAK,KAAK,MAAM,WAAW;AAAA,MACxC,KAAK,CAAC,OAAO;AAAE,YAAI,GAAG,SAAS,gBAAiB,MAAK,iBAAiB,GAAG,KAAK;AAAA,MAAe;AAAA,IAC/F,CAAC;AAAA,EACH;AAAA,EAEA,WAAW,OAAmC;AAC5C,UAAM,iBAAiB,MAAM,kBAAkB,KAAK,SAAS;AAC7D,UAAM,kBAAkB,iBAAiB,SAAa,MAAM,mBAAmB,KAAK,SAAS;AAC7F,QAAI,CAAC,kBAAkB,CAAC,iBAAiB;AACvC,YAAM,IAAI,MAAM,mGAAmG;AAAA,IACrH;AACA,QAAI,CAAC,MAAM,YAAY,CAAC,MAAM,YAAY;AACxC,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,WAAO,WAAW,KAAK,KAAK,iBAAiB,EAAE,GAAG,OAAO,gBAAgB,gBAAgB,CAAC,CAAC;AAAA,EAC7F;AAAA,EAEA,mBAA4D;AAC1D,WAAO,iBAAiB,KAAK,GAAG;AAAA,EAClC;AACF;;;AChCA,IAAM,mBAAmB;AAElB,IAAM,oBAAN,MAAwB;AAAA,EAG7B,YAAY,SAAmC;AAC7C,QAAI,CAAC,QAAQ,WAAY,OAAM,IAAI,MAAM,wBAAwB;AACjE,QAAI,CAAC,QAAQ,UAAW,OAAM,IAAI,MAAM,uBAAuB;AAC/D,UAAM,YAAY,QAAQ,UAAU,WAAW,QAAQ,WAAW,MAAM,KAAK,UAAU,IAAI;AAC3F,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,uDAAuD;AACvF,SAAK,MAAM;AAAA,MACT,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ,WAAW;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,KAAK,OAAkB,WAAuC;AAC5D,WAAO,QAAQ,KAAK,KAAK,OAAO,SAAS;AAAA,EAC3C;AAAA,EAEA,MAAM,WAAW,OAAmC;AAClD,UAAM,WAAW,KAAK,KAAK,iBAAiB,KAAK,CAAC;AAAA,EACpD;AAAA,EAEA,aAAa,SAAqC;AAChD,WAAO,IAAI,aAAa,KAAK,KAAK,OAAO;AAAA,EAC3C;AACF;;;ACkDA,IAAM,iBAAiB,CAAC,aAAa,UAAU,kBAAkB,aAAa,SAAS,aAAa;AAE7F,SAAS,kBAAkB,GAAkC;AAClE,MAAI,OAAO,MAAM,YAAY,MAAM,KAAM,QAAO;AAChD,QAAM,IAAI;AACV,UAAQ,EAAE,QAAQ;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,OAAO,EAAE,mBAAmB,YAC9B,OAAO,SAAS,EAAE,cAAc,KAChC,OAAO,EAAE,aAAa;AAAA,IAC7B,KAAK;AACH,aAAO,OAAO,EAAE,WAAW,YACtB,eAAe,SAAS,EAAE,MAAM;AAAA,IACvC;AACE,aAAO;AAAA,EACX;AACF;","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/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 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} 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, 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 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","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, PinRef } from './events'\nimport { getLiveDashboard, postLiveMonitor, 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","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { 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","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
|
@@ -108,14 +108,21 @@ interface ClubFanDashboardPrefillCard extends ClubFanDashboardCardBase {
|
|
|
108
108
|
actionType: string;
|
|
109
109
|
rank: number;
|
|
110
110
|
}
|
|
111
|
+
interface FormMatch {
|
|
112
|
+
result: 'W' | 'D' | 'L';
|
|
113
|
+
teamScore: number;
|
|
114
|
+
oppScore: number;
|
|
115
|
+
teamIsHome: boolean;
|
|
116
|
+
opponentCrestUrl?: string | null;
|
|
117
|
+
}
|
|
111
118
|
interface FixtureCardData {
|
|
112
119
|
homeName: string;
|
|
113
120
|
awayName: string;
|
|
114
121
|
competition: string;
|
|
115
122
|
kickoffUnix: number;
|
|
116
123
|
venue?: string | null;
|
|
117
|
-
homeForm:
|
|
118
|
-
awayForm:
|
|
124
|
+
homeForm: FormMatch[];
|
|
125
|
+
awayForm: FormMatch[];
|
|
119
126
|
h2H?: ClubFanDashboardHeadToHead | null;
|
|
120
127
|
fact?: string | null;
|
|
121
128
|
homeCrestUrl?: string | null;
|
|
@@ -443,6 +450,7 @@ interface BettingInsight {
|
|
|
443
450
|
competitionImagePath?: string;
|
|
444
451
|
kickoffUtc?: string;
|
|
445
452
|
isMarketFloor?: boolean;
|
|
453
|
+
pinEnabled?: boolean;
|
|
446
454
|
[key: string]: unknown;
|
|
447
455
|
}
|
|
448
456
|
interface BettingInsightEventData {
|
|
@@ -477,6 +485,7 @@ interface MarketOddsCard {
|
|
|
477
485
|
rows?: MarketOddsRow[];
|
|
478
486
|
disclaimer?: string | null;
|
|
479
487
|
addToSlipEnabled?: boolean;
|
|
488
|
+
pinEnabled?: boolean;
|
|
480
489
|
[key: string]: unknown;
|
|
481
490
|
}
|
|
482
491
|
interface MarketOddsEventData {
|
|
@@ -507,11 +516,94 @@ interface OddsMovementCard {
|
|
|
507
516
|
excludedSuspendedCount?: number;
|
|
508
517
|
disclaimer?: string | null;
|
|
509
518
|
isSuspended?: boolean;
|
|
519
|
+
pinEnabled?: boolean;
|
|
520
|
+
matchOddsId?: number | null;
|
|
510
521
|
[key: string]: unknown;
|
|
511
522
|
}
|
|
512
523
|
interface OddsMovementEventData {
|
|
513
524
|
card: OddsMovementCard;
|
|
514
525
|
}
|
|
526
|
+
type PinKind = 'match' | 'market' | 'selection';
|
|
527
|
+
interface PinRef {
|
|
528
|
+
key: string;
|
|
529
|
+
kind: PinKind;
|
|
530
|
+
matchId: number;
|
|
531
|
+
marketDeveloperName?: string;
|
|
532
|
+
line?: string | null;
|
|
533
|
+
selectionLabel?: string;
|
|
534
|
+
matchOddsId?: number | null;
|
|
535
|
+
withHistory?: boolean;
|
|
536
|
+
}
|
|
537
|
+
interface LiveMonitorStatPrice {
|
|
538
|
+
marketDeveloperName: string;
|
|
539
|
+
marketLabel: string;
|
|
540
|
+
selectionLabel: string;
|
|
541
|
+
price?: number | null;
|
|
542
|
+
matchOddsId?: number | null;
|
|
543
|
+
isSuspended: boolean;
|
|
544
|
+
addToSlipEnabled: boolean;
|
|
545
|
+
}
|
|
546
|
+
interface LiveMonitorStatRow {
|
|
547
|
+
label: string;
|
|
548
|
+
homeValue: string;
|
|
549
|
+
awayValue: string;
|
|
550
|
+
homeNum: number;
|
|
551
|
+
awayNum: number;
|
|
552
|
+
market?: LiveMonitorStatPrice | null;
|
|
553
|
+
}
|
|
554
|
+
interface LiveMonitorEvent {
|
|
555
|
+
minuteLabel: string;
|
|
556
|
+
text: string;
|
|
557
|
+
type: 'goal' | 'yellow' | 'red' | 'sub' | 'other';
|
|
558
|
+
side: 'home' | 'away';
|
|
559
|
+
player?: string | null;
|
|
560
|
+
}
|
|
561
|
+
type MonitorPhase = 'preMatch' | 'live' | 'fullTime' | 'postponed' | 'gone';
|
|
562
|
+
interface LiveMonitorMatch {
|
|
563
|
+
matchId: number;
|
|
564
|
+
phase: MonitorPhase;
|
|
565
|
+
status: 'ok' | 'stale' | 'gone';
|
|
566
|
+
homeTeamName?: string | null;
|
|
567
|
+
awayTeamName?: string | null;
|
|
568
|
+
competitionName?: string | null;
|
|
569
|
+
kickoffUtc?: string | null;
|
|
570
|
+
homeScore?: number | null;
|
|
571
|
+
awayScore?: number | null;
|
|
572
|
+
liveMinute?: number | null;
|
|
573
|
+
liveAddedTime?: number | null;
|
|
574
|
+
liveStatus?: string | null;
|
|
575
|
+
minuteLabel?: string | null;
|
|
576
|
+
events: LiveMonitorEvent[];
|
|
577
|
+
statRows: LiveMonitorStatRow[];
|
|
578
|
+
momentum: MomentumPoint[];
|
|
579
|
+
mainMarket?: MarketOddsCard | null;
|
|
580
|
+
homeCrestUrl?: string | null;
|
|
581
|
+
awayCrestUrl?: string | null;
|
|
582
|
+
asOfUtc: string;
|
|
583
|
+
[key: string]: unknown;
|
|
584
|
+
}
|
|
585
|
+
interface LiveMonitorMarket {
|
|
586
|
+
key: string;
|
|
587
|
+
status: 'ok' | 'stale' | 'gone';
|
|
588
|
+
phase: MonitorPhase;
|
|
589
|
+
homeScore?: number | null;
|
|
590
|
+
awayScore?: number | null;
|
|
591
|
+
minuteLabel?: string | null;
|
|
592
|
+
homeTeamName?: string | null;
|
|
593
|
+
awayTeamName?: string | null;
|
|
594
|
+
card?: MarketOddsCard | null;
|
|
595
|
+
history?: OddsMovementCard | null;
|
|
596
|
+
isSettled: boolean;
|
|
597
|
+
isSuspended: boolean;
|
|
598
|
+
asOfUtc: string;
|
|
599
|
+
[key: string]: unknown;
|
|
600
|
+
}
|
|
601
|
+
interface LiveMonitorSnapshot {
|
|
602
|
+
matches: LiveMonitorMatch[];
|
|
603
|
+
markets: LiveMonitorMarket[];
|
|
604
|
+
serverNowUtc: string;
|
|
605
|
+
nextPollSeconds: number;
|
|
606
|
+
}
|
|
515
607
|
interface EventEnvelope<TType extends string, TData> {
|
|
516
608
|
type: TType;
|
|
517
609
|
requestId: string;
|
|
@@ -626,6 +718,7 @@ declare class Conversation {
|
|
|
626
718
|
send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle;
|
|
627
719
|
sendSignal(input: SignalInput): Promise<void>;
|
|
628
720
|
getLiveDashboard(): Promise<ClubFanDashboardPayload | null>;
|
|
721
|
+
getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null>;
|
|
629
722
|
}
|
|
630
723
|
|
|
631
724
|
declare class StatsWidgetClient {
|
|
@@ -645,4 +738,4 @@ interface NdjsonParser {
|
|
|
645
738
|
}
|
|
646
739
|
declare function createNdjsonParser(): NdjsonParser;
|
|
647
740
|
|
|
648
|
-
export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, 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 FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, 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 LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, 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, WidgetSdkError, createNdjsonParser, isAddToSlipResult };
|
|
741
|
+
export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, 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 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 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, WidgetSdkError, createNdjsonParser, isAddToSlipResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -108,14 +108,21 @@ interface ClubFanDashboardPrefillCard extends ClubFanDashboardCardBase {
|
|
|
108
108
|
actionType: string;
|
|
109
109
|
rank: number;
|
|
110
110
|
}
|
|
111
|
+
interface FormMatch {
|
|
112
|
+
result: 'W' | 'D' | 'L';
|
|
113
|
+
teamScore: number;
|
|
114
|
+
oppScore: number;
|
|
115
|
+
teamIsHome: boolean;
|
|
116
|
+
opponentCrestUrl?: string | null;
|
|
117
|
+
}
|
|
111
118
|
interface FixtureCardData {
|
|
112
119
|
homeName: string;
|
|
113
120
|
awayName: string;
|
|
114
121
|
competition: string;
|
|
115
122
|
kickoffUnix: number;
|
|
116
123
|
venue?: string | null;
|
|
117
|
-
homeForm:
|
|
118
|
-
awayForm:
|
|
124
|
+
homeForm: FormMatch[];
|
|
125
|
+
awayForm: FormMatch[];
|
|
119
126
|
h2H?: ClubFanDashboardHeadToHead | null;
|
|
120
127
|
fact?: string | null;
|
|
121
128
|
homeCrestUrl?: string | null;
|
|
@@ -443,6 +450,7 @@ interface BettingInsight {
|
|
|
443
450
|
competitionImagePath?: string;
|
|
444
451
|
kickoffUtc?: string;
|
|
445
452
|
isMarketFloor?: boolean;
|
|
453
|
+
pinEnabled?: boolean;
|
|
446
454
|
[key: string]: unknown;
|
|
447
455
|
}
|
|
448
456
|
interface BettingInsightEventData {
|
|
@@ -477,6 +485,7 @@ interface MarketOddsCard {
|
|
|
477
485
|
rows?: MarketOddsRow[];
|
|
478
486
|
disclaimer?: string | null;
|
|
479
487
|
addToSlipEnabled?: boolean;
|
|
488
|
+
pinEnabled?: boolean;
|
|
480
489
|
[key: string]: unknown;
|
|
481
490
|
}
|
|
482
491
|
interface MarketOddsEventData {
|
|
@@ -507,11 +516,94 @@ interface OddsMovementCard {
|
|
|
507
516
|
excludedSuspendedCount?: number;
|
|
508
517
|
disclaimer?: string | null;
|
|
509
518
|
isSuspended?: boolean;
|
|
519
|
+
pinEnabled?: boolean;
|
|
520
|
+
matchOddsId?: number | null;
|
|
510
521
|
[key: string]: unknown;
|
|
511
522
|
}
|
|
512
523
|
interface OddsMovementEventData {
|
|
513
524
|
card: OddsMovementCard;
|
|
514
525
|
}
|
|
526
|
+
type PinKind = 'match' | 'market' | 'selection';
|
|
527
|
+
interface PinRef {
|
|
528
|
+
key: string;
|
|
529
|
+
kind: PinKind;
|
|
530
|
+
matchId: number;
|
|
531
|
+
marketDeveloperName?: string;
|
|
532
|
+
line?: string | null;
|
|
533
|
+
selectionLabel?: string;
|
|
534
|
+
matchOddsId?: number | null;
|
|
535
|
+
withHistory?: boolean;
|
|
536
|
+
}
|
|
537
|
+
interface LiveMonitorStatPrice {
|
|
538
|
+
marketDeveloperName: string;
|
|
539
|
+
marketLabel: string;
|
|
540
|
+
selectionLabel: string;
|
|
541
|
+
price?: number | null;
|
|
542
|
+
matchOddsId?: number | null;
|
|
543
|
+
isSuspended: boolean;
|
|
544
|
+
addToSlipEnabled: boolean;
|
|
545
|
+
}
|
|
546
|
+
interface LiveMonitorStatRow {
|
|
547
|
+
label: string;
|
|
548
|
+
homeValue: string;
|
|
549
|
+
awayValue: string;
|
|
550
|
+
homeNum: number;
|
|
551
|
+
awayNum: number;
|
|
552
|
+
market?: LiveMonitorStatPrice | null;
|
|
553
|
+
}
|
|
554
|
+
interface LiveMonitorEvent {
|
|
555
|
+
minuteLabel: string;
|
|
556
|
+
text: string;
|
|
557
|
+
type: 'goal' | 'yellow' | 'red' | 'sub' | 'other';
|
|
558
|
+
side: 'home' | 'away';
|
|
559
|
+
player?: string | null;
|
|
560
|
+
}
|
|
561
|
+
type MonitorPhase = 'preMatch' | 'live' | 'fullTime' | 'postponed' | 'gone';
|
|
562
|
+
interface LiveMonitorMatch {
|
|
563
|
+
matchId: number;
|
|
564
|
+
phase: MonitorPhase;
|
|
565
|
+
status: 'ok' | 'stale' | 'gone';
|
|
566
|
+
homeTeamName?: string | null;
|
|
567
|
+
awayTeamName?: string | null;
|
|
568
|
+
competitionName?: string | null;
|
|
569
|
+
kickoffUtc?: string | null;
|
|
570
|
+
homeScore?: number | null;
|
|
571
|
+
awayScore?: number | null;
|
|
572
|
+
liveMinute?: number | null;
|
|
573
|
+
liveAddedTime?: number | null;
|
|
574
|
+
liveStatus?: string | null;
|
|
575
|
+
minuteLabel?: string | null;
|
|
576
|
+
events: LiveMonitorEvent[];
|
|
577
|
+
statRows: LiveMonitorStatRow[];
|
|
578
|
+
momentum: MomentumPoint[];
|
|
579
|
+
mainMarket?: MarketOddsCard | null;
|
|
580
|
+
homeCrestUrl?: string | null;
|
|
581
|
+
awayCrestUrl?: string | null;
|
|
582
|
+
asOfUtc: string;
|
|
583
|
+
[key: string]: unknown;
|
|
584
|
+
}
|
|
585
|
+
interface LiveMonitorMarket {
|
|
586
|
+
key: string;
|
|
587
|
+
status: 'ok' | 'stale' | 'gone';
|
|
588
|
+
phase: MonitorPhase;
|
|
589
|
+
homeScore?: number | null;
|
|
590
|
+
awayScore?: number | null;
|
|
591
|
+
minuteLabel?: string | null;
|
|
592
|
+
homeTeamName?: string | null;
|
|
593
|
+
awayTeamName?: string | null;
|
|
594
|
+
card?: MarketOddsCard | null;
|
|
595
|
+
history?: OddsMovementCard | null;
|
|
596
|
+
isSettled: boolean;
|
|
597
|
+
isSuspended: boolean;
|
|
598
|
+
asOfUtc: string;
|
|
599
|
+
[key: string]: unknown;
|
|
600
|
+
}
|
|
601
|
+
interface LiveMonitorSnapshot {
|
|
602
|
+
matches: LiveMonitorMatch[];
|
|
603
|
+
markets: LiveMonitorMarket[];
|
|
604
|
+
serverNowUtc: string;
|
|
605
|
+
nextPollSeconds: number;
|
|
606
|
+
}
|
|
515
607
|
interface EventEnvelope<TType extends string, TData> {
|
|
516
608
|
type: TType;
|
|
517
609
|
requestId: string;
|
|
@@ -626,6 +718,7 @@ declare class Conversation {
|
|
|
626
718
|
send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle;
|
|
627
719
|
sendSignal(input: SignalInput): Promise<void>;
|
|
628
720
|
getLiveDashboard(): Promise<ClubFanDashboardPayload | null>;
|
|
721
|
+
getLiveMonitor(pins: PinRef[]): Promise<LiveMonitorSnapshot | null>;
|
|
629
722
|
}
|
|
630
723
|
|
|
631
724
|
declare class StatsWidgetClient {
|
|
@@ -645,4 +738,4 @@ interface NdjsonParser {
|
|
|
645
738
|
}
|
|
646
739
|
declare function createNdjsonParser(): NdjsonParser;
|
|
647
740
|
|
|
648
|
-
export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, 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 FetchLike, type FixtureCard, type FixtureCardData, ForbiddenError, 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 LiveScoreCard, type LiveScoreData, type LiveStatRow, type LiveStatsCard, type LiveStatsData, type LiveTimelineCard, type LiveTimelineData, type MarketOddsCard, type MarketOddsEventData, type MarketOddsRow, type NdjsonParser, NetworkError, type OddsMovementCard, type OddsMovementEventData, type OddsMovementPoint, ParseError, 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, WidgetSdkError, createNdjsonParser, isAddToSlipResult };
|
|
741
|
+
export { type ActionButtonEventData, type ActionsLoadingEventData, type AddToSlipHandler, type AddToSlipRejectReason, type AddToSlipResult, type AnswerEventData, AuthError, 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 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 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, WidgetSdkError, createNdjsonParser, isAddToSlipResult };
|
package/dist/index.js
CHANGED
|
@@ -91,6 +91,16 @@ async function getLiveDashboard(cfg) {
|
|
|
91
91
|
if (!res.ok) throw new Error(`live-dashboard ${res.status}`);
|
|
92
92
|
return await res.json();
|
|
93
93
|
}
|
|
94
|
+
async function postLiveMonitor(cfg, pins) {
|
|
95
|
+
const res = await cfg.fetch(endpoint(cfg, "live-monitor"), {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey },
|
|
98
|
+
body: JSON.stringify({ pins })
|
|
99
|
+
});
|
|
100
|
+
if (res.status === 404) return null;
|
|
101
|
+
if (!res.ok) throw new Error(`live-monitor ${res.status}`);
|
|
102
|
+
return await res.json();
|
|
103
|
+
}
|
|
94
104
|
|
|
95
105
|
// src/ndjson.ts
|
|
96
106
|
function parseLine(line) {
|
|
@@ -297,6 +307,9 @@ var Conversation = class {
|
|
|
297
307
|
getLiveDashboard() {
|
|
298
308
|
return getLiveDashboard(this.cfg);
|
|
299
309
|
}
|
|
310
|
+
getLiveMonitor(pins) {
|
|
311
|
+
return postLiveMonitor(this.cfg, pins);
|
|
312
|
+
}
|
|
300
313
|
};
|
|
301
314
|
|
|
302
315
|
// src/client.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/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 } 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 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","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 } from './events'\nimport { getLiveDashboard, 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","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { 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","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/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, 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 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","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, PinRef } from './events'\nimport { getLiveDashboard, postLiveMonitor, 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","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { 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","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":[]}
|