@sensiblestats/widget-sdk 0.58.0 → 0.59.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 +6 -0
- package/dist/index.cjs +27 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +27 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @sensiblestats/widget-sdk
|
|
2
2
|
|
|
3
|
+
## 0.59.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3b75853: The widget sends its version in an X-SS-Client header (widget-react/<version>) so the operator panel can show which version each brand runs. The SDK takes an optional `client` option and sends no header without it.
|
|
8
|
+
|
|
3
9
|
## 0.58.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -97,6 +97,11 @@ var ParseError = class extends WidgetSdkError {
|
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
// src/http.ts
|
|
100
|
+
function headersFor(cfg, json) {
|
|
101
|
+
const h = json ? { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey } : { "X-SS-Public-Key": cfg.publicKey };
|
|
102
|
+
if (cfg.client) h["X-SS-Client"] = cfg.client;
|
|
103
|
+
return h;
|
|
104
|
+
}
|
|
100
105
|
function endpoint(cfg, path) {
|
|
101
106
|
return `${cfg.baseUrl.replace(/\/+$/, "")}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`;
|
|
102
107
|
}
|
|
@@ -142,7 +147,7 @@ async function send(cfg, path, body, signal) {
|
|
|
142
147
|
try {
|
|
143
148
|
return await cfg.fetch(endpoint(cfg, path), {
|
|
144
149
|
method: "POST",
|
|
145
|
-
headers:
|
|
150
|
+
headers: headersFor(cfg, true),
|
|
146
151
|
body: JSON.stringify(body),
|
|
147
152
|
signal
|
|
148
153
|
});
|
|
@@ -168,7 +173,7 @@ function postEventsKeepalive(cfg, batch) {
|
|
|
168
173
|
try {
|
|
169
174
|
void cfg.fetch(endpoint(cfg, "events"), {
|
|
170
175
|
method: "POST",
|
|
171
|
-
headers:
|
|
176
|
+
headers: headersFor(cfg, true),
|
|
172
177
|
body: JSON.stringify(batch),
|
|
173
178
|
keepalive: true
|
|
174
179
|
}).catch(() => {
|
|
@@ -177,7 +182,7 @@ function postEventsKeepalive(cfg, batch) {
|
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
async function getLiveDashboard(cfg) {
|
|
180
|
-
const res = await cfg.fetch(endpoint(cfg, "live-dashboard"), { method: "GET", headers:
|
|
185
|
+
const res = await cfg.fetch(endpoint(cfg, "live-dashboard"), { method: "GET", headers: headersFor(cfg, false) });
|
|
181
186
|
if (res.status === 204) return null;
|
|
182
187
|
if (!res.ok) throw new Error(`live-dashboard ${res.status}`);
|
|
183
188
|
return await res.json();
|
|
@@ -187,7 +192,7 @@ async function postLiveMonitor(cfg, pins, locale) {
|
|
|
187
192
|
if (locale) body.locale = locale;
|
|
188
193
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor"), {
|
|
189
194
|
method: "POST",
|
|
190
|
-
headers:
|
|
195
|
+
headers: headersFor(cfg, true),
|
|
191
196
|
body: JSON.stringify(body)
|
|
192
197
|
});
|
|
193
198
|
if (res.status === 404) return null;
|
|
@@ -197,7 +202,7 @@ async function postLiveMonitor(cfg, pins, locale) {
|
|
|
197
202
|
async function postMarketOdds(cfg, matchId, marketDeveloperName) {
|
|
198
203
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/market"), {
|
|
199
204
|
method: "POST",
|
|
200
|
-
headers:
|
|
205
|
+
headers: headersFor(cfg, true),
|
|
201
206
|
body: JSON.stringify({ matchId, marketDeveloperName })
|
|
202
207
|
});
|
|
203
208
|
if (res.status === 404) return null;
|
|
@@ -207,7 +212,7 @@ async function postMarketOdds(cfg, matchId, marketDeveloperName) {
|
|
|
207
212
|
async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) {
|
|
208
213
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/schedule"), {
|
|
209
214
|
method: "POST",
|
|
210
|
-
headers:
|
|
215
|
+
headers: headersFor(cfg, true),
|
|
211
216
|
body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId })
|
|
212
217
|
});
|
|
213
218
|
if (res.status === 404) return null;
|
|
@@ -217,7 +222,7 @@ async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, an
|
|
|
217
222
|
async function postLeagueStar(cfg, competitionId, starred, operatorUserId, anonymousUserId) {
|
|
218
223
|
const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {
|
|
219
224
|
method: "POST",
|
|
220
|
-
headers:
|
|
225
|
+
headers: headersFor(cfg, true),
|
|
221
226
|
body: JSON.stringify({ starred, operatorUserId, anonymousUserId })
|
|
222
227
|
});
|
|
223
228
|
if (res.status === 404) return null;
|
|
@@ -227,7 +232,7 @@ async function postLeagueStar(cfg, competitionId, starred, operatorUserId, anony
|
|
|
227
232
|
async function postStates(cfg, matchIds) {
|
|
228
233
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/states"), {
|
|
229
234
|
method: "POST",
|
|
230
|
-
headers:
|
|
235
|
+
headers: headersFor(cfg, true),
|
|
231
236
|
body: JSON.stringify({ matchIds })
|
|
232
237
|
});
|
|
233
238
|
if (res.status === 404) return null;
|
|
@@ -239,19 +244,19 @@ function q(parts) {
|
|
|
239
244
|
return kept.length ? `?${kept.join("&")}` : "";
|
|
240
245
|
}
|
|
241
246
|
async function getGames(cfg, operatorUserId, gameDay) {
|
|
242
|
-
const res = await cfg.fetch(endpoint(cfg, "games" + q({ operatorUserId, gameDay })), { method: "GET", headers:
|
|
247
|
+
const res = await cfg.fetch(endpoint(cfg, "games" + q({ operatorUserId, gameDay })), { method: "GET", headers: headersFor(cfg, false) });
|
|
243
248
|
if (res.status === 404) return null;
|
|
244
249
|
if (!res.ok) throw new Error(`games ${res.status}`);
|
|
245
250
|
return await res.json();
|
|
246
251
|
}
|
|
247
252
|
async function getGameConfig(cfg, gameId, fixtureId, gameDay, locale) {
|
|
248
|
-
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: "GET", headers:
|
|
253
|
+
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: "GET", headers: headersFor(cfg, false) });
|
|
249
254
|
if (res.status === 404) return null;
|
|
250
255
|
if (!res.ok) throw new Error(`game-config ${res.status}`);
|
|
251
256
|
return await res.json();
|
|
252
257
|
}
|
|
253
258
|
async function getGameResult(cfg, gameId, operatorUserId, fixtureId, gameDay, locale) {
|
|
254
|
-
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: "GET", headers:
|
|
259
|
+
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: "GET", headers: headersFor(cfg, false) });
|
|
255
260
|
if (res.status === 404) return null;
|
|
256
261
|
if (!res.ok) throw new Error(`game-result ${res.status}`);
|
|
257
262
|
return await res.json();
|
|
@@ -259,7 +264,7 @@ async function getGameResult(cfg, gameId, operatorUserId, fixtureId, gameDay, lo
|
|
|
259
264
|
async function postPlay(cfg, gameId, body, locale) {
|
|
260
265
|
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {
|
|
261
266
|
method: "POST",
|
|
262
|
-
headers:
|
|
267
|
+
headers: headersFor(cfg, true),
|
|
263
268
|
body: JSON.stringify(body)
|
|
264
269
|
});
|
|
265
270
|
if (res.status === 404) return null;
|
|
@@ -267,49 +272,49 @@ async function postPlay(cfg, gameId, body, locale) {
|
|
|
267
272
|
return await res.json();
|
|
268
273
|
}
|
|
269
274
|
async function getLeaderboard(cfg, operatorUserId, week) {
|
|
270
|
-
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({ operatorUserId, week })), { method: "GET", headers:
|
|
275
|
+
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({ operatorUserId, week })), { method: "GET", headers: headersFor(cfg, false) });
|
|
271
276
|
if (res.status === 404) return null;
|
|
272
277
|
if (!res.ok) throw new Error(`leaderboard ${res.status}`);
|
|
273
278
|
return await res.json();
|
|
274
279
|
}
|
|
275
280
|
async function getClubFixtures(cfg, competitionId, limit) {
|
|
276
|
-
const res = await cfg.fetch(endpoint(cfg, "club/fixtures" + q({ competitionId, limit })), { method: "GET", headers:
|
|
281
|
+
const res = await cfg.fetch(endpoint(cfg, "club/fixtures" + q({ competitionId, limit })), { method: "GET", headers: headersFor(cfg, false) });
|
|
277
282
|
if (res.status === 404) return null;
|
|
278
283
|
if (!res.ok) throw new Error(`club-fixtures ${res.status}`);
|
|
279
284
|
return await res.json();
|
|
280
285
|
}
|
|
281
286
|
async function getClubStandings(cfg, competitionId) {
|
|
282
|
-
const res = await cfg.fetch(endpoint(cfg, "club/standings" + q({ competitionId })), { method: "GET", headers:
|
|
287
|
+
const res = await cfg.fetch(endpoint(cfg, "club/standings" + q({ competitionId })), { method: "GET", headers: headersFor(cfg, false) });
|
|
283
288
|
if (res.status === 404) return null;
|
|
284
289
|
if (!res.ok) throw new Error(`club-standings ${res.status}`);
|
|
285
290
|
return await res.json();
|
|
286
291
|
}
|
|
287
292
|
async function getClubSquad(cfg) {
|
|
288
|
-
const res = await cfg.fetch(endpoint(cfg, "club/squad"), { method: "GET", headers:
|
|
293
|
+
const res = await cfg.fetch(endpoint(cfg, "club/squad"), { method: "GET", headers: headersFor(cfg, false) });
|
|
289
294
|
if (res.status === 404) return null;
|
|
290
295
|
if (!res.ok) throw new Error(`club-squad ${res.status}`);
|
|
291
296
|
return await res.json();
|
|
292
297
|
}
|
|
293
298
|
async function getClubSquadStats(cfg) {
|
|
294
|
-
const res = await cfg.fetch(endpoint(cfg, "club/squad/stats"), { method: "GET", headers:
|
|
299
|
+
const res = await cfg.fetch(endpoint(cfg, "club/squad/stats"), { method: "GET", headers: headersFor(cfg, false) });
|
|
295
300
|
if (res.status === 404) return null;
|
|
296
301
|
if (!res.ok) throw new Error(`club-squad-stats ${res.status}`);
|
|
297
302
|
return await res.json();
|
|
298
303
|
}
|
|
299
304
|
async function getClubPlayerDetail(cfg, playerId) {
|
|
300
|
-
const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: "GET", headers:
|
|
305
|
+
const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: "GET", headers: headersFor(cfg, false) });
|
|
301
306
|
if (res.status === 404) return null;
|
|
302
307
|
if (!res.ok) throw new Error(`club-player ${res.status}`);
|
|
303
308
|
return await res.json();
|
|
304
309
|
}
|
|
305
310
|
async function getClubRecords(cfg, limit) {
|
|
306
|
-
const res = await cfg.fetch(endpoint(cfg, "club/records" + q({ limit })), { method: "GET", headers:
|
|
311
|
+
const res = await cfg.fetch(endpoint(cfg, "club/records" + q({ limit })), { method: "GET", headers: headersFor(cfg, false) });
|
|
307
312
|
if (res.status === 404) return null;
|
|
308
313
|
if (!res.ok) throw new Error(`club-records ${res.status}`);
|
|
309
314
|
return await res.json();
|
|
310
315
|
}
|
|
311
316
|
async function getPricePresets(cfg, locale, operatorUserId, options) {
|
|
312
|
-
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale, operatorUserId, pool: options?.pool })), { method: "GET", headers:
|
|
317
|
+
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale, operatorUserId, pool: options?.pool })), { method: "GET", headers: headersFor(cfg, false) });
|
|
313
318
|
if (res.status === 404) return null;
|
|
314
319
|
if (!res.ok) throw new Error(`price-presets ${res.status}`);
|
|
315
320
|
return await res.json();
|
|
@@ -719,7 +724,8 @@ var StatsWidgetClient = class {
|
|
|
719
724
|
operatorId: options.operatorId,
|
|
720
725
|
publicKey: options.publicKey,
|
|
721
726
|
baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
|
|
722
|
-
fetch: fetchImpl
|
|
727
|
+
fetch: fetchImpl,
|
|
728
|
+
client: options.client
|
|
723
729
|
};
|
|
724
730
|
}
|
|
725
731
|
chat(input, callbacks) {
|
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/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export { StatsWidgetClient } from './client'\nexport { Conversation } from './conversation'\nexport type { ChatCallbacks, ChatHandle } from './chat'\nexport { SIGNAL_TYPE_CODES, ENTITY_TYPE_CODES } from './signals'\nexport {\n WidgetSdkError, AuthError, ForbiddenError, RateLimitError, UpstreamError, NetworkError, ParseError,\n LimitError, LIMIT_CODES, isLimitCode,\n} from './errors'\nexport type { LimitCode, LimitDetails } from './errors'\nexport type {\n StatsWidgetClientOptions, FetchLike, UserContext, ChatInput, ChatGrounding, ChatPreset,\n SignalType, SignalEntityType, SignalInput,\n SlipSelection, AddToSlipRejectReason, AddToSlipResult, AddToSlipHandler,\n} from './types'\nexport { isAddToSlipResult } from './types'\nexport { createNdjsonParser } from './ndjson'\nexport type { NdjsonParser } from './ndjson'\nexport { createEventLogger } from './eventLog'\nexport type {\n WidgetEventName, WidgetEntityEventName, WidgetPopupEventName, WidgetPopupAskEventName, WidgetOpenEventName, WidgetEntityType, WidgetEventInput,\n WidgetPopupEventInput, WidgetPopupAskEventInput, WidgetOpenEventInput, WidgetLogInput, WireEvent, EventBatch, EventLoggerOptions, EventLogger,\n} from './eventLog'\nexport type {\n ChatEvent, ProgressEventData, AnswerEventData, EntityCard, EntityCardStat, EntityCardScope, EntityCardEventData,\n ActionButtonEventData, IntentChipEventData, ActionsLoadingEventData,\n TurnCompleteEventData, StreamErrorEventData,\n BettingInsight, BettingInsightOdds, BettingInsightEventData,\n MarketOddsRow, MarketOddsCard, MarketOddsCardInsight, MarketOddsLiveBlock, MarketOddsEventData,\n ComboCard, ComboLeg, ComboReplacedLeg, ComboCardEventData,\n PresetPick, PresetSinglesCell, PresetComboCell, PresetMarketCell, PresetGrid, PresetGridOptions,\n OddsMovementPoint, OddsMovementCard, OddsMovementEventData,\n GreetingDashboard, GreetingDashboardTile, GreetingDashboardLayout, GreetingDashboardSpan, GreetingDashboardTileEmphasis, 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, HeadToHead, FormAndH2H,\n LiveMonitorStatPrice, LiveMonitorStatRow, LiveMonitorEvent,\n LiveMonitorFact, LiveMonitorMatch, LiveMonitorMarket, LiveMonitorSnapshot,\n AvailableMarket, MarketOddsBlock,\n ScheduleMatch, ScheduleGroup, SchedulePayload, LeagueStarResult, MatchState, StatesPayload,\n GameSummary, GameListPayload, GameStatePayload,\n SubmitPlayBody, SubmitPlayResult,\n GameResultPayload,\n LeaderboardRow, AllTimeRow, LeaderboardPayload, LeaderboardChampion,\n ClubFixture, ClubFixturesPayload, ClubStandingRow, ClubStandingsPayload, ClubSquadPlayer, ClubSquadPayload,\n ClubPlayerSeasonStats, ClubSquadStatsPayload, ClubPlayerDetailPayload,\n ClubPlayerAvailability, ClubPlayerAvailabilityStatus, ClubNextFixture, ClubMatchLogRow, ClubPlayerPerformance, ClubPerformanceMetric, ClubRecordEntry, ClubRecordsPayload,\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}\n// B4 Q7: the codes a brand's limit refuses with. Any other 429 stays a plain RateLimitError.\nexport const LIMIT_CODES = ['daily_cap', 'quota_exhausted', 'assistant_paused'] as const\nexport type LimitCode = (typeof LIMIT_CODES)[number]\nexport function isLimitCode(code: unknown): code is LimitCode {\n return typeof code === 'string' && (LIMIT_CODES as readonly string[]).includes(code)\n}\nexport interface LimitDetails {\n limitCode: LimitCode\n resetsAt?: string\n /** The brand's or the built-in text, already in the user's language. */\n message?: string\n}\nexport class LimitError extends RateLimitError {\n readonly limitCode: LimitCode\n readonly resetsAt?: string\n readonly limitMessage?: string\n constructor(details: LimitDetails, retryAfter?: number) {\n super(retryAfter, details.message ?? 'Limit reached')\n this.limitCode = details.limitCode\n this.resetsAt = details.resetsAt\n this.limitMessage = details.message\n }\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, isLimitCode, LimitError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayBody, SubmitPlayResult,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\n// B4 Q7: a limit refusal is a 429 whose problem+json body names the limit. The gateway's own per-minute 429 sets\n// Retry-After without exposing it to browsers, so a missing header is normal: the body's retryAfterSeconds covers\n// it, and no countdown is shown when neither is present.\nexport async function chatError(res: Response): Promise<WidgetSdkError> {\n const base = toWidgetError(res.status, res.headers.get('Retry-After'))\n if (!(base instanceof RateLimitError)) return base\n let body: unknown\n try { body = await res.json() } catch { return base }\n if (typeof body !== 'object' || body === null) return base\n const b = body as Record<string, unknown>\n if (!isLimitCode(b.errorCode)) return base\n const text = (v: unknown): string | undefined => (typeof v === 'string' && v.trim() !== '' ? v : undefined)\n const header = res.headers.get('Retry-After')?.trim()\n const headerRetry = header != null && /^\\d+$/.test(header) ? Number(header) : undefined\n const bodyRetry = typeof b.retryAfterSeconds === 'number' && Number.isFinite(b.retryAfterSeconds) && b.retryAfterSeconds >= 0 ? b.retryAfterSeconds : undefined\n return new LimitError(\n { limitCode: b.errorCode, resetsAt: text(b.resetsAt), message: text(b.message) },\n headerRetry ?? bodyRetry,\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 await chatError(res)\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n const body: { pins: PinRef[]; locale?: string } = { pins }\n if (locale) body.locale = locale\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(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postLeagueStar(\n cfg: ResolvedConfig, competitionId: number, starred: boolean,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<LeagueStarResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ starred, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leagues/star ${res.status}`)\n return (await res.json()) as LeagueStarResult\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n\nfunction q(parts: Record<string, string | number | undefined>): string {\n const kept = Object.entries(parts)\n .filter(([, v]) => v !== undefined && v !== '')\n .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)\n return kept.length ? `?${kept.join('&')}` : ''\n}\n\nexport async function getGames(cfg: ResolvedConfig, operatorUserId?: string, gameDay?: string): Promise<GameListPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games' + q({ operatorUserId, gameDay })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`games ${res.status}`)\n return (await res.json()) as GameListPayload\n}\n\nexport async function getGameConfig(cfg: ResolvedConfig, gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-config ${res.status}`)\n return (await res.json()) as GameStatePayload\n}\n\nexport async function getGameResult(cfg: ResolvedConfig, gameId: string, operatorUserId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-result ${res.status}`)\n return (await res.json()) as GameResultPayload\n}\n\nexport async function postPlay(cfg: ResolvedConfig, gameId: string, body: SubmitPlayBody, locale?: string): Promise<SubmitPlayResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`play ${res.status}`)\n return (await res.json()) as SubmitPlayResult\n}\n\nexport async function getLeaderboard(cfg: ResolvedConfig, operatorUserId?: string, week?: string): Promise<LeaderboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games/leaderboard' + q({ operatorUserId, week })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leaderboard ${res.status}`)\n return (await res.json()) as LeaderboardPayload\n}\n\nexport async function getClubFixtures(cfg: ResolvedConfig, competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/fixtures' + q({ competitionId, limit })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-fixtures ${res.status}`)\n return (await res.json()) as ClubFixturesPayload\n}\n\nexport async function getClubStandings(cfg: ResolvedConfig, competitionId?: number): Promise<ClubStandingsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/standings' + q({ competitionId })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-standings ${res.status}`)\n return (await res.json()) as ClubStandingsPayload\n}\n\nexport async function getClubSquad(cfg: ResolvedConfig): Promise<ClubSquadPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad ${res.status}`)\n return (await res.json()) as ClubSquadPayload\n}\n\nexport async function getClubSquadStats(cfg: ResolvedConfig): Promise<ClubSquadStatsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad/stats'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad-stats ${res.status}`)\n return (await res.json()) as ClubSquadStatsPayload\n}\n\nexport async function getClubPlayerDetail(cfg: ResolvedConfig, playerId: number): Promise<ClubPlayerDetailPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-player ${res.status}`)\n return (await res.json()) as ClubPlayerDetailPayload\n}\n\nexport async function getClubRecords(cfg: ResolvedConfig, limit?: number): Promise<ClubRecordsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/records' + q({ limit })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-records ${res.status}`)\n return (await res.json()) as ClubRecordsPayload\n}\n\n// Onboarding presets stage 2 (contract §1). 404 is the definitive \"no presets for this visitor\"\n// answer (flag off, not a betting operator, or cool-off). 503 and every other non-ok status throw:\n// the widget keeps any grid it already has and asks again on the next panel open.\n// operatorUserId is optional, passed as the games routes pass it: the cool-off check (D3) needs it,\n// and a request without it is an anonymous visitor.\nexport async function getPricePresets(\n cfg: ResolvedConfig, locale: string, operatorUserId?: string, options?: PresetGridOptions,\n): Promise<PresetGrid | null> {\n const res = await cfg.fetch(endpoint(cfg, 'price-presets' + q({ locale, operatorUserId, pool: options?.pool })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`price-presets ${res.status}`)\n return (await res.json()) as PresetGrid\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayResult,\n} from './events'\nimport {\n getClubFixtures, getClubPlayerDetail, getClubRecords, getClubSquad, getClubSquadStats, getClubStandings, getGameConfig, getGameResult, getGames, getLeaderboard, getLiveDashboard, getPricePresets,\n postLeagueStar, postLiveMonitor, postMarketOdds, postPlay, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins, locale)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getPricePresets(locale: string, options?: PresetGridOptions): Promise<PresetGrid | null> {\n return getPricePresets(this.cfg, locale, this.context?.operatorUserId, options)\n }\n\n getSchedule(\n localDate: string, utcOffsetMinutes: number, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId)\n }\n\n starLeague(\n competitionId: number, starred: boolean, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<LeagueStarResult | null> {\n return postLeagueStar(this.cfg, competitionId, starred, operatorUserId, anonymousUserId)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n\n getGames(gameDay?: string): Promise<GameListPayload | null> {\n return getGames(this.cfg, this.context?.operatorUserId, gameDay)\n }\n\n getGameConfig(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n return getGameConfig(this.cfg, gameId, fixtureId, gameDay, locale)\n }\n\n getGameResult(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return getGameResult(this.cfg, gameId, operatorUserId, fixtureId, gameDay, locale)\n }\n\n postPlay(gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string): Promise<SubmitPlayResult | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return postPlay(this.cfg, gameId, { operatorUserId, gameDay, answerJson, fixtureId }, locale)\n }\n\n getLeaderboard(week?: string): Promise<LeaderboardPayload | null> {\n return getLeaderboard(this.cfg, this.context?.operatorUserId, week)\n }\n\n getClubFixtures(competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n return getClubFixtures(this.cfg, competitionId, limit)\n }\n getClubStandings(competitionId?: number): Promise<ClubStandingsPayload | null> {\n return getClubStandings(this.cfg, competitionId)\n }\n getClubSquad(): Promise<ClubSquadPayload | null> {\n return getClubSquad(this.cfg)\n }\n getClubSquadStats(): Promise<ClubSquadStatsPayload | null> {\n return getClubSquadStats(this.cfg)\n }\n getClubPlayerDetail(playerId: number): Promise<ClubPlayerDetailPayload | null> {\n return getClubPlayerDetail(this.cfg, playerId)\n }\n getClubRecords(limit?: number): Promise<ClubRecordsPayload | null> {\n return getClubRecords(this.cfg, limit)\n }\n}\n","export type WidgetEntityEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n | 'slip_remove' | 'bet_placed' | 'match_view' | 'match_open'\n\nexport type WidgetPopupEventName = 'popup_shown' | 'popup_opened' | 'popup_dismissed'\n\nexport type WidgetPopupAskEventName = 'popup_ask_tap'\n\nexport type WidgetOpenEventName = 'widget_open'\n\nexport type WidgetEventName = WidgetEntityEventName | WidgetPopupEventName | WidgetPopupAskEventName | WidgetOpenEventName\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEntityEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n /** Football match id of the slip selection (slip_click / slip_result). */\n matchId?: number\n /** The raw odds label as stored (\"Home\", \"Over\", \"Home/Draw\"), never a joined display string. Max 64. */\n selection?: string\n /** The raw line (\"2.5\"). Max 32; omit when empty. */\n line?: string\n /** Decimal price shown when the selection was added. */\n odds?: number\n}\n\n/** Launcher popup telemetry: counted server-side, never tied to an entity. */\nexport type WidgetPopupEventInput =\n { name: WidgetPopupEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\n/** A tap on one of the launcher bubble's asks. `outcome` carries the ask's position, \"0\" or \"1\"\n * (contract §5): the gateway forwards only the fields of its own event model, and outcome is its\n * one free-text field. */\nexport type WidgetPopupAskEventInput =\n { name: WidgetPopupAskEventName; outcome: string } & { [K in Exclude<keyof WidgetEventInput, 'name' | 'outcome'>]?: never }\n\n/** The panel opening: entity-free, each open is added to the user's count for the day. */\nexport type WidgetOpenEventInput =\n { name: WidgetOpenEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\nexport type WidgetLogInput = WidgetEventInput | WidgetPopupEventInput | WidgetPopupAskEventInput | WidgetOpenEventInput\n\nexport type WireEvent = WidgetLogInput & {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetLogInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n /** Undoes dispose(). React StrictMode runs an effect's cleanup and then its setup again on the\n * same logger, so the widget's setup has to be able to bring a disposed logger back. */\n resume(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set([\n 'pin_add', 'pin_remove', 'slip_click', 'slip_result', 'slip_remove', 'bet_placed',\n])\n\n// Queued without arming the batch timer: the event leaves with the next flush of any cause. A match\n// page view fires for every visitor, so it must never start a request of its own.\nconst DEFERRED: ReadonlySet<WidgetEventName> = new Set(['match_view'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetLogInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else if (!DEFERRED.has(input.name)) {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n resume(): void {\n this.disposed = false\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\n/** Onboarding presets stage 2 (contract §3): what a tool's Send asked for. Sent only from a tool's\n * Send, beside the full sentence in `message`. The server ignores it unless every value is valid. */\nexport interface ChatPreset {\n kind: 'max_price' | 'min_price' | 'combo' | 'market'\n /** max_price, min_price */\n price?: number\n /** max_price, min_price */\n count?: number\n /** combo */\n total?: number\n /** combo */\n legs?: number\n /** market */\n marketDeveloperName?: string\n /** The picks or legs the tool showed, in the order shown (R12: the answer reprices exactly these). */\n matchOddsIds: number[]\n /** The same picks' matchId, index for index with matchOddsIds (from the grid). */\n matchIds: number[]\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 /** Features this client can draw (e.g. \"price_presets\"). The server sends nothing that needs a\n * feature the list does not name; an absent list means today's responses. */\n clientCapabilities?: string[]\n /** Onboarding presets stage 2: set only by a preset tool's Send (contract §3). */\n preset?: ChatPreset\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;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;AAEO,IAAM,cAAc,CAAC,aAAa,mBAAmB,kBAAkB;AAEvE,SAAS,YAAY,MAAkC;AAC5D,SAAO,OAAO,SAAS,YAAa,YAAkC,SAAS,IAAI;AACrF;AAOO,IAAM,aAAN,cAAyB,eAAe;AAAA,EAI7C,YAAY,SAAuB,YAAqB;AACtD,UAAM,YAAY,QAAQ,WAAW,eAAe;AACpD,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AACxB,SAAK,eAAe,QAAQ;AAAA,EAC9B;AACF;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;;;ACxCA,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;AAKA,eAAsB,UAAU,KAAwC;AACtE,QAAM,OAAO,cAAc,IAAI,QAAQ,IAAI,QAAQ,IAAI,aAAa,CAAC;AACrE,MAAI,EAAE,gBAAgB,gBAAiB,QAAO;AAC9C,MAAI;AACJ,MAAI;AAAE,WAAO,MAAM,IAAI,KAAK;AAAA,EAAE,QAAQ;AAAE,WAAO;AAAA,EAAK;AACpD,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,IAAI;AACV,MAAI,CAAC,YAAY,EAAE,SAAS,EAAG,QAAO;AACtC,QAAM,OAAO,CAAC,MAAoC,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,KAAK,IAAI;AACjG,QAAM,SAAS,IAAI,QAAQ,IAAI,aAAa,GAAG,KAAK;AACpD,QAAM,cAAc,UAAU,QAAQ,QAAQ,KAAK,MAAM,IAAI,OAAO,MAAM,IAAI;AAC9E,QAAM,YAAY,OAAO,EAAE,sBAAsB,YAAY,OAAO,SAAS,EAAE,iBAAiB,KAAK,EAAE,qBAAqB,IAAI,EAAE,oBAAoB;AACtJ,SAAO,IAAI;AAAA,IACT,EAAE,WAAW,EAAE,WAAW,UAAU,KAAK,EAAE,QAAQ,GAAG,SAAS,KAAK,EAAE,OAAO,EAAE;AAAA,IAC/E,eAAe;AAAA,EACjB;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,MAAM,UAAU,GAAG;AAC1D,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,WAAW,KAAqB,OAA8B;AAClF,QAAM,MAAM,MAAM,KAAK,KAAK,UAAU,KAAK;AAC3C,MAAI,CAAC,IAAI,GAAI,OAAM,cAAc,IAAI,QAAQ,IAAI,QAAQ,IAAI,aAAa,CAAC;AAC7E;AAQO,SAAS,oBAAoB,KAAqB,OAAqB;AAC5E,MAAI;AACF,SAAK,IAAI,MAAM,SAAS,KAAK,QAAQ,GAAG;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,MAChF,MAAM,KAAK,UAAU,KAAK;AAAA,MAC1B,WAAW;AAAA,IACb,CAAC,EAAE,MAAM,MAAM;AAAA,IAA8D,CAAC;AAAA,EAChF,QAAQ;AAAA,EAER;AACF;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;AAKA,eAAsB,gBAAgB,KAAqB,MAAgB,QAAsD;AAC/H,QAAM,OAA4C,EAAE,KAAK;AACzD,MAAI,OAAQ,MAAK,SAAS;AAC1B,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,cAAc,GAAG;AAAA,IACzD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,gBAAgB,IAAI,MAAM,EAAE;AACzD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,eACpB,KAAqB,SAAiB,qBACL;AACjC,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,qBAAqB,GAAG;AAAA,IAChE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,EAAE,SAAS,oBAAoB,CAAC;AAAA,EACvD,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,EAAE;AAChE,SAAQ,MAAM,IAAI,KAAK;AACzB;AAIA,eAAsB,aACpB,KAAqB,WAAmB,kBACxC,gBAAyB,iBACQ;AACjC,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,uBAAuB,GAAG;AAAA,IAClE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,EAAE,WAAW,kBAAkB,gBAAgB,gBAAgB,CAAC;AAAA,EACvF,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,yBAAyB,IAAI,MAAM,EAAE;AAClE,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,eACpB,KAAqB,eAAuB,SAC5C,gBAAyB,iBACS;AAClC,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,WAAW,aAAa,OAAO,GAAG;AAAA,IAC1E,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,EAAE,SAAS,gBAAgB,gBAAgB,CAAC;AAAA,EACnE,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,gBAAgB,IAAI,MAAM,EAAE;AACzD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,WAAW,KAAqB,UAAmD;AACvG,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,qBAAqB,GAAG;AAAA,IAChE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,EAAE,SAAS,CAAC;AAAA,EACnC,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,EAAE;AAChE,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,SAAS,EAAE,OAA4D;AACrE,QAAM,OAAO,OAAO,QAAQ,KAAK,EAC9B,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,mBAAmB,OAAO,CAAC,CAAC,CAAC,EAAE;AAC1D,SAAO,KAAK,SAAS,IAAI,KAAK,KAAK,GAAG,CAAC,KAAK;AAC9C;AAEA,eAAsB,SAAS,KAAqB,gBAAyB,SAAmD;AAC9H,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,UAAU,EAAE,EAAE,gBAAgB,QAAQ,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AACrJ,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,SAAS,IAAI,MAAM,EAAE;AAClD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,cAAc,KAAqB,QAAgB,WAAoB,SAAkB,QAAmD;AAChK,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,SAAS,mBAAmB,MAAM,CAAC,KAAK,EAAE,EAAE,WAAW,SAAS,OAAO,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AACtL,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe,IAAI,MAAM,EAAE;AACxD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,cAAc,KAAqB,QAAgB,gBAAwB,WAAoB,SAAkB,QAAoD;AACzL,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,SAAS,mBAAmB,MAAM,CAAC,YAAY,EAAE,EAAE,gBAAgB,WAAW,SAAS,OAAO,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAC7M,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe,IAAI,MAAM,EAAE;AACxD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,SAAS,KAAqB,QAAgB,MAAsB,QAAmD;AAC3I,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,SAAS,mBAAmB,MAAM,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC,GAAG;AAAA,IACtG,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,mBAAmB,IAAI,UAAU;AAAA,IAChF,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE;AACjD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,eAAe,KAAqB,gBAAyB,MAAmD;AACpI,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,sBAAsB,EAAE,EAAE,gBAAgB,KAAK,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAC9J,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe,IAAI,MAAM,EAAE;AACxD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,gBAAgB,KAAqB,eAAwB,OAAqD;AACtI,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,kBAAkB,EAAE,EAAE,eAAe,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAC1J,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,iBAAiB,IAAI,MAAM,EAAE;AAC1D,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,iBAAiB,KAAqB,eAA8D;AACxH,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,mBAAmB,EAAE,EAAE,cAAc,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AACpJ,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,EAAE;AAC3D,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,aAAa,KAAuD;AACxF,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,YAAY,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AACzH,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,cAAc,IAAI,MAAM,EAAE;AACvD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,kBAAkB,KAA4D;AAClG,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,kBAAkB,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAC/H,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,oBAAoB,IAAI,MAAM,EAAE;AAC7D,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,oBAAoB,KAAqB,UAA2D;AACxH,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,eAAe,mBAAmB,OAAO,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAClK,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe,IAAI,MAAM,EAAE;AACxD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,eAAe,KAAqB,OAAoD;AAC5G,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,iBAAiB,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AAC1I,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,gBAAgB,IAAI,MAAM,EAAE;AACzD,SAAQ,MAAM,IAAI,KAAK;AACzB;AAOA,eAAsB,gBACpB,KAAqB,QAAgB,gBAAyB,SAClC;AAC5B,QAAM,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,kBAAkB,EAAE,EAAE,QAAQ,gBAAgB,MAAM,SAAS,KAAK,CAAC,CAAC,GAAG,EAAE,QAAQ,OAAO,SAAS,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC;AACjL,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,iBAAiB,IAAI,MAAM,EAAE;AAC1D,SAAQ,MAAM,IAAI,KAAK;AACzB;;;ACrRA,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;;;ACfO,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;AAAA,EAEA,eAAe,MAAgB,QAAsD;AACnF,WAAO,gBAAgB,KAAK,KAAK,MAAM,MAAM;AAAA,EAC/C;AAAA,EAEA,cAAc,SAAiB,qBAA8D;AAC3F,WAAO,eAAe,KAAK,KAAK,SAAS,mBAAmB;AAAA,EAC9D;AAAA,EAEA,gBAAgB,QAAgB,SAAyD;AACvF,WAAO,gBAAgB,KAAK,KAAK,QAAQ,KAAK,SAAS,gBAAgB,OAAO;AAAA,EAChF;AAAA,EAEA,YACE,WAAmB,kBAA0B,gBAAyB,iBACrC;AACjC,WAAO,aAAa,KAAK,KAAK,WAAW,kBAAkB,gBAAgB,eAAe;AAAA,EAC5F;AAAA,EAEA,WACE,eAAuB,SAAkB,gBAAyB,iBAChC;AAClC,WAAO,eAAe,KAAK,KAAK,eAAe,SAAS,gBAAgB,eAAe;AAAA,EACzF;AAAA,EAEA,UAAU,UAAmD;AAC3D,WAAO,WAAW,KAAK,KAAK,QAAQ;AAAA,EACtC;AAAA,EAEA,SAAS,SAAmD;AAC1D,WAAO,SAAS,KAAK,KAAK,KAAK,SAAS,gBAAgB,OAAO;AAAA,EACjE;AAAA,EAEA,cAAc,QAAgB,WAAoB,SAAkB,QAAmD;AACrH,WAAO,cAAc,KAAK,KAAK,QAAQ,WAAW,SAAS,MAAM;AAAA,EACnE;AAAA,EAEA,cAAc,QAAgB,WAAoB,SAAkB,QAAoD;AACtH,UAAM,iBAAiB,KAAK,SAAS;AACrC,QAAI,CAAC,eAAgB,QAAO,QAAQ,QAAQ,IAAI;AAChD,WAAO,cAAc,KAAK,KAAK,QAAQ,gBAAgB,WAAW,SAAS,MAAM;AAAA,EACnF;AAAA,EAEA,SAAS,QAAgB,YAAoB,SAAiB,WAAoB,QAAmD;AACnI,UAAM,iBAAiB,KAAK,SAAS;AACrC,QAAI,CAAC,eAAgB,QAAO,QAAQ,QAAQ,IAAI;AAChD,WAAO,SAAS,KAAK,KAAK,QAAQ,EAAE,gBAAgB,SAAS,YAAY,UAAU,GAAG,MAAM;AAAA,EAC9F;AAAA,EAEA,eAAe,MAAmD;AAChE,WAAO,eAAe,KAAK,KAAK,KAAK,SAAS,gBAAgB,IAAI;AAAA,EACpE;AAAA,EAEA,gBAAgB,eAAwB,OAAqD;AAC3F,WAAO,gBAAgB,KAAK,KAAK,eAAe,KAAK;AAAA,EACvD;AAAA,EACA,iBAAiB,eAA8D;AAC7E,WAAO,iBAAiB,KAAK,KAAK,aAAa;AAAA,EACjD;AAAA,EACA,eAAiD;AAC/C,WAAO,aAAa,KAAK,GAAG;AAAA,EAC9B;AAAA,EACA,oBAA2D;AACzD,WAAO,kBAAkB,KAAK,GAAG;AAAA,EACnC;AAAA,EACA,oBAAoB,UAA2D;AAC7E,WAAO,oBAAoB,KAAK,KAAK,QAAQ;AAAA,EAC/C;AAAA,EACA,eAAe,OAAoD;AACjE,WAAO,eAAe,KAAK,KAAK,KAAK;AAAA,EACvC;AACF;;;AClBA,IAAM,YAA0C,oBAAI,IAAI;AAAA,EACtD;AAAA,EAAW;AAAA,EAAc;AAAA,EAAc;AAAA,EAAe;AAAA,EAAe;AACvE,CAAC;AAID,IAAM,WAAyC,oBAAI,IAAI,CAAC,YAAY,CAAC;AAErE,IAAM,4BAA4B;AAClC,IAAM,oBAAoB;AAC1B,IAAM,uBAAuB;AAE7B,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,SAAS,gBAAwB;AAC/B,QAAM,IAAwB,WAAW;AACzC,MAAI,KAAK,OAAO,EAAE,eAAe,WAAY,QAAO,EAAE,WAAW;AACjE,SAAO,KAAK,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAC5E;AAEA,IAAM,kBAAN,MAA6C;AAAA,EAgB3C,YAA6B,MAA0B;AAA1B;AAf7B,SAAiB,YAAY,cAAc;AAM3C,SAAQ,QAAqB,CAAC;AAC9B,SAAQ,MAAM;AACd,SAAQ,UAAU;AAClB,SAAQ,UAAU;AAClB,SAAQ,WAA2F,CAAC;AACpG,SAAQ,QAA8C;AACtD,SAAQ,WAAiC;AACzC,SAAQ,WAAW;AAGjB,SAAK,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;AACvC,SAAK,kBAAkB,KAAK,mBAAmB;AAC/C,SAAK,WAAW,KAAK,YAAY;AACjC,SAAK,cAAc,KAAK,eAAe;AAAA,EACzC;AAAA,EAEA,IAAI,OAA6B;AAC/B,QAAI,KAAK,SAAU;AACnB,UAAM,QAAmB,EAAE,GAAG,OAAO,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AACrE,SAAK,MAAM,KAAK,KAAK;AACrB,QAAI,UAAU,IAAI,MAAM,IAAI,GAAG;AAC7B,WAAK,QAAQ;AAAA,IACf,WAAW,KAAK,MAAM,UAAU,KAAK,UAAU;AAC7C,WAAK,QAAQ;AAAA,IACf,WAAW,CAAC,SAAS,IAAI,MAAM,IAAI,GAAG;AACpC,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,YAAY,IAA0F;AACpG,SAAK,WAAW,EAAE,GAAG,KAAK,UAAU,GAAG,GAAG;AAAA,EAC5C;AAAA,EAEA,MAAM,WAA0B;AAC9B,QAAI,KAAK,SAAU,OAAM,KAAK;AAC9B,QAAI,KAAK,MAAM,SAAS,EAAG,OAAM,KAAK,QAAQ;AAAA,EAChD;AAAA,EAEA,cAAoB;AAClB,SAAK,WAAW;AAChB,UAAM,QAAQ,KAAK,WAAW;AAC9B,QAAI,UAAU,KAAM;AACpB,SAAK,KAAK,eAAe,KAAK;AAAA,EAChC;AAAA,EAEA,UAAgB;AACd,SAAK,WAAW;AAChB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,SAAe;AACb,SAAK,WAAW;AAAA,EAClB;AAAA,EAEQ,WAAiB;AACvB,QAAI,KAAK,UAAU,KAAM;AACzB,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,QAAQ;AACb,WAAK,QAAQ;AAAA,IACf,GAAG,KAAK,eAAe;AAAA,EACzB;AAAA,EAEQ,aAAmB;AACzB,QAAI,KAAK,UAAU,KAAM;AACzB,iBAAa,KAAK,KAAK;AACvB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,UAAgB;AACtB,QAAI,KAAK,SAAU;AACnB,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW,KAAK,QAAQ,EAAE,QAAQ,MAAM;AAC3C,WAAK,WAAW;AAKhB,UAAI,KAAK,MAAM,SAAS,EAAG,MAAK,QAAQ;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,aAAgC;AACtC,QAAI,KAAK,MAAM,WAAW,KAAK,KAAK,YAAY,KAAK,KAAK,YAAY,EAAG,QAAO;AAChF,UAAM,SAAS,KAAK;AACpB,SAAK,QAAQ,CAAC;AACd,UAAM,QAAoB,EAAE,GAAG,GAAG,WAAW,KAAK,WAAW,GAAG,KAAK,UAAU,OAAO;AACtF,QAAI,KAAK,UAAU,EAAG,OAAM,UAAU,KAAK;AAC3C,QAAI,KAAK,UAAU,EAAG,OAAM,UAAU,KAAK;AAC3C,SAAK,UAAU;AACf,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,UAAyB;AACrC,SAAK,WAAW;AAChB,UAAM,QAAQ,KAAK,WAAW;AAC9B,QAAI,UAAU,KAAM;AACpB,aAAS,UAAU,GAAG,WAAW,KAAK,aAAa,WAAW;AAC5D,UAAI;AACF,cAAM,KAAK,KAAK,MAAM,KAAK;AAC3B;AAAA,MACF,QAAQ;AACN,aAAK;AACL,YAAI,WAAW,KAAK,aAAa;AAC/B,eAAK,WAAW,MAAM,OAAO;AAC7B;AAAA,QACF;AACA,cAAM,MAAM,KAAK,UAAU,EAAE;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,MAAuC;AACvE,SAAO,IAAI,gBAAgB,IAAI;AACjC;;;AChPA,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;AAAA,EAEA,kBAAkB,UAAwG;AACxH,UAAM,SAAS,kBAAkB;AAAA,MAC/B,OAAO,CAAC,UAAU,WAAW,KAAK,KAAK,KAAK;AAAA,MAC5C,gBAAgB,CAAC,UAAU,oBAAoB,KAAK,KAAK,KAAK;AAAA,IAChE,CAAC;AACD,QAAI,SAAU,QAAO,YAAY,QAAQ;AACzC,WAAO;AAAA,EACT;AACF;;;ACiEA,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/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export { StatsWidgetClient } from './client'\nexport { Conversation } from './conversation'\nexport type { ChatCallbacks, ChatHandle } from './chat'\nexport { SIGNAL_TYPE_CODES, ENTITY_TYPE_CODES } from './signals'\nexport {\n WidgetSdkError, AuthError, ForbiddenError, RateLimitError, UpstreamError, NetworkError, ParseError,\n LimitError, LIMIT_CODES, isLimitCode,\n} from './errors'\nexport type { LimitCode, LimitDetails } from './errors'\nexport type {\n StatsWidgetClientOptions, FetchLike, UserContext, ChatInput, ChatGrounding, ChatPreset,\n SignalType, SignalEntityType, SignalInput,\n SlipSelection, AddToSlipRejectReason, AddToSlipResult, AddToSlipHandler,\n} from './types'\nexport { isAddToSlipResult } from './types'\nexport { createNdjsonParser } from './ndjson'\nexport type { NdjsonParser } from './ndjson'\nexport { createEventLogger } from './eventLog'\nexport type {\n WidgetEventName, WidgetEntityEventName, WidgetPopupEventName, WidgetPopupAskEventName, WidgetOpenEventName, WidgetEntityType, WidgetEventInput,\n WidgetPopupEventInput, WidgetPopupAskEventInput, WidgetOpenEventInput, WidgetLogInput, WireEvent, EventBatch, EventLoggerOptions, EventLogger,\n} from './eventLog'\nexport type {\n ChatEvent, ProgressEventData, AnswerEventData, EntityCard, EntityCardStat, EntityCardScope, EntityCardEventData,\n ActionButtonEventData, IntentChipEventData, ActionsLoadingEventData,\n TurnCompleteEventData, StreamErrorEventData,\n BettingInsight, BettingInsightOdds, BettingInsightEventData,\n MarketOddsRow, MarketOddsCard, MarketOddsCardInsight, MarketOddsLiveBlock, MarketOddsEventData,\n ComboCard, ComboLeg, ComboReplacedLeg, ComboCardEventData,\n PresetPick, PresetSinglesCell, PresetComboCell, PresetMarketCell, PresetGrid, PresetGridOptions,\n OddsMovementPoint, OddsMovementCard, OddsMovementEventData,\n GreetingDashboard, GreetingDashboardTile, GreetingDashboardLayout, GreetingDashboardSpan, GreetingDashboardTileEmphasis, 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, HeadToHead, FormAndH2H,\n LiveMonitorStatPrice, LiveMonitorStatRow, LiveMonitorEvent,\n LiveMonitorFact, LiveMonitorMatch, LiveMonitorMarket, LiveMonitorSnapshot,\n AvailableMarket, MarketOddsBlock,\n ScheduleMatch, ScheduleGroup, SchedulePayload, LeagueStarResult, MatchState, StatesPayload,\n GameSummary, GameListPayload, GameStatePayload,\n SubmitPlayBody, SubmitPlayResult,\n GameResultPayload,\n LeaderboardRow, AllTimeRow, LeaderboardPayload, LeaderboardChampion,\n ClubFixture, ClubFixturesPayload, ClubStandingRow, ClubStandingsPayload, ClubSquadPlayer, ClubSquadPayload,\n ClubPlayerSeasonStats, ClubSquadStatsPayload, ClubPlayerDetailPayload,\n ClubPlayerAvailability, ClubPlayerAvailabilityStatus, ClubNextFixture, ClubMatchLogRow, ClubPlayerPerformance, ClubPerformanceMetric, ClubRecordEntry, ClubRecordsPayload,\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}\n// B4 Q7: the codes a brand's limit refuses with. Any other 429 stays a plain RateLimitError.\nexport const LIMIT_CODES = ['daily_cap', 'quota_exhausted', 'assistant_paused'] as const\nexport type LimitCode = (typeof LIMIT_CODES)[number]\nexport function isLimitCode(code: unknown): code is LimitCode {\n return typeof code === 'string' && (LIMIT_CODES as readonly string[]).includes(code)\n}\nexport interface LimitDetails {\n limitCode: LimitCode\n resetsAt?: string\n /** The brand's or the built-in text, already in the user's language. */\n message?: string\n}\nexport class LimitError extends RateLimitError {\n readonly limitCode: LimitCode\n readonly resetsAt?: string\n readonly limitMessage?: string\n constructor(details: LimitDetails, retryAfter?: number) {\n super(retryAfter, details.message ?? 'Limit reached')\n this.limitCode = details.limitCode\n this.resetsAt = details.resetsAt\n this.limitMessage = details.message\n }\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, isLimitCode, LimitError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayBody, SubmitPlayResult,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n client?: string\n}\n\nexport function headersFor(cfg: ResolvedConfig, json: boolean): Record<string, string> {\n const h: Record<string, string> = json ? { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey } : { 'X-SS-Public-Key': cfg.publicKey }\n if (cfg.client) h['X-SS-Client'] = cfg.client\n return h\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\n// B4 Q7: a limit refusal is a 429 whose problem+json body names the limit. The gateway's own per-minute 429 sets\n// Retry-After without exposing it to browsers, so a missing header is normal: the body's retryAfterSeconds covers\n// it, and no countdown is shown when neither is present.\nexport async function chatError(res: Response): Promise<WidgetSdkError> {\n const base = toWidgetError(res.status, res.headers.get('Retry-After'))\n if (!(base instanceof RateLimitError)) return base\n let body: unknown\n try { body = await res.json() } catch { return base }\n if (typeof body !== 'object' || body === null) return base\n const b = body as Record<string, unknown>\n if (!isLimitCode(b.errorCode)) return base\n const text = (v: unknown): string | undefined => (typeof v === 'string' && v.trim() !== '' ? v : undefined)\n const header = res.headers.get('Retry-After')?.trim()\n const headerRetry = header != null && /^\\d+$/.test(header) ? Number(header) : undefined\n const bodyRetry = typeof b.retryAfterSeconds === 'number' && Number.isFinite(b.retryAfterSeconds) && b.retryAfterSeconds >= 0 ? b.retryAfterSeconds : undefined\n return new LimitError(\n { limitCode: b.errorCode, resetsAt: text(b.resetsAt), message: text(b.message) },\n headerRetry ?? bodyRetry,\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: headersFor(cfg, true),\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 await chatError(res)\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: headersFor(cfg, false) })\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[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n const body: { pins: PinRef[]; locale?: string } = { pins }\n if (locale) body.locale = locale\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postLeagueStar(\n cfg: ResolvedConfig, competitionId: number, starred: boolean,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<LeagueStarResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ starred, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leagues/star ${res.status}`)\n return (await res.json()) as LeagueStarResult\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n\nfunction q(parts: Record<string, string | number | undefined>): string {\n const kept = Object.entries(parts)\n .filter(([, v]) => v !== undefined && v !== '')\n .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)\n return kept.length ? `?${kept.join('&')}` : ''\n}\n\nexport async function getGames(cfg: ResolvedConfig, operatorUserId?: string, gameDay?: string): Promise<GameListPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games' + q({ operatorUserId, gameDay })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`games ${res.status}`)\n return (await res.json()) as GameListPayload\n}\n\nexport async function getGameConfig(cfg: ResolvedConfig, gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-config ${res.status}`)\n return (await res.json()) as GameStatePayload\n}\n\nexport async function getGameResult(cfg: ResolvedConfig, gameId: string, operatorUserId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-result ${res.status}`)\n return (await res.json()) as GameResultPayload\n}\n\nexport async function postPlay(cfg: ResolvedConfig, gameId: string, body: SubmitPlayBody, locale?: string): Promise<SubmitPlayResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`play ${res.status}`)\n return (await res.json()) as SubmitPlayResult\n}\n\nexport async function getLeaderboard(cfg: ResolvedConfig, operatorUserId?: string, week?: string): Promise<LeaderboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games/leaderboard' + q({ operatorUserId, week })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leaderboard ${res.status}`)\n return (await res.json()) as LeaderboardPayload\n}\n\nexport async function getClubFixtures(cfg: ResolvedConfig, competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/fixtures' + q({ competitionId, limit })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-fixtures ${res.status}`)\n return (await res.json()) as ClubFixturesPayload\n}\n\nexport async function getClubStandings(cfg: ResolvedConfig, competitionId?: number): Promise<ClubStandingsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/standings' + q({ competitionId })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-standings ${res.status}`)\n return (await res.json()) as ClubStandingsPayload\n}\n\nexport async function getClubSquad(cfg: ResolvedConfig): Promise<ClubSquadPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad'), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad ${res.status}`)\n return (await res.json()) as ClubSquadPayload\n}\n\nexport async function getClubSquadStats(cfg: ResolvedConfig): Promise<ClubSquadStatsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad/stats'), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad-stats ${res.status}`)\n return (await res.json()) as ClubSquadStatsPayload\n}\n\nexport async function getClubPlayerDetail(cfg: ResolvedConfig, playerId: number): Promise<ClubPlayerDetailPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-player ${res.status}`)\n return (await res.json()) as ClubPlayerDetailPayload\n}\n\nexport async function getClubRecords(cfg: ResolvedConfig, limit?: number): Promise<ClubRecordsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/records' + q({ limit })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-records ${res.status}`)\n return (await res.json()) as ClubRecordsPayload\n}\n\n// Onboarding presets stage 2 (contract §1). 404 is the definitive \"no presets for this visitor\"\n// answer (flag off, not a betting operator, or cool-off). 503 and every other non-ok status throw:\n// the widget keeps any grid it already has and asks again on the next panel open.\n// operatorUserId is optional, passed as the games routes pass it: the cool-off check (D3) needs it,\n// and a request without it is an anonymous visitor.\nexport async function getPricePresets(\n cfg: ResolvedConfig, locale: string, operatorUserId?: string, options?: PresetGridOptions,\n): Promise<PresetGrid | null> {\n const res = await cfg.fetch(endpoint(cfg, 'price-presets' + q({ locale, operatorUserId, pool: options?.pool })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`price-presets ${res.status}`)\n return (await res.json()) as PresetGrid\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayResult,\n} from './events'\nimport {\n getClubFixtures, getClubPlayerDetail, getClubRecords, getClubSquad, getClubSquadStats, getClubStandings, getGameConfig, getGameResult, getGames, getLeaderboard, getLiveDashboard, getPricePresets,\n postLeagueStar, postLiveMonitor, postMarketOdds, postPlay, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins, locale)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getPricePresets(locale: string, options?: PresetGridOptions): Promise<PresetGrid | null> {\n return getPricePresets(this.cfg, locale, this.context?.operatorUserId, options)\n }\n\n getSchedule(\n localDate: string, utcOffsetMinutes: number, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId)\n }\n\n starLeague(\n competitionId: number, starred: boolean, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<LeagueStarResult | null> {\n return postLeagueStar(this.cfg, competitionId, starred, operatorUserId, anonymousUserId)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n\n getGames(gameDay?: string): Promise<GameListPayload | null> {\n return getGames(this.cfg, this.context?.operatorUserId, gameDay)\n }\n\n getGameConfig(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n return getGameConfig(this.cfg, gameId, fixtureId, gameDay, locale)\n }\n\n getGameResult(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return getGameResult(this.cfg, gameId, operatorUserId, fixtureId, gameDay, locale)\n }\n\n postPlay(gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string): Promise<SubmitPlayResult | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return postPlay(this.cfg, gameId, { operatorUserId, gameDay, answerJson, fixtureId }, locale)\n }\n\n getLeaderboard(week?: string): Promise<LeaderboardPayload | null> {\n return getLeaderboard(this.cfg, this.context?.operatorUserId, week)\n }\n\n getClubFixtures(competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n return getClubFixtures(this.cfg, competitionId, limit)\n }\n getClubStandings(competitionId?: number): Promise<ClubStandingsPayload | null> {\n return getClubStandings(this.cfg, competitionId)\n }\n getClubSquad(): Promise<ClubSquadPayload | null> {\n return getClubSquad(this.cfg)\n }\n getClubSquadStats(): Promise<ClubSquadStatsPayload | null> {\n return getClubSquadStats(this.cfg)\n }\n getClubPlayerDetail(playerId: number): Promise<ClubPlayerDetailPayload | null> {\n return getClubPlayerDetail(this.cfg, playerId)\n }\n getClubRecords(limit?: number): Promise<ClubRecordsPayload | null> {\n return getClubRecords(this.cfg, limit)\n }\n}\n","export type WidgetEntityEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n | 'slip_remove' | 'bet_placed' | 'match_view' | 'match_open'\n\nexport type WidgetPopupEventName = 'popup_shown' | 'popup_opened' | 'popup_dismissed'\n\nexport type WidgetPopupAskEventName = 'popup_ask_tap'\n\nexport type WidgetOpenEventName = 'widget_open'\n\nexport type WidgetEventName = WidgetEntityEventName | WidgetPopupEventName | WidgetPopupAskEventName | WidgetOpenEventName\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEntityEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n /** Football match id of the slip selection (slip_click / slip_result). */\n matchId?: number\n /** The raw odds label as stored (\"Home\", \"Over\", \"Home/Draw\"), never a joined display string. Max 64. */\n selection?: string\n /** The raw line (\"2.5\"). Max 32; omit when empty. */\n line?: string\n /** Decimal price shown when the selection was added. */\n odds?: number\n}\n\n/** Launcher popup telemetry: counted server-side, never tied to an entity. */\nexport type WidgetPopupEventInput =\n { name: WidgetPopupEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\n/** A tap on one of the launcher bubble's asks. `outcome` carries the ask's position, \"0\" or \"1\"\n * (contract §5): the gateway forwards only the fields of its own event model, and outcome is its\n * one free-text field. */\nexport type WidgetPopupAskEventInput =\n { name: WidgetPopupAskEventName; outcome: string } & { [K in Exclude<keyof WidgetEventInput, 'name' | 'outcome'>]?: never }\n\n/** The panel opening: entity-free, each open is added to the user's count for the day. */\nexport type WidgetOpenEventInput =\n { name: WidgetOpenEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\nexport type WidgetLogInput = WidgetEventInput | WidgetPopupEventInput | WidgetPopupAskEventInput | WidgetOpenEventInput\n\nexport type WireEvent = WidgetLogInput & {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetLogInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n /** Undoes dispose(). React StrictMode runs an effect's cleanup and then its setup again on the\n * same logger, so the widget's setup has to be able to bring a disposed logger back. */\n resume(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set([\n 'pin_add', 'pin_remove', 'slip_click', 'slip_result', 'slip_remove', 'bet_placed',\n])\n\n// Queued without arming the batch timer: the event leaves with the next flush of any cause. A match\n// page view fires for every visitor, so it must never start a request of its own.\nconst DEFERRED: ReadonlySet<WidgetEventName> = new Set(['match_view'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetLogInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else if (!DEFERRED.has(input.name)) {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n resume(): void {\n this.disposed = false\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n client: options.client,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n /** Sent as X-SS-Client; set by widget-react. */\n client?: string\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\n/** Onboarding presets stage 2 (contract §3): what a tool's Send asked for. Sent only from a tool's\n * Send, beside the full sentence in `message`. The server ignores it unless every value is valid. */\nexport interface ChatPreset {\n kind: 'max_price' | 'min_price' | 'combo' | 'market'\n /** max_price, min_price */\n price?: number\n /** max_price, min_price */\n count?: number\n /** combo */\n total?: number\n /** combo */\n legs?: number\n /** market */\n marketDeveloperName?: string\n /** The picks or legs the tool showed, in the order shown (R12: the answer reprices exactly these). */\n matchOddsIds: number[]\n /** The same picks' matchId, index for index with matchOddsIds (from the grid). */\n matchIds: number[]\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 /** Features this client can draw (e.g. \"price_presets\"). The server sends nothing that needs a\n * feature the list does not name; an absent list means today's responses. */\n clientCapabilities?: string[]\n /** Onboarding presets stage 2: set only by a preset tool's Send (contract §3). */\n preset?: ChatPreset\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
|
@@ -1089,6 +1089,8 @@ interface StatsWidgetClientOptions {
|
|
|
1089
1089
|
baseUrl?: string;
|
|
1090
1090
|
/** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */
|
|
1091
1091
|
fetch?: FetchLike;
|
|
1092
|
+
/** Sent as X-SS-Client; set by widget-react. */
|
|
1093
|
+
client?: string;
|
|
1092
1094
|
}
|
|
1093
1095
|
interface UserContext {
|
|
1094
1096
|
operatorUserId?: string;
|
|
@@ -1188,6 +1190,7 @@ interface ResolvedConfig {
|
|
|
1188
1190
|
publicKey: string;
|
|
1189
1191
|
baseUrl: string;
|
|
1190
1192
|
fetch: FetchLike;
|
|
1193
|
+
client?: string;
|
|
1191
1194
|
}
|
|
1192
1195
|
|
|
1193
1196
|
interface ChatCallbacks {
|
package/dist/index.d.ts
CHANGED
|
@@ -1089,6 +1089,8 @@ interface StatsWidgetClientOptions {
|
|
|
1089
1089
|
baseUrl?: string;
|
|
1090
1090
|
/** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */
|
|
1091
1091
|
fetch?: FetchLike;
|
|
1092
|
+
/** Sent as X-SS-Client; set by widget-react. */
|
|
1093
|
+
client?: string;
|
|
1092
1094
|
}
|
|
1093
1095
|
interface UserContext {
|
|
1094
1096
|
operatorUserId?: string;
|
|
@@ -1188,6 +1190,7 @@ interface ResolvedConfig {
|
|
|
1188
1190
|
publicKey: string;
|
|
1189
1191
|
baseUrl: string;
|
|
1190
1192
|
fetch: FetchLike;
|
|
1193
|
+
client?: string;
|
|
1191
1194
|
}
|
|
1192
1195
|
|
|
1193
1196
|
interface ChatCallbacks {
|
package/dist/index.js
CHANGED
|
@@ -55,6 +55,11 @@ var ParseError = class extends WidgetSdkError {
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
// src/http.ts
|
|
58
|
+
function headersFor(cfg, json) {
|
|
59
|
+
const h = json ? { "Content-Type": "application/json", "X-SS-Public-Key": cfg.publicKey } : { "X-SS-Public-Key": cfg.publicKey };
|
|
60
|
+
if (cfg.client) h["X-SS-Client"] = cfg.client;
|
|
61
|
+
return h;
|
|
62
|
+
}
|
|
58
63
|
function endpoint(cfg, path) {
|
|
59
64
|
return `${cfg.baseUrl.replace(/\/+$/, "")}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`;
|
|
60
65
|
}
|
|
@@ -100,7 +105,7 @@ async function send(cfg, path, body, signal) {
|
|
|
100
105
|
try {
|
|
101
106
|
return await cfg.fetch(endpoint(cfg, path), {
|
|
102
107
|
method: "POST",
|
|
103
|
-
headers:
|
|
108
|
+
headers: headersFor(cfg, true),
|
|
104
109
|
body: JSON.stringify(body),
|
|
105
110
|
signal
|
|
106
111
|
});
|
|
@@ -126,7 +131,7 @@ function postEventsKeepalive(cfg, batch) {
|
|
|
126
131
|
try {
|
|
127
132
|
void cfg.fetch(endpoint(cfg, "events"), {
|
|
128
133
|
method: "POST",
|
|
129
|
-
headers:
|
|
134
|
+
headers: headersFor(cfg, true),
|
|
130
135
|
body: JSON.stringify(batch),
|
|
131
136
|
keepalive: true
|
|
132
137
|
}).catch(() => {
|
|
@@ -135,7 +140,7 @@ function postEventsKeepalive(cfg, batch) {
|
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
async function getLiveDashboard(cfg) {
|
|
138
|
-
const res = await cfg.fetch(endpoint(cfg, "live-dashboard"), { method: "GET", headers:
|
|
143
|
+
const res = await cfg.fetch(endpoint(cfg, "live-dashboard"), { method: "GET", headers: headersFor(cfg, false) });
|
|
139
144
|
if (res.status === 204) return null;
|
|
140
145
|
if (!res.ok) throw new Error(`live-dashboard ${res.status}`);
|
|
141
146
|
return await res.json();
|
|
@@ -145,7 +150,7 @@ async function postLiveMonitor(cfg, pins, locale) {
|
|
|
145
150
|
if (locale) body.locale = locale;
|
|
146
151
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor"), {
|
|
147
152
|
method: "POST",
|
|
148
|
-
headers:
|
|
153
|
+
headers: headersFor(cfg, true),
|
|
149
154
|
body: JSON.stringify(body)
|
|
150
155
|
});
|
|
151
156
|
if (res.status === 404) return null;
|
|
@@ -155,7 +160,7 @@ async function postLiveMonitor(cfg, pins, locale) {
|
|
|
155
160
|
async function postMarketOdds(cfg, matchId, marketDeveloperName) {
|
|
156
161
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/market"), {
|
|
157
162
|
method: "POST",
|
|
158
|
-
headers:
|
|
163
|
+
headers: headersFor(cfg, true),
|
|
159
164
|
body: JSON.stringify({ matchId, marketDeveloperName })
|
|
160
165
|
});
|
|
161
166
|
if (res.status === 404) return null;
|
|
@@ -165,7 +170,7 @@ async function postMarketOdds(cfg, matchId, marketDeveloperName) {
|
|
|
165
170
|
async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) {
|
|
166
171
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/schedule"), {
|
|
167
172
|
method: "POST",
|
|
168
|
-
headers:
|
|
173
|
+
headers: headersFor(cfg, true),
|
|
169
174
|
body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId })
|
|
170
175
|
});
|
|
171
176
|
if (res.status === 404) return null;
|
|
@@ -175,7 +180,7 @@ async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, an
|
|
|
175
180
|
async function postLeagueStar(cfg, competitionId, starred, operatorUserId, anonymousUserId) {
|
|
176
181
|
const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {
|
|
177
182
|
method: "POST",
|
|
178
|
-
headers:
|
|
183
|
+
headers: headersFor(cfg, true),
|
|
179
184
|
body: JSON.stringify({ starred, operatorUserId, anonymousUserId })
|
|
180
185
|
});
|
|
181
186
|
if (res.status === 404) return null;
|
|
@@ -185,7 +190,7 @@ async function postLeagueStar(cfg, competitionId, starred, operatorUserId, anony
|
|
|
185
190
|
async function postStates(cfg, matchIds) {
|
|
186
191
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/states"), {
|
|
187
192
|
method: "POST",
|
|
188
|
-
headers:
|
|
193
|
+
headers: headersFor(cfg, true),
|
|
189
194
|
body: JSON.stringify({ matchIds })
|
|
190
195
|
});
|
|
191
196
|
if (res.status === 404) return null;
|
|
@@ -197,19 +202,19 @@ function q(parts) {
|
|
|
197
202
|
return kept.length ? `?${kept.join("&")}` : "";
|
|
198
203
|
}
|
|
199
204
|
async function getGames(cfg, operatorUserId, gameDay) {
|
|
200
|
-
const res = await cfg.fetch(endpoint(cfg, "games" + q({ operatorUserId, gameDay })), { method: "GET", headers:
|
|
205
|
+
const res = await cfg.fetch(endpoint(cfg, "games" + q({ operatorUserId, gameDay })), { method: "GET", headers: headersFor(cfg, false) });
|
|
201
206
|
if (res.status === 404) return null;
|
|
202
207
|
if (!res.ok) throw new Error(`games ${res.status}`);
|
|
203
208
|
return await res.json();
|
|
204
209
|
}
|
|
205
210
|
async function getGameConfig(cfg, gameId, fixtureId, gameDay, locale) {
|
|
206
|
-
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: "GET", headers:
|
|
211
|
+
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: "GET", headers: headersFor(cfg, false) });
|
|
207
212
|
if (res.status === 404) return null;
|
|
208
213
|
if (!res.ok) throw new Error(`game-config ${res.status}`);
|
|
209
214
|
return await res.json();
|
|
210
215
|
}
|
|
211
216
|
async function getGameResult(cfg, gameId, operatorUserId, fixtureId, gameDay, locale) {
|
|
212
|
-
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: "GET", headers:
|
|
217
|
+
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: "GET", headers: headersFor(cfg, false) });
|
|
213
218
|
if (res.status === 404) return null;
|
|
214
219
|
if (!res.ok) throw new Error(`game-result ${res.status}`);
|
|
215
220
|
return await res.json();
|
|
@@ -217,7 +222,7 @@ async function getGameResult(cfg, gameId, operatorUserId, fixtureId, gameDay, lo
|
|
|
217
222
|
async function postPlay(cfg, gameId, body, locale) {
|
|
218
223
|
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {
|
|
219
224
|
method: "POST",
|
|
220
|
-
headers:
|
|
225
|
+
headers: headersFor(cfg, true),
|
|
221
226
|
body: JSON.stringify(body)
|
|
222
227
|
});
|
|
223
228
|
if (res.status === 404) return null;
|
|
@@ -225,49 +230,49 @@ async function postPlay(cfg, gameId, body, locale) {
|
|
|
225
230
|
return await res.json();
|
|
226
231
|
}
|
|
227
232
|
async function getLeaderboard(cfg, operatorUserId, week) {
|
|
228
|
-
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({ operatorUserId, week })), { method: "GET", headers:
|
|
233
|
+
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({ operatorUserId, week })), { method: "GET", headers: headersFor(cfg, false) });
|
|
229
234
|
if (res.status === 404) return null;
|
|
230
235
|
if (!res.ok) throw new Error(`leaderboard ${res.status}`);
|
|
231
236
|
return await res.json();
|
|
232
237
|
}
|
|
233
238
|
async function getClubFixtures(cfg, competitionId, limit) {
|
|
234
|
-
const res = await cfg.fetch(endpoint(cfg, "club/fixtures" + q({ competitionId, limit })), { method: "GET", headers:
|
|
239
|
+
const res = await cfg.fetch(endpoint(cfg, "club/fixtures" + q({ competitionId, limit })), { method: "GET", headers: headersFor(cfg, false) });
|
|
235
240
|
if (res.status === 404) return null;
|
|
236
241
|
if (!res.ok) throw new Error(`club-fixtures ${res.status}`);
|
|
237
242
|
return await res.json();
|
|
238
243
|
}
|
|
239
244
|
async function getClubStandings(cfg, competitionId) {
|
|
240
|
-
const res = await cfg.fetch(endpoint(cfg, "club/standings" + q({ competitionId })), { method: "GET", headers:
|
|
245
|
+
const res = await cfg.fetch(endpoint(cfg, "club/standings" + q({ competitionId })), { method: "GET", headers: headersFor(cfg, false) });
|
|
241
246
|
if (res.status === 404) return null;
|
|
242
247
|
if (!res.ok) throw new Error(`club-standings ${res.status}`);
|
|
243
248
|
return await res.json();
|
|
244
249
|
}
|
|
245
250
|
async function getClubSquad(cfg) {
|
|
246
|
-
const res = await cfg.fetch(endpoint(cfg, "club/squad"), { method: "GET", headers:
|
|
251
|
+
const res = await cfg.fetch(endpoint(cfg, "club/squad"), { method: "GET", headers: headersFor(cfg, false) });
|
|
247
252
|
if (res.status === 404) return null;
|
|
248
253
|
if (!res.ok) throw new Error(`club-squad ${res.status}`);
|
|
249
254
|
return await res.json();
|
|
250
255
|
}
|
|
251
256
|
async function getClubSquadStats(cfg) {
|
|
252
|
-
const res = await cfg.fetch(endpoint(cfg, "club/squad/stats"), { method: "GET", headers:
|
|
257
|
+
const res = await cfg.fetch(endpoint(cfg, "club/squad/stats"), { method: "GET", headers: headersFor(cfg, false) });
|
|
253
258
|
if (res.status === 404) return null;
|
|
254
259
|
if (!res.ok) throw new Error(`club-squad-stats ${res.status}`);
|
|
255
260
|
return await res.json();
|
|
256
261
|
}
|
|
257
262
|
async function getClubPlayerDetail(cfg, playerId) {
|
|
258
|
-
const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: "GET", headers:
|
|
263
|
+
const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: "GET", headers: headersFor(cfg, false) });
|
|
259
264
|
if (res.status === 404) return null;
|
|
260
265
|
if (!res.ok) throw new Error(`club-player ${res.status}`);
|
|
261
266
|
return await res.json();
|
|
262
267
|
}
|
|
263
268
|
async function getClubRecords(cfg, limit) {
|
|
264
|
-
const res = await cfg.fetch(endpoint(cfg, "club/records" + q({ limit })), { method: "GET", headers:
|
|
269
|
+
const res = await cfg.fetch(endpoint(cfg, "club/records" + q({ limit })), { method: "GET", headers: headersFor(cfg, false) });
|
|
265
270
|
if (res.status === 404) return null;
|
|
266
271
|
if (!res.ok) throw new Error(`club-records ${res.status}`);
|
|
267
272
|
return await res.json();
|
|
268
273
|
}
|
|
269
274
|
async function getPricePresets(cfg, locale, operatorUserId, options) {
|
|
270
|
-
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale, operatorUserId, pool: options?.pool })), { method: "GET", headers:
|
|
275
|
+
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale, operatorUserId, pool: options?.pool })), { method: "GET", headers: headersFor(cfg, false) });
|
|
271
276
|
if (res.status === 404) return null;
|
|
272
277
|
if (!res.ok) throw new Error(`price-presets ${res.status}`);
|
|
273
278
|
return await res.json();
|
|
@@ -677,7 +682,8 @@ var StatsWidgetClient = class {
|
|
|
677
682
|
operatorId: options.operatorId,
|
|
678
683
|
publicKey: options.publicKey,
|
|
679
684
|
baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
|
|
680
|
-
fetch: fetchImpl
|
|
685
|
+
fetch: fetchImpl,
|
|
686
|
+
client: options.client
|
|
681
687
|
};
|
|
682
688
|
}
|
|
683
689
|
chat(input, callbacks) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\n// B4 Q7: the codes a brand's limit refuses with. Any other 429 stays a plain RateLimitError.\nexport const LIMIT_CODES = ['daily_cap', 'quota_exhausted', 'assistant_paused'] as const\nexport type LimitCode = (typeof LIMIT_CODES)[number]\nexport function isLimitCode(code: unknown): code is LimitCode {\n return typeof code === 'string' && (LIMIT_CODES as readonly string[]).includes(code)\n}\nexport interface LimitDetails {\n limitCode: LimitCode\n resetsAt?: string\n /** The brand's or the built-in text, already in the user's language. */\n message?: string\n}\nexport class LimitError extends RateLimitError {\n readonly limitCode: LimitCode\n readonly resetsAt?: string\n readonly limitMessage?: string\n constructor(details: LimitDetails, retryAfter?: number) {\n super(retryAfter, details.message ?? 'Limit reached')\n this.limitCode = details.limitCode\n this.resetsAt = details.resetsAt\n this.limitMessage = details.message\n }\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, isLimitCode, LimitError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayBody, SubmitPlayResult,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n}\n\nfunction endpoint(cfg: ResolvedConfig, path: string): string {\n return `${cfg.baseUrl.replace(/\\/+$/, '')}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`\n}\n\nexport function toWidgetError(status: number, retryAfterHeader: string | null): WidgetSdkError {\n switch (status) {\n case 401: return new AuthError()\n case 403: return new ForbiddenError()\n case 429: {\n const n = retryAfterHeader != null ? Number(retryAfterHeader) : undefined\n return new RateLimitError(Number.isFinite(n) ? (n as number) : undefined)\n }\n default: return new UpstreamError(status)\n }\n}\n\n// B4 Q7: a limit refusal is a 429 whose problem+json body names the limit. The gateway's own per-minute 429 sets\n// Retry-After without exposing it to browsers, so a missing header is normal: the body's retryAfterSeconds covers\n// it, and no countdown is shown when neither is present.\nexport async function chatError(res: Response): Promise<WidgetSdkError> {\n const base = toWidgetError(res.status, res.headers.get('Retry-After'))\n if (!(base instanceof RateLimitError)) return base\n let body: unknown\n try { body = await res.json() } catch { return base }\n if (typeof body !== 'object' || body === null) return base\n const b = body as Record<string, unknown>\n if (!isLimitCode(b.errorCode)) return base\n const text = (v: unknown): string | undefined => (typeof v === 'string' && v.trim() !== '' ? v : undefined)\n const header = res.headers.get('Retry-After')?.trim()\n const headerRetry = header != null && /^\\d+$/.test(header) ? Number(header) : undefined\n const bodyRetry = typeof b.retryAfterSeconds === 'number' && Number.isFinite(b.retryAfterSeconds) && b.retryAfterSeconds >= 0 ? b.retryAfterSeconds : undefined\n return new LimitError(\n { limitCode: b.errorCode, resetsAt: text(b.resetsAt), message: text(b.message) },\n headerRetry ?? bodyRetry,\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 await chatError(res)\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n // 204 is the definitive \"not live / match over\" signal -- the poll loop stops on it.\n // Any other non-ok status (e.g. a transient 502/503/504) must throw rather than return\n // null, so the poll loop's per-tick try/catch retries on the next tick instead of stopping.\n if (res.status === 204) return null\n if (!res.ok) throw new Error(`live-dashboard ${res.status}`)\n return (await res.json()) as ClubFanDashboardPayload\n}\n\n// 404 is the definitive \"live monitor disabled for this operator\" signal -- the poll loop\n// stops and the tabs disable. Any other non-ok status must throw so the per-tick\n// try/catch retries next tick instead of silently disabling the feature.\nexport async function postLiveMonitor(cfg: ResolvedConfig, pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n const body: { pins: PinRef[]; locale?: string } = { pins }\n if (locale) body.locale = locale\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(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postLeagueStar(\n cfg: ResolvedConfig, competitionId: number, starred: boolean,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<LeagueStarResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ starred, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leagues/star ${res.status}`)\n return (await res.json()) as LeagueStarResult\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n\nfunction q(parts: Record<string, string | number | undefined>): string {\n const kept = Object.entries(parts)\n .filter(([, v]) => v !== undefined && v !== '')\n .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)\n return kept.length ? `?${kept.join('&')}` : ''\n}\n\nexport async function getGames(cfg: ResolvedConfig, operatorUserId?: string, gameDay?: string): Promise<GameListPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games' + q({ operatorUserId, gameDay })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`games ${res.status}`)\n return (await res.json()) as GameListPayload\n}\n\nexport async function getGameConfig(cfg: ResolvedConfig, gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-config ${res.status}`)\n return (await res.json()) as GameStatePayload\n}\n\nexport async function getGameResult(cfg: ResolvedConfig, gameId: string, operatorUserId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-result ${res.status}`)\n return (await res.json()) as GameResultPayload\n}\n\nexport async function postPlay(cfg: ResolvedConfig, gameId: string, body: SubmitPlayBody, locale?: string): Promise<SubmitPlayResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey },\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`play ${res.status}`)\n return (await res.json()) as SubmitPlayResult\n}\n\nexport async function getLeaderboard(cfg: ResolvedConfig, operatorUserId?: string, week?: string): Promise<LeaderboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games/leaderboard' + q({ operatorUserId, week })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leaderboard ${res.status}`)\n return (await res.json()) as LeaderboardPayload\n}\n\nexport async function getClubFixtures(cfg: ResolvedConfig, competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/fixtures' + q({ competitionId, limit })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-fixtures ${res.status}`)\n return (await res.json()) as ClubFixturesPayload\n}\n\nexport async function getClubStandings(cfg: ResolvedConfig, competitionId?: number): Promise<ClubStandingsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/standings' + q({ competitionId })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-standings ${res.status}`)\n return (await res.json()) as ClubStandingsPayload\n}\n\nexport async function getClubSquad(cfg: ResolvedConfig): Promise<ClubSquadPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad ${res.status}`)\n return (await res.json()) as ClubSquadPayload\n}\n\nexport async function getClubSquadStats(cfg: ResolvedConfig): Promise<ClubSquadStatsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad/stats'), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad-stats ${res.status}`)\n return (await res.json()) as ClubSquadStatsPayload\n}\n\nexport async function getClubPlayerDetail(cfg: ResolvedConfig, playerId: number): Promise<ClubPlayerDetailPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-player ${res.status}`)\n return (await res.json()) as ClubPlayerDetailPayload\n}\n\nexport async function getClubRecords(cfg: ResolvedConfig, limit?: number): Promise<ClubRecordsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/records' + q({ limit })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-records ${res.status}`)\n return (await res.json()) as ClubRecordsPayload\n}\n\n// Onboarding presets stage 2 (contract §1). 404 is the definitive \"no presets for this visitor\"\n// answer (flag off, not a betting operator, or cool-off). 503 and every other non-ok status throw:\n// the widget keeps any grid it already has and asks again on the next panel open.\n// operatorUserId is optional, passed as the games routes pass it: the cool-off check (D3) needs it,\n// and a request without it is an anonymous visitor.\nexport async function getPricePresets(\n cfg: ResolvedConfig, locale: string, operatorUserId?: string, options?: PresetGridOptions,\n): Promise<PresetGrid | null> {\n const res = await cfg.fetch(endpoint(cfg, 'price-presets' + q({ locale, operatorUserId, pool: options?.pool })), { method: 'GET', headers: { 'X-SS-Public-Key': cfg.publicKey } })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`price-presets ${res.status}`)\n return (await res.json()) as PresetGrid\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayResult,\n} from './events'\nimport {\n getClubFixtures, getClubPlayerDetail, getClubRecords, getClubSquad, getClubSquadStats, getClubStandings, getGameConfig, getGameResult, getGames, getLeaderboard, getLiveDashboard, getPricePresets,\n postLeagueStar, postLiveMonitor, postMarketOdds, postPlay, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins, locale)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getPricePresets(locale: string, options?: PresetGridOptions): Promise<PresetGrid | null> {\n return getPricePresets(this.cfg, locale, this.context?.operatorUserId, options)\n }\n\n getSchedule(\n localDate: string, utcOffsetMinutes: number, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId)\n }\n\n starLeague(\n competitionId: number, starred: boolean, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<LeagueStarResult | null> {\n return postLeagueStar(this.cfg, competitionId, starred, operatorUserId, anonymousUserId)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n\n getGames(gameDay?: string): Promise<GameListPayload | null> {\n return getGames(this.cfg, this.context?.operatorUserId, gameDay)\n }\n\n getGameConfig(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n return getGameConfig(this.cfg, gameId, fixtureId, gameDay, locale)\n }\n\n getGameResult(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return getGameResult(this.cfg, gameId, operatorUserId, fixtureId, gameDay, locale)\n }\n\n postPlay(gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string): Promise<SubmitPlayResult | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return postPlay(this.cfg, gameId, { operatorUserId, gameDay, answerJson, fixtureId }, locale)\n }\n\n getLeaderboard(week?: string): Promise<LeaderboardPayload | null> {\n return getLeaderboard(this.cfg, this.context?.operatorUserId, week)\n }\n\n getClubFixtures(competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n return getClubFixtures(this.cfg, competitionId, limit)\n }\n getClubStandings(competitionId?: number): Promise<ClubStandingsPayload | null> {\n return getClubStandings(this.cfg, competitionId)\n }\n getClubSquad(): Promise<ClubSquadPayload | null> {\n return getClubSquad(this.cfg)\n }\n getClubSquadStats(): Promise<ClubSquadStatsPayload | null> {\n return getClubSquadStats(this.cfg)\n }\n getClubPlayerDetail(playerId: number): Promise<ClubPlayerDetailPayload | null> {\n return getClubPlayerDetail(this.cfg, playerId)\n }\n getClubRecords(limit?: number): Promise<ClubRecordsPayload | null> {\n return getClubRecords(this.cfg, limit)\n }\n}\n","export type WidgetEntityEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n | 'slip_remove' | 'bet_placed' | 'match_view' | 'match_open'\n\nexport type WidgetPopupEventName = 'popup_shown' | 'popup_opened' | 'popup_dismissed'\n\nexport type WidgetPopupAskEventName = 'popup_ask_tap'\n\nexport type WidgetOpenEventName = 'widget_open'\n\nexport type WidgetEventName = WidgetEntityEventName | WidgetPopupEventName | WidgetPopupAskEventName | WidgetOpenEventName\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEntityEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n /** Football match id of the slip selection (slip_click / slip_result). */\n matchId?: number\n /** The raw odds label as stored (\"Home\", \"Over\", \"Home/Draw\"), never a joined display string. Max 64. */\n selection?: string\n /** The raw line (\"2.5\"). Max 32; omit when empty. */\n line?: string\n /** Decimal price shown when the selection was added. */\n odds?: number\n}\n\n/** Launcher popup telemetry: counted server-side, never tied to an entity. */\nexport type WidgetPopupEventInput =\n { name: WidgetPopupEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\n/** A tap on one of the launcher bubble's asks. `outcome` carries the ask's position, \"0\" or \"1\"\n * (contract §5): the gateway forwards only the fields of its own event model, and outcome is its\n * one free-text field. */\nexport type WidgetPopupAskEventInput =\n { name: WidgetPopupAskEventName; outcome: string } & { [K in Exclude<keyof WidgetEventInput, 'name' | 'outcome'>]?: never }\n\n/** The panel opening: entity-free, each open is added to the user's count for the day. */\nexport type WidgetOpenEventInput =\n { name: WidgetOpenEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\nexport type WidgetLogInput = WidgetEventInput | WidgetPopupEventInput | WidgetPopupAskEventInput | WidgetOpenEventInput\n\nexport type WireEvent = WidgetLogInput & {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetLogInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n /** Undoes dispose(). React StrictMode runs an effect's cleanup and then its setup again on the\n * same logger, so the widget's setup has to be able to bring a disposed logger back. */\n resume(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set([\n 'pin_add', 'pin_remove', 'slip_click', 'slip_result', 'slip_remove', 'bet_placed',\n])\n\n// Queued without arming the batch timer: the event leaves with the next flush of any cause. A match\n// page view fires for every visitor, so it must never start a request of its own.\nconst DEFERRED: ReadonlySet<WidgetEventName> = new Set(['match_view'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetLogInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else if (!DEFERRED.has(input.name)) {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n resume(): void {\n this.disposed = false\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n}\n\nexport interface UserContext {\n operatorUserId?: string\n defaultLanguage?: string\n anonymousUserId?: string\n}\n\nexport interface ChatGrounding {\n kind?: string\n matchId?: number\n opponentTeamId?: number\n teamId?: number\n competitionId?: number\n season?: string\n subject?: string\n personaHint?: string\n}\n\n/** Onboarding presets stage 2 (contract §3): what a tool's Send asked for. Sent only from a tool's\n * Send, beside the full sentence in `message`. The server ignores it unless every value is valid. */\nexport interface ChatPreset {\n kind: 'max_price' | 'min_price' | 'combo' | 'market'\n /** max_price, min_price */\n price?: number\n /** max_price, min_price */\n count?: number\n /** combo */\n total?: number\n /** combo */\n legs?: number\n /** market */\n marketDeveloperName?: string\n /** The picks or legs the tool showed, in the order shown (R12: the answer reprices exactly these). */\n matchOddsIds: number[]\n /** The same picks' matchId, index for index with matchOddsIds (from the grid). */\n matchIds: number[]\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 /** Features this client can draw (e.g. \"price_presets\"). The server sends nothing that needs a\n * feature the list does not name; an absent list means today's responses. */\n clientCapabilities?: string[]\n /** Onboarding presets stage 2: set only by a preset tool's Send (contract §3). */\n preset?: ChatPreset\n}\n\nexport type SignalType =\n | 'MatchPageView' | 'PlayerPageView' | 'TeamPageView' | 'MarketView'\n | 'SearchQuery' | 'SessionDepth' | 'TimeOnPage' | 'InsightViewed'\n | 'InsightMarketClicked' | 'BetPlacedFromInsight' | 'InsightScrollDepth'\n | 'ToolCall' | 'EntityMention' | 'Handoff' | 'FollowUpQuery' | 'RecommendationDismissed'\n\nexport type SignalEntityType =\n | 'Match' | 'Team' | 'Player' | 'Competition' | 'Market'\n | 'Article' | 'Session' | 'Query' | 'Conversation'\n\nexport interface SignalInput {\n signalType: SignalType\n entityType: SignalEntityType\n /** Either this or entityId is required -- an operator's UI mostly knows a display name. */\n entityName?: string\n /** Either this or entityName is required -- a dashboard tile knows its entity by id. */\n entityId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /** Greeting dashboard layout this signal came from, when it is a dashboard tap. */\n dashboardLayout?: string\n /** Zero-based tile position within the dashboard, when it is a dashboard tap. */\n tileIndex?: number\n}\n\nexport interface SlipSelection {\n matchOddsId: number\n matchId: number\n oddsDecimal: number\n quotedAtUtc?: string\n insightId?: string\n conversationId?: string\n}\n\nexport type AddToSlipRejectReason =\n | 'suspended' | 'closed' | 'login_required'\n | 'not_found' | 'limit' | 'unsupported'\n\nexport type AddToSlipResult =\n | { status: 'added'; slip?: { selectionCount: number; totalOddsDecimal?: number } }\n | { status: 'duplicate' }\n | { status: 'price_changed'; newOddsDecimal: number; accepted: boolean }\n | { status: 'rejected'; reason: AddToSlipRejectReason; message?: string }\n\nexport type AddToSlipHandler = (\n selection: SlipSelection,\n) => Promise<AddToSlipResult | void> | AddToSlipResult | void\n\nconst REJECT_REASONS = ['suspended', 'closed', 'login_required', 'not_found', 'limit', 'unsupported']\n\nexport function isAddToSlipResult(v: unknown): v is AddToSlipResult {\n if (typeof v !== 'object' || v === null) return false\n const o = v as Record<string, unknown>\n switch (o.status) {\n case 'added':\n case 'duplicate':\n return true\n case 'price_changed':\n return typeof o.newOddsDecimal === 'number'\n && Number.isFinite(o.newOddsDecimal)\n && typeof o.accepted === 'boolean'\n case 'rejected':\n return typeof o.reason === 'string'\n && REJECT_REASONS.includes(o.reason)\n default:\n return false\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/ndjson.ts","../src/chat.ts","../src/signals.ts","../src/conversation.ts","../src/eventLog.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["export class WidgetSdkError extends Error {\n readonly code: string\n readonly status?: number\n constructor(message: string, code: string, status?: number) {\n super(message)\n this.name = new.target.name\n this.code = code\n this.status = status\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\nexport class AuthError extends WidgetSdkError {\n constructor(message = 'Invalid or missing public key') { super(message, 'unauthorized', 401) }\n}\nexport class ForbiddenError extends WidgetSdkError {\n constructor(message = 'Origin not allowed or widget disabled') { super(message, 'forbidden', 403) }\n}\nexport class RateLimitError extends WidgetSdkError {\n readonly retryAfter?: number\n constructor(retryAfter?: number, message = 'Rate limited') { super(message, 'rate_limited', 429); this.retryAfter = retryAfter }\n}\n// B4 Q7: the codes a brand's limit refuses with. Any other 429 stays a plain RateLimitError.\nexport const LIMIT_CODES = ['daily_cap', 'quota_exhausted', 'assistant_paused'] as const\nexport type LimitCode = (typeof LIMIT_CODES)[number]\nexport function isLimitCode(code: unknown): code is LimitCode {\n return typeof code === 'string' && (LIMIT_CODES as readonly string[]).includes(code)\n}\nexport interface LimitDetails {\n limitCode: LimitCode\n resetsAt?: string\n /** The brand's or the built-in text, already in the user's language. */\n message?: string\n}\nexport class LimitError extends RateLimitError {\n readonly limitCode: LimitCode\n readonly resetsAt?: string\n readonly limitMessage?: string\n constructor(details: LimitDetails, retryAfter?: number) {\n super(retryAfter, details.message ?? 'Limit reached')\n this.limitCode = details.limitCode\n this.resetsAt = details.resetsAt\n this.limitMessage = details.message\n }\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, isLimitCode, LimitError, NetworkError, RateLimitError, UpstreamError, WidgetSdkError } from './errors'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayBody, SubmitPlayResult,\n} from './events'\nimport type { ChatInput, FetchLike } from './types'\n\nexport interface ResolvedConfig {\n operatorId: string\n publicKey: string\n baseUrl: string\n fetch: FetchLike\n client?: string\n}\n\nexport function headersFor(cfg: ResolvedConfig, json: boolean): Record<string, string> {\n const h: Record<string, string> = json ? { 'Content-Type': 'application/json', 'X-SS-Public-Key': cfg.publicKey } : { 'X-SS-Public-Key': cfg.publicKey }\n if (cfg.client) h['X-SS-Client'] = cfg.client\n return h\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\n// B4 Q7: a limit refusal is a 429 whose problem+json body names the limit. The gateway's own per-minute 429 sets\n// Retry-After without exposing it to browsers, so a missing header is normal: the body's retryAfterSeconds covers\n// it, and no countdown is shown when neither is present.\nexport async function chatError(res: Response): Promise<WidgetSdkError> {\n const base = toWidgetError(res.status, res.headers.get('Retry-After'))\n if (!(base instanceof RateLimitError)) return base\n let body: unknown\n try { body = await res.json() } catch { return base }\n if (typeof body !== 'object' || body === null) return base\n const b = body as Record<string, unknown>\n if (!isLimitCode(b.errorCode)) return base\n const text = (v: unknown): string | undefined => (typeof v === 'string' && v.trim() !== '' ? v : undefined)\n const header = res.headers.get('Retry-After')?.trim()\n const headerRetry = header != null && /^\\d+$/.test(header) ? Number(header) : undefined\n const bodyRetry = typeof b.retryAfterSeconds === 'number' && Number.isFinite(b.retryAfterSeconds) && b.retryAfterSeconds >= 0 ? b.retryAfterSeconds : undefined\n return new LimitError(\n { limitCode: b.errorCode, resetsAt: text(b.resetsAt), message: text(b.message) },\n headerRetry ?? bodyRetry,\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: headersFor(cfg, true),\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 await chatError(res)\n return res\n}\n\nexport async function postSignal(cfg: ResolvedConfig, wireBody: object, signal?: AbortSignal): Promise<void> {\n const res = await send(cfg, 'signals', wireBody, signal)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\nexport async function postEvents(cfg: ResolvedConfig, batch: object): Promise<void> {\n const res = await send(cfg, 'events', batch)\n if (!res.ok) throw toWidgetError(res.status, res.headers.get('Retry-After'))\n}\n\n// Best-effort tail flush on page hide/unload. Uses fetch keepalive (not sendBeacon) because the\n// gateway requires the X-SS-Public-Key header, which sendBeacon cannot set. Both the synchronous\n// call and the returned promise are guarded -- an async rejection (real network failure, or\n// Chrome's ~64KB keepalive body cap) must never surface as an unhandled rejection, since this\n// runs inside an operator-embedded widget during page-hide and would show up as noise in the\n// OPERATOR's own error monitoring.\nexport function postEventsKeepalive(cfg: ResolvedConfig, batch: object): void {\n try {\n void cfg.fetch(endpoint(cfg, 'events'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(batch),\n keepalive: true,\n }).catch(() => { /* best-effort tail flush -- swallow async rejection too */ })\n } catch {\n /* best-effort tail flush -- never throw on unload */\n }\n}\n\nexport async function getLiveDashboard(cfg: ResolvedConfig): Promise<ClubFanDashboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-dashboard'), { method: 'GET', headers: headersFor(cfg, false) })\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[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n const body: { pins: PinRef[]; locale?: string } = { pins }\n if (locale) body.locale = locale\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor ${res.status}`)\n return (await res.json()) as LiveMonitorSnapshot\n}\n\nexport async function postMarketOdds(\n cfg: ResolvedConfig, matchId: number, marketDeveloperName: string,\n): Promise<MarketOddsBlock | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/market'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ matchId, marketDeveloperName }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/market ${res.status}`)\n return (await res.json()) as MarketOddsBlock\n}\n\n// 404 mirrors postLiveMonitor: the definitive \"live monitor disabled for this operator\" signal.\n// Every other non-ok status throws so the caller's per-tick catch retries next tick.\nexport async function postSchedule(\n cfg: ResolvedConfig, localDate: string, utcOffsetMinutes: number,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<SchedulePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/schedule'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ localDate, utcOffsetMinutes, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`)\n return (await res.json()) as SchedulePayload\n}\n\nexport async function postLeagueStar(\n cfg: ResolvedConfig, competitionId: number, starred: boolean,\n operatorUserId?: string, anonymousUserId?: string,\n): Promise<LeagueStarResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ starred, operatorUserId, anonymousUserId }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leagues/star ${res.status}`)\n return (await res.json()) as LeagueStarResult\n}\n\nexport async function postStates(cfg: ResolvedConfig, matchIds: number[]): Promise<StatesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'live-monitor/states'), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify({ matchIds }),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`live-monitor/states ${res.status}`)\n return (await res.json()) as StatesPayload\n}\n\nfunction q(parts: Record<string, string | number | undefined>): string {\n const kept = Object.entries(parts)\n .filter(([, v]) => v !== undefined && v !== '')\n .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)\n return kept.length ? `?${kept.join('&')}` : ''\n}\n\nexport async function getGames(cfg: ResolvedConfig, operatorUserId?: string, gameDay?: string): Promise<GameListPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games' + q({ operatorUserId, gameDay })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`games ${res.status}`)\n return (await res.json()) as GameListPayload\n}\n\nexport async function getGameConfig(cfg: ResolvedConfig, gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}` + q({ fixtureId, gameDay, locale })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-config ${res.status}`)\n return (await res.json()) as GameStatePayload\n}\n\nexport async function getGameResult(cfg: ResolvedConfig, gameId: string, operatorUserId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ operatorUserId, fixtureId, gameDay, locale })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`game-result ${res.status}`)\n return (await res.json()) as GameResultPayload\n}\n\nexport async function postPlay(cfg: ResolvedConfig, gameId: string, body: SubmitPlayBody, locale?: string): Promise<SubmitPlayResult | null> {\n const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {\n method: 'POST',\n headers: headersFor(cfg, true),\n body: JSON.stringify(body),\n })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`play ${res.status}`)\n return (await res.json()) as SubmitPlayResult\n}\n\nexport async function getLeaderboard(cfg: ResolvedConfig, operatorUserId?: string, week?: string): Promise<LeaderboardPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'games/leaderboard' + q({ operatorUserId, week })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`leaderboard ${res.status}`)\n return (await res.json()) as LeaderboardPayload\n}\n\nexport async function getClubFixtures(cfg: ResolvedConfig, competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/fixtures' + q({ competitionId, limit })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-fixtures ${res.status}`)\n return (await res.json()) as ClubFixturesPayload\n}\n\nexport async function getClubStandings(cfg: ResolvedConfig, competitionId?: number): Promise<ClubStandingsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/standings' + q({ competitionId })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-standings ${res.status}`)\n return (await res.json()) as ClubStandingsPayload\n}\n\nexport async function getClubSquad(cfg: ResolvedConfig): Promise<ClubSquadPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad'), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad ${res.status}`)\n return (await res.json()) as ClubSquadPayload\n}\n\nexport async function getClubSquadStats(cfg: ResolvedConfig): Promise<ClubSquadStatsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/squad/stats'), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-squad-stats ${res.status}`)\n return (await res.json()) as ClubSquadStatsPayload\n}\n\nexport async function getClubPlayerDetail(cfg: ResolvedConfig, playerId: number): Promise<ClubPlayerDetailPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, `club/player/${encodeURIComponent(String(playerId))}`), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-player ${res.status}`)\n return (await res.json()) as ClubPlayerDetailPayload\n}\n\nexport async function getClubRecords(cfg: ResolvedConfig, limit?: number): Promise<ClubRecordsPayload | null> {\n const res = await cfg.fetch(endpoint(cfg, 'club/records' + q({ limit })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`club-records ${res.status}`)\n return (await res.json()) as ClubRecordsPayload\n}\n\n// Onboarding presets stage 2 (contract §1). 404 is the definitive \"no presets for this visitor\"\n// answer (flag off, not a betting operator, or cool-off). 503 and every other non-ok status throw:\n// the widget keeps any grid it already has and asks again on the next panel open.\n// operatorUserId is optional, passed as the games routes pass it: the cool-off check (D3) needs it,\n// and a request without it is an anonymous visitor.\nexport async function getPricePresets(\n cfg: ResolvedConfig, locale: string, operatorUserId?: string, options?: PresetGridOptions,\n): Promise<PresetGrid | null> {\n const res = await cfg.fetch(endpoint(cfg, 'price-presets' + q({ locale, operatorUserId, pool: options?.pool })), { method: 'GET', headers: headersFor(cfg, false) })\n if (res.status === 404) return null\n if (!res.ok) throw new Error(`price-presets ${res.status}`)\n return (await res.json()) as PresetGrid\n}\n","import { ParseError } from './errors'\n\nexport interface NdjsonParser {\n push(text: string): unknown[]\n flush(): unknown[]\n}\n\nfunction parseLine(line: string): unknown | undefined {\n const trimmed = line.trim()\n if (trimmed === '') return undefined\n try {\n return JSON.parse(trimmed)\n } catch {\n throw new ParseError('Malformed NDJSON line', line)\n }\n}\n\nexport function createNdjsonParser(): NdjsonParser {\n let buffer = ''\n return {\n push(text: string): unknown[] {\n buffer += text\n const out: unknown[] = []\n let idx: number\n while ((idx = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, idx)\n buffer = buffer.slice(idx + 1)\n const parsed = parseLine(line)\n if (parsed !== undefined) out.push(parsed)\n }\n return out\n },\n flush(): unknown[] {\n const rest = buffer\n buffer = ''\n const parsed = parseLine(rest)\n return parsed === undefined ? [] : [parsed]\n },\n }\n}\n","import { WidgetSdkError } from './errors'\nimport type {\n ActionButtonEventData, ActionsLoadingEventData, AnswerEventData, ChatEvent,\n EntityCardEventData, IntentChipEventData, ProgressEventData, StreamErrorEventData, TurnCompleteEventData,\n} from './events'\nimport { postChat, type ResolvedConfig } from './http'\nimport { createNdjsonParser } from './ndjson'\nimport type { ChatInput } from './types'\n\nexport interface ChatCallbacks {\n onProgress?(data: ProgressEventData): void\n onAnswer?(data: AnswerEventData): void\n onEntityCard?(data: EntityCardEventData): void\n onActionButton?(data: ActionButtonEventData): void\n onIntentChip?(data: IntentChipEventData): void\n onActionsLoading?(data: ActionsLoadingEventData): void\n onError?(error: StreamErrorEventData | WidgetSdkError): void\n onComplete?(data: TurnCompleteEventData): void\n}\n\nexport interface ChatHandle extends AsyncIterable<ChatEvent>, PromiseLike<void> {\n cancel(): void\n}\n\nfunction dispatch(ev: ChatEvent, cb: ChatCallbacks): void {\n switch (ev.type) {\n case 'progress': cb.onProgress?.(ev.data); break\n case 'answer': cb.onAnswer?.(ev.data); break\n case 'entity_card': cb.onEntityCard?.(ev.data); break\n case 'action_button': cb.onActionButton?.(ev.data); break\n case 'intent_chip': cb.onIntentChip?.(ev.data); break\n case 'actions_loading': cb.onActionsLoading?.(ev.data); break\n case 'turn_complete': cb.onComplete?.(ev.data); break\n case 'error': cb.onError?.(ev.data); break\n }\n}\n\nasync function* streamEvents(cfg: ResolvedConfig, input: ChatInput, signal: AbortSignal): AsyncGenerator<ChatEvent> {\n const res = await postChat(cfg, input, signal)\n const reader = res.body!.getReader()\n const decoder = new TextDecoder()\n const parser = createNdjsonParser()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n for (const obj of parser.push(decoder.decode(value, { stream: true }))) yield obj as ChatEvent\n }\n for (const obj of parser.flush()) yield obj as ChatEvent\n } finally {\n await reader.cancel().catch(() => {})\n }\n}\n\nexport function runChat(\n cfg: ResolvedConfig,\n input: ChatInput,\n callbacks?: ChatCallbacks,\n opts?: { signal?: AbortSignal; tap?: (ev: ChatEvent) => void },\n): ChatHandle {\n const controller = new AbortController()\n const external = opts?.signal\n if (external) {\n if (external.aborted) controller.abort()\n else external.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n async function* source(): AsyncGenerator<ChatEvent> {\n for await (const ev of streamEvents(cfg, input, controller.signal)) {\n opts?.tap?.(ev)\n yield ev\n }\n }\n\n const iterator = source()\n let consumed = false\n\n async function drive(): Promise<void> {\n try {\n for await (const ev of iterator) { if (callbacks) dispatch(ev, callbacks) }\n } catch (error) {\n if (callbacks?.onError && error instanceof WidgetSdkError) { callbacks.onError(error); return }\n throw error\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ChatEvent> {\n if (consumed) throw new Error('chat stream already consumed')\n consumed = true\n return iterator\n },\n then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n if (consumed) return Promise.resolve().then(onfulfilled, onrejected)\n consumed = true\n return drive().then(onfulfilled, onrejected)\n },\n cancel(): void { controller.abort() },\n }\n}\n","import type { SignalEntityType, SignalInput, SignalType } from './types'\n\nexport const SIGNAL_TYPE_CODES: Record<SignalType, number> = {\n MatchPageView: 1, PlayerPageView: 2, TeamPageView: 3, MarketView: 4,\n SearchQuery: 5, SessionDepth: 6, TimeOnPage: 7, InsightViewed: 8,\n InsightMarketClicked: 9, BetPlacedFromInsight: 10, InsightScrollDepth: 11,\n ToolCall: 12, EntityMention: 13, Handoff: 14, FollowUpQuery: 15, RecommendationDismissed: 16,\n}\n\nexport const ENTITY_TYPE_CODES: Record<SignalEntityType, number> = {\n Match: 1, Team: 2, Player: 3, Competition: 4, Market: 5,\n Article: 6, Session: 7, Query: 8, Conversation: 9,\n}\n\nexport function toSignalWireBody(input: SignalInput): {\n signalType: number; entityType: number; entityName?: string; entityId?: string\n operatorUserId?: string; anonymousUserId?: string; dashboardLayout?: string; tileIndex?: number\n} {\n const signalType = SIGNAL_TYPE_CODES[input.signalType]\n const entityType = ENTITY_TYPE_CODES[input.entityType]\n if (signalType === undefined) throw new Error(`Unknown signalType: ${String(input.signalType)}`)\n if (entityType === undefined) throw new Error(`Unknown entityType: ${String(input.entityType)}`)\n return {\n signalType, entityType, entityName: input.entityName, entityId: input.entityId,\n operatorUserId: input.operatorUserId, anonymousUserId: input.anonymousUserId,\n dashboardLayout: input.dashboardLayout, tileIndex: input.tileIndex,\n }\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport type {\n ClubFanDashboardPayload, ClubFixturesPayload, ClubSquadPayload, ClubSquadStatsPayload, ClubPlayerDetailPayload, ClubRecordsPayload, ClubStandingsPayload, GameListPayload, GameResultPayload, GameStatePayload, LeaderboardPayload,\n LeagueStarResult, LiveMonitorSnapshot, MarketOddsBlock, PinRef, PresetGrid, PresetGridOptions, SchedulePayload, StatesPayload, SubmitPlayResult,\n} from './events'\nimport {\n getClubFixtures, getClubPlayerDetail, getClubRecords, getClubSquad, getClubSquadStats, getClubStandings, getGameConfig, getGameResult, getGames, getLeaderboard, getLiveDashboard, getPricePresets,\n postLeagueStar, postLiveMonitor, postMarketOdds, postPlay, postSchedule, postSignal, postStates, type ResolvedConfig,\n} from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, UserContext } from './types'\n\nexport class Conversation {\n conversationId?: string\n\n constructor(private readonly cfg: ResolvedConfig, private readonly context?: UserContext) {}\n\n send(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n const mergedContext: UserContext = { ...this.context, ...input.userContext }\n const full: ChatInput = {\n ...input,\n conversationId: input.conversationId ?? this.conversationId,\n userContext: Object.keys(mergedContext).length > 0 ? mergedContext : undefined,\n }\n return runChat(this.cfg, full, callbacks, {\n tap: (ev) => { if (ev.type === 'turn_complete') this.conversationId = ev.data.conversationId },\n })\n }\n\n sendSignal(input: SignalInput): Promise<void> {\n const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId\n const anonymousUserId = operatorUserId ? undefined : (input.anonymousUserId ?? this.context?.anonymousUserId)\n if (!operatorUserId && !anonymousUserId) {\n throw new Error('operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)')\n }\n if (!input.entityId && !input.entityName) {\n throw new Error('entityId or entityName is required')\n }\n return postSignal(this.cfg, toSignalWireBody({ ...input, operatorUserId, anonymousUserId }))\n }\n\n getLiveDashboard(): Promise<ClubFanDashboardPayload | null> {\n return getLiveDashboard(this.cfg)\n }\n\n getLiveMonitor(pins: PinRef[], locale?: string): Promise<LiveMonitorSnapshot | null> {\n return postLiveMonitor(this.cfg, pins, locale)\n }\n\n getMarketOdds(matchId: number, marketDeveloperName: string): Promise<MarketOddsBlock | null> {\n return postMarketOdds(this.cfg, matchId, marketDeveloperName)\n }\n\n getPricePresets(locale: string, options?: PresetGridOptions): Promise<PresetGrid | null> {\n return getPricePresets(this.cfg, locale, this.context?.operatorUserId, options)\n }\n\n getSchedule(\n localDate: string, utcOffsetMinutes: number, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<SchedulePayload | null> {\n return postSchedule(this.cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId)\n }\n\n starLeague(\n competitionId: number, starred: boolean, operatorUserId?: string, anonymousUserId?: string,\n ): Promise<LeagueStarResult | null> {\n return postLeagueStar(this.cfg, competitionId, starred, operatorUserId, anonymousUserId)\n }\n\n getStates(matchIds: number[]): Promise<StatesPayload | null> {\n return postStates(this.cfg, matchIds)\n }\n\n getGames(gameDay?: string): Promise<GameListPayload | null> {\n return getGames(this.cfg, this.context?.operatorUserId, gameDay)\n }\n\n getGameConfig(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameStatePayload | null> {\n return getGameConfig(this.cfg, gameId, fixtureId, gameDay, locale)\n }\n\n getGameResult(gameId: string, fixtureId?: number, gameDay?: string, locale?: string): Promise<GameResultPayload | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return getGameResult(this.cfg, gameId, operatorUserId, fixtureId, gameDay, locale)\n }\n\n postPlay(gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string): Promise<SubmitPlayResult | null> {\n const operatorUserId = this.context?.operatorUserId\n if (!operatorUserId) return Promise.resolve(null)\n return postPlay(this.cfg, gameId, { operatorUserId, gameDay, answerJson, fixtureId }, locale)\n }\n\n getLeaderboard(week?: string): Promise<LeaderboardPayload | null> {\n return getLeaderboard(this.cfg, this.context?.operatorUserId, week)\n }\n\n getClubFixtures(competitionId?: number, limit?: number): Promise<ClubFixturesPayload | null> {\n return getClubFixtures(this.cfg, competitionId, limit)\n }\n getClubStandings(competitionId?: number): Promise<ClubStandingsPayload | null> {\n return getClubStandings(this.cfg, competitionId)\n }\n getClubSquad(): Promise<ClubSquadPayload | null> {\n return getClubSquad(this.cfg)\n }\n getClubSquadStats(): Promise<ClubSquadStatsPayload | null> {\n return getClubSquadStats(this.cfg)\n }\n getClubPlayerDetail(playerId: number): Promise<ClubPlayerDetailPayload | null> {\n return getClubPlayerDetail(this.cfg, playerId)\n }\n getClubRecords(limit?: number): Promise<ClubRecordsPayload | null> {\n return getClubRecords(this.cfg, limit)\n }\n}\n","export type WidgetEntityEventName =\n | 'pin_add' | 'pin_remove' | 'slip_click' | 'slip_result'\n | 'insight_expand' | 'tile_tap' | 'chip_tap'\n | 'slip_remove' | 'bet_placed' | 'match_view' | 'match_open'\n\nexport type WidgetPopupEventName = 'popup_shown' | 'popup_opened' | 'popup_dismissed'\n\nexport type WidgetPopupAskEventName = 'popup_ask_tap'\n\nexport type WidgetOpenEventName = 'widget_open'\n\nexport type WidgetEventName = WidgetEntityEventName | WidgetPopupEventName | WidgetPopupAskEventName | WidgetOpenEventName\n\nexport type WidgetEntityType = 'match' | 'team' | 'player' | 'competition' | 'market'\n\nexport interface WidgetEventInput {\n name: WidgetEntityEventName\n entityType: WidgetEntityType\n entityId?: string\n entityName?: string\n marketDeveloperName?: string\n outcome?: string\n /** Football match id of the slip selection (slip_click / slip_result). */\n matchId?: number\n /** The raw odds label as stored (\"Home\", \"Over\", \"Home/Draw\"), never a joined display string. Max 64. */\n selection?: string\n /** The raw line (\"2.5\"). Max 32; omit when empty. */\n line?: string\n /** Decimal price shown when the selection was added. */\n odds?: number\n}\n\n/** Launcher popup telemetry: counted server-side, never tied to an entity. */\nexport type WidgetPopupEventInput =\n { name: WidgetPopupEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\n/** A tap on one of the launcher bubble's asks. `outcome` carries the ask's position, \"0\" or \"1\"\n * (contract §5): the gateway forwards only the fields of its own event model, and outcome is its\n * one free-text field. */\nexport type WidgetPopupAskEventInput =\n { name: WidgetPopupAskEventName; outcome: string } & { [K in Exclude<keyof WidgetEventInput, 'name' | 'outcome'>]?: never }\n\n/** The panel opening: entity-free, each open is added to the user's count for the day. */\nexport type WidgetOpenEventInput =\n { name: WidgetOpenEventName } & { [K in Exclude<keyof WidgetEventInput, 'name'>]?: never }\n\nexport type WidgetLogInput = WidgetEventInput | WidgetPopupEventInput | WidgetPopupAskEventInput | WidgetOpenEventInput\n\nexport type WireEvent = WidgetLogInput & {\n seq: number\n at: number\n}\n\nexport interface EventBatch {\n v: 1\n sessionId: string\n conversationId?: string\n operatorUserId?: string\n anonymousUserId?: string\n /**\n * Events dropped after exhausting delivery attempts during a PRIOR flush cycle — not a count of\n * this batch's own events. Rides whichever batch is built next after the drop, then is omitted\n * (0/undefined) once a clean cycle passes without a new failure.\n */\n dropped?: number\n /**\n * Failed delivery attempts from a PRIOR flush cycle — not retries of this batch's own events.\n * Rides whichever batch is built next after the failure, then is omitted (0/undefined) once a\n * clean cycle passes without a new failure.\n */\n retries?: number\n events: WireEvent[]\n}\n\nexport interface EventLoggerOptions {\n /** Normal delivery (fetch). Rejecting triggers the retry/backoff loop. */\n flush: (batch: EventBatch) => Promise<void>\n /** Best-effort tail flush on page hide/unload (fetch keepalive). Never awaited. */\n flushKeepalive: (batch: EventBatch) => void\n /** Injectable clock (tests). Defaults to Date.now. */\n now?: () => number\n batchIntervalMs?: number\n maxBatch?: number\n maxAttempts?: number\n}\n\nexport interface EventLogger {\n log(input: WidgetLogInput): void\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void\n flushNow(): Promise<void>\n flushOnHide(): void\n dispose(): void\n /** Undoes dispose(). React StrictMode runs an effect's cleanup and then its setup again on the\n * same logger, so the widget's setup has to be able to bring a disposed logger back. */\n resume(): void\n}\n\nconst IMMEDIATE: ReadonlySet<WidgetEventName> = new Set([\n 'pin_add', 'pin_remove', 'slip_click', 'slip_result', 'slip_remove', 'bet_placed',\n])\n\n// Queued without arming the batch timer: the event leaves with the next flush of any cause. A match\n// page view fires for every visitor, so it must never start a request of its own.\nconst DEFERRED: ReadonlySet<WidgetEventName> = new Set(['match_view'])\n\nconst DEFAULT_BATCH_INTERVAL_MS = 10_000\nconst DEFAULT_MAX_BATCH = 50\nconst DEFAULT_MAX_ATTEMPTS = 3\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction makeSessionId(): string {\n const c: Crypto | undefined = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `s_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n}\n\nclass EventLoggerImpl implements EventLogger {\n private readonly sessionId = makeSessionId()\n private readonly now: () => number\n private readonly batchIntervalMs: number\n private readonly maxBatch: number\n private readonly maxAttempts: number\n\n private queue: WireEvent[] = []\n private seq = 0\n private retries = 0\n private dropped = 0\n private identity: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string } = {}\n private timer: ReturnType<typeof setTimeout> | null = null\n private inFlight: Promise<void> | null = null\n private disposed = false\n\n constructor(private readonly opts: EventLoggerOptions) {\n this.now = opts.now ?? (() => Date.now())\n this.batchIntervalMs = opts.batchIntervalMs ?? DEFAULT_BATCH_INTERVAL_MS\n this.maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH\n this.maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n }\n\n log(input: WidgetLogInput): void {\n if (this.disposed) return\n const event: WireEvent = { ...input, seq: ++this.seq, at: this.now() }\n this.queue.push(event)\n if (IMMEDIATE.has(input.name)) {\n this.trigger()\n } else if (this.queue.length >= this.maxBatch) {\n this.trigger()\n } else if (!DEFERRED.has(input.name)) {\n this.armTimer()\n }\n }\n\n setIdentity(id: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): void {\n this.identity = { ...this.identity, ...id }\n }\n\n async flushNow(): Promise<void> {\n if (this.inFlight) await this.inFlight\n if (this.queue.length > 0) await this.doFlush()\n }\n\n flushOnHide(): void {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n this.opts.flushKeepalive(batch)\n }\n\n dispose(): void {\n this.disposed = true\n this.clearTimer()\n }\n\n resume(): void {\n this.disposed = false\n }\n\n private armTimer(): void {\n if (this.timer !== null) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.trigger()\n }, this.batchIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer === null) return\n clearTimeout(this.timer)\n this.timer = null\n }\n\n private trigger(): void {\n if (this.disposed) return\n if (this.inFlight) return\n this.inFlight = this.doFlush().finally(() => {\n this.inFlight = null\n // An immediate (or maxBatch-triggered) log() call that arrived while this flush was\n // in-flight was a no-op above -- drain it now instead of stranding it until some later\n // log()/flushNow()/dispose() call. Guarded by the disposed check at the top of trigger()\n // itself, so a straggler queued just before dispose() does not fire a flush after it.\n if (this.queue.length > 0) this.trigger()\n })\n }\n\n /**\n * Snapshots the queue + carry-over counters (see EventBatch.dropped/retries) into a batch and\n * resets both for the next cycle. Returns null only when there is truly nothing to report --\n * an empty queue AND no pending dropped/retries -- so a pending counter-only report (queue\n * drained by an exhausted flush, nothing logged since) still gets built and delivered.\n */\n private buildBatch(): EventBatch | null {\n if (this.queue.length === 0 && this.retries === 0 && this.dropped === 0) return null\n const events = this.queue\n this.queue = []\n const batch: EventBatch = { v: 1, sessionId: this.sessionId, ...this.identity, events }\n if (this.retries > 0) batch.retries = this.retries\n if (this.dropped > 0) batch.dropped = this.dropped\n this.retries = 0\n this.dropped = 0\n return batch\n }\n\n private async doFlush(): Promise<void> {\n this.clearTimer()\n const batch = this.buildBatch()\n if (batch === null) return\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n await this.opts.flush(batch)\n return\n } catch {\n this.retries++\n if (attempt >= this.maxAttempts) {\n this.dropped += batch.events.length\n return\n }\n await delay(2 ** attempt * 50)\n }\n }\n }\n}\n\nexport function createEventLogger(opts: EventLoggerOptions): EventLogger {\n return new EventLoggerImpl(opts)\n}\n","import { runChat, type ChatCallbacks, type ChatHandle } from './chat'\nimport { Conversation } from './conversation'\nimport { createEventLogger, type EventLogger } from './eventLog'\nimport { postEvents, postEventsKeepalive, postSignal, type ResolvedConfig } from './http'\nimport { toSignalWireBody } from './signals'\nimport type { ChatInput, SignalInput, StatsWidgetClientOptions, UserContext } from './types'\n\nconst DEFAULT_BASE_URL = 'https://widget.sensiblestats.com'\n\nexport class StatsWidgetClient {\n private readonly cfg: ResolvedConfig\n\n constructor(options: StatsWidgetClientOptions) {\n if (!options.operatorId) throw new Error('operatorId is required')\n if (!options.publicKey) throw new Error('publicKey is required')\n const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : undefined)\n if (!fetchImpl) throw new Error('No fetch implementation available; pass options.fetch')\n this.cfg = {\n operatorId: options.operatorId,\n publicKey: options.publicKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetch: fetchImpl,\n client: options.client,\n }\n }\n\n chat(input: ChatInput, callbacks?: ChatCallbacks): ChatHandle {\n return runChat(this.cfg, input, callbacks)\n }\n\n async sendSignal(input: SignalInput): Promise<void> {\n await postSignal(this.cfg, toSignalWireBody(input))\n }\n\n conversation(context?: UserContext): Conversation {\n return new Conversation(this.cfg, context)\n }\n\n createEventLogger(identity?: { operatorUserId?: string; anonymousUserId?: string; conversationId?: string }): EventLogger {\n const logger = createEventLogger({\n flush: (batch) => postEvents(this.cfg, batch),\n flushKeepalive: (batch) => postEventsKeepalive(this.cfg, batch),\n })\n if (identity) logger.setIdentity(identity)\n return logger\n }\n}\n","export type FetchLike = (input: string, init: RequestInit) => Promise<Response>\n\nexport interface StatsWidgetClientOptions {\n operatorId: string\n publicKey: string\n baseUrl?: string\n /** Advanced/testing: inject a fetch implementation. Defaults to globalThis.fetch. */\n fetch?: FetchLike\n /** Sent as X-SS-Client; set by widget-react. */\n client?: string\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\n/** Onboarding presets stage 2 (contract §3): what a tool's Send asked for. Sent only from a tool's\n * Send, beside the full sentence in `message`. The server ignores it unless every value is valid. */\nexport interface ChatPreset {\n kind: 'max_price' | 'min_price' | 'combo' | 'market'\n /** max_price, min_price */\n price?: number\n /** max_price, min_price */\n count?: number\n /** combo */\n total?: number\n /** combo */\n legs?: number\n /** market */\n marketDeveloperName?: string\n /** The picks or legs the tool showed, in the order shown (R12: the answer reprices exactly these). */\n matchOddsIds: number[]\n /** The same picks' matchId, index for index with matchOddsIds (from the grid). */\n matchIds: number[]\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 /** Features this client can draw (e.g. \"price_presets\"). The server sends nothing that needs a\n * feature the list does not name; an absent list means today's responses. */\n clientCapabilities?: string[]\n /** Onboarding presets stage 2: set only by a preset tool's Send (contract §3). */\n preset?: ChatPreset\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":[]}
|