@sensiblestats/widget-sdk 0.74.0 → 0.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +6 -2
- package/dist/index.cjs +127 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +204 -2
- package/dist/index.d.ts +204 -2
- package/dist/index.js +127 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -60,6 +60,23 @@ function headersFor(cfg, json) {
|
|
|
60
60
|
if (cfg.client) h["X-SS-Client"] = cfg.client;
|
|
61
61
|
return h;
|
|
62
62
|
}
|
|
63
|
+
var OPERATOR_USER_ID_HEADER = "X-SS-Operator-User-Id";
|
|
64
|
+
var ANONYMOUS_USER_ID_HEADER = "X-SS-Anonymous-User-Id";
|
|
65
|
+
var SENDABLE_ID = /^[\x20-\x7E]{1,128}$/;
|
|
66
|
+
function isSendableId(id) {
|
|
67
|
+
const v = id?.trim();
|
|
68
|
+
return !!v && SENDABLE_ID.test(v);
|
|
69
|
+
}
|
|
70
|
+
function identityHeaders(operatorUserId, anonymousUserId) {
|
|
71
|
+
const h = {};
|
|
72
|
+
if (isSendableId(operatorUserId)) h[OPERATOR_USER_ID_HEADER] = operatorUserId.trim();
|
|
73
|
+
if (isSendableId(anonymousUserId)) h[ANONYMOUS_USER_ID_HEADER] = anonymousUserId.trim();
|
|
74
|
+
return h;
|
|
75
|
+
}
|
|
76
|
+
function splitIdentity(body) {
|
|
77
|
+
const { operatorUserId, anonymousUserId, ...rest } = body;
|
|
78
|
+
return { identity: identityHeaders(operatorUserId, anonymousUserId), rest };
|
|
79
|
+
}
|
|
63
80
|
function endpoint(cfg, path) {
|
|
64
81
|
return `${cfg.baseUrl.replace(/\/+$/, "")}/v1/${encodeURIComponent(cfg.operatorId)}/${path}`;
|
|
65
82
|
}
|
|
@@ -101,11 +118,11 @@ async function chatError(res) {
|
|
|
101
118
|
function isAbort(error) {
|
|
102
119
|
return error instanceof Error && error.name === "AbortError";
|
|
103
120
|
}
|
|
104
|
-
async function send(cfg, path, body, signal) {
|
|
121
|
+
async function send(cfg, path, body, signal, identity = {}) {
|
|
105
122
|
try {
|
|
106
123
|
return await cfg.fetch(endpoint(cfg, path), {
|
|
107
124
|
method: "POST",
|
|
108
|
-
headers: headersFor(cfg, true),
|
|
125
|
+
headers: { ...headersFor(cfg, true), ...identity },
|
|
109
126
|
body: JSON.stringify(body),
|
|
110
127
|
signal
|
|
111
128
|
});
|
|
@@ -115,24 +132,35 @@ async function send(cfg, path, body, signal) {
|
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
async function postChat(cfg, input, signal) {
|
|
118
|
-
const
|
|
135
|
+
const { userContext, ...rest } = input;
|
|
136
|
+
let body = rest;
|
|
137
|
+
let identity = {};
|
|
138
|
+
if (userContext) {
|
|
139
|
+
const split = splitIdentity(userContext);
|
|
140
|
+
identity = split.identity;
|
|
141
|
+
body = Object.keys(split.rest).length > 0 ? { ...rest, userContext: split.rest } : rest;
|
|
142
|
+
}
|
|
143
|
+
const res = await send(cfg, "chat", body, signal, identity);
|
|
119
144
|
if (!res.ok || res.body == null) throw await chatError(res);
|
|
120
145
|
return res;
|
|
121
146
|
}
|
|
122
147
|
async function postSignal(cfg, wireBody, signal) {
|
|
123
|
-
const
|
|
148
|
+
const { identity, rest } = splitIdentity(wireBody);
|
|
149
|
+
const res = await send(cfg, "signals", rest, signal, identity);
|
|
124
150
|
if (!res.ok) throw toWidgetError(res.status, res.headers.get("Retry-After"));
|
|
125
151
|
}
|
|
126
152
|
async function postEvents(cfg, batch) {
|
|
127
|
-
const
|
|
153
|
+
const { identity, rest } = splitIdentity(batch);
|
|
154
|
+
const res = await send(cfg, "events", rest, void 0, identity);
|
|
128
155
|
if (!res.ok) throw toWidgetError(res.status, res.headers.get("Retry-After"));
|
|
129
156
|
}
|
|
130
157
|
function postEventsKeepalive(cfg, batch) {
|
|
131
158
|
try {
|
|
159
|
+
const { identity, rest } = splitIdentity(batch);
|
|
132
160
|
void cfg.fetch(endpoint(cfg, "events"), {
|
|
133
161
|
method: "POST",
|
|
134
|
-
headers: headersFor(cfg, true),
|
|
135
|
-
body: JSON.stringify(
|
|
162
|
+
headers: { ...headersFor(cfg, true), ...identity },
|
|
163
|
+
body: JSON.stringify(rest),
|
|
136
164
|
keepalive: true
|
|
137
165
|
}).catch(() => {
|
|
138
166
|
});
|
|
@@ -182,8 +210,8 @@ async function postPlayerProps(cfg, matchId, sport) {
|
|
|
182
210
|
async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) {
|
|
183
211
|
const res = await cfg.fetch(endpoint(cfg, "live-monitor/schedule"), {
|
|
184
212
|
method: "POST",
|
|
185
|
-
headers: headersFor(cfg, true),
|
|
186
|
-
body: JSON.stringify({ localDate, utcOffsetMinutes, sports: ["basketball", "americanfootball"]
|
|
213
|
+
headers: { ...headersFor(cfg, true), ...identityHeaders(operatorUserId, anonymousUserId) },
|
|
214
|
+
body: JSON.stringify({ localDate, utcOffsetMinutes, sports: ["basketball", "americanfootball"] })
|
|
187
215
|
});
|
|
188
216
|
if (res.status === 404) return null;
|
|
189
217
|
if (!res.ok) throw new Error(`live-monitor/schedule ${res.status}`);
|
|
@@ -192,8 +220,8 @@ async function postSchedule(cfg, localDate, utcOffsetMinutes, operatorUserId, an
|
|
|
192
220
|
async function postLeagueStar(cfg, competitionId, starred, operatorUserId, anonymousUserId) {
|
|
193
221
|
const res = await cfg.fetch(endpoint(cfg, `leagues/${competitionId}/star`), {
|
|
194
222
|
method: "POST",
|
|
195
|
-
headers: headersFor(cfg, true),
|
|
196
|
-
body: JSON.stringify({ starred
|
|
223
|
+
headers: { ...headersFor(cfg, true), ...identityHeaders(operatorUserId, anonymousUserId) },
|
|
224
|
+
body: JSON.stringify({ starred })
|
|
197
225
|
});
|
|
198
226
|
if (res.status === 404) return null;
|
|
199
227
|
if (!res.ok) throw new Error(`leagues/star ${res.status}`);
|
|
@@ -218,7 +246,7 @@ function q(parts) {
|
|
|
218
246
|
return kept.length ? `?${kept.join("&")}` : "";
|
|
219
247
|
}
|
|
220
248
|
async function getGames(cfg, operatorUserId, gameDay) {
|
|
221
|
-
const res = await cfg.fetch(endpoint(cfg, "games" + q({
|
|
249
|
+
const res = await cfg.fetch(endpoint(cfg, "games" + q({ gameDay })), { method: "GET", headers: { ...headersFor(cfg, false), ...identityHeaders(operatorUserId) } });
|
|
222
250
|
if (res.status === 404) return null;
|
|
223
251
|
if (!res.ok) throw new Error(`games ${res.status}`);
|
|
224
252
|
return await res.json();
|
|
@@ -230,23 +258,24 @@ async function getGameConfig(cfg, gameId, fixtureId, gameDay, locale) {
|
|
|
230
258
|
return await res.json();
|
|
231
259
|
}
|
|
232
260
|
async function getGameResult(cfg, gameId, operatorUserId, fixtureId, gameDay, locale) {
|
|
233
|
-
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({
|
|
261
|
+
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/result` + q({ fixtureId, gameDay, locale })), { method: "GET", headers: { ...headersFor(cfg, false), ...identityHeaders(operatorUserId) } });
|
|
234
262
|
if (res.status === 404) return null;
|
|
235
263
|
if (!res.ok) throw new Error(`game-result ${res.status}`);
|
|
236
264
|
return await res.json();
|
|
237
265
|
}
|
|
238
266
|
async function postPlay(cfg, gameId, body, locale) {
|
|
267
|
+
const { identity, rest } = splitIdentity(body);
|
|
239
268
|
const res = await cfg.fetch(endpoint(cfg, `games/${encodeURIComponent(gameId)}/plays` + q({ locale })), {
|
|
240
269
|
method: "POST",
|
|
241
|
-
headers: headersFor(cfg, true),
|
|
242
|
-
body: JSON.stringify(
|
|
270
|
+
headers: { ...headersFor(cfg, true), ...identity },
|
|
271
|
+
body: JSON.stringify(rest)
|
|
243
272
|
});
|
|
244
273
|
if (res.status === 404) return null;
|
|
245
274
|
if (!res.ok) throw new Error(`play ${res.status}`);
|
|
246
275
|
return await res.json();
|
|
247
276
|
}
|
|
248
277
|
async function getLeaderboard(cfg, operatorUserId, week) {
|
|
249
|
-
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({
|
|
278
|
+
const res = await cfg.fetch(endpoint(cfg, "games/leaderboard" + q({ week })), { method: "GET", headers: { ...headersFor(cfg, false), ...identityHeaders(operatorUserId) } });
|
|
250
279
|
if (res.status === 404) return null;
|
|
251
280
|
if (!res.ok) throw new Error(`leaderboard ${res.status}`);
|
|
252
281
|
return await res.json();
|
|
@@ -288,11 +317,68 @@ async function getClubRecords(cfg, limit) {
|
|
|
288
317
|
return await res.json();
|
|
289
318
|
}
|
|
290
319
|
async function getPricePresets(cfg, locale, operatorUserId, options) {
|
|
291
|
-
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale,
|
|
320
|
+
const res = await cfg.fetch(endpoint(cfg, "price-presets" + q({ locale, pool: options?.pool })), { method: "GET", headers: { ...headersFor(cfg, false), ...identityHeaders(operatorUserId) } });
|
|
292
321
|
if (res.status === 404) return null;
|
|
293
322
|
if (!res.ok) throw new Error(`price-presets ${res.status}`);
|
|
294
323
|
return await res.json();
|
|
295
324
|
}
|
|
325
|
+
async function getBuilderGrid(cfg, locale, req) {
|
|
326
|
+
const query = q({
|
|
327
|
+
locale,
|
|
328
|
+
sport: req.sport,
|
|
329
|
+
legs: req.legs,
|
|
330
|
+
total: req.total,
|
|
331
|
+
marketKey: req.marketKey ?? void 0,
|
|
332
|
+
matchIds: req.widen ? void 0 : req.matchIds.join(","),
|
|
333
|
+
widen: req.widen ? "true" : void 0
|
|
334
|
+
});
|
|
335
|
+
const res = await cfg.fetch(endpoint(cfg, "price-presets" + query), {
|
|
336
|
+
method: "GET",
|
|
337
|
+
headers: { ...headersFor(cfg, false), ...identityHeaders(req.operatorUserId, req.anonymousUserId) }
|
|
338
|
+
});
|
|
339
|
+
if (res.status === 404) return null;
|
|
340
|
+
if (!res.ok) throw new Error(`price-presets ${res.status}`);
|
|
341
|
+
return await res.json();
|
|
342
|
+
}
|
|
343
|
+
function favouritePath(kind, id) {
|
|
344
|
+
return `favourites/${encodeURIComponent(kind)}/${encodeURIComponent(id)}`;
|
|
345
|
+
}
|
|
346
|
+
function favouritesFetch(cfg, method, path, operatorUserId, anonymousUserId) {
|
|
347
|
+
return cfg.fetch(endpoint(cfg, path), { method, headers: { ...headersFor(cfg, false), ...identityHeaders(operatorUserId, anonymousUserId) } });
|
|
348
|
+
}
|
|
349
|
+
async function getFavourites(cfg, sport, operatorUserId, anonymousUserId) {
|
|
350
|
+
const res = await favouritesFetch(cfg, "GET", "favourites" + q({ sport }), operatorUserId, anonymousUserId);
|
|
351
|
+
if (res.status === 400) {
|
|
352
|
+
const body = await res.json().catch(() => null);
|
|
353
|
+
return body?.code === "NoAcceptedIdentity" ? "noAcceptedIdentity" : null;
|
|
354
|
+
}
|
|
355
|
+
if (!res.ok) return null;
|
|
356
|
+
return await res.json();
|
|
357
|
+
}
|
|
358
|
+
var MIN_FAVOURITES_QUERY = 2;
|
|
359
|
+
async function searchFavourites(cfg, sport, query, kind, operatorUserId, anonymousUserId) {
|
|
360
|
+
const text = query.trim();
|
|
361
|
+
if (text.length < MIN_FAVOURITES_QUERY) return [];
|
|
362
|
+
const res = await favouritesFetch(cfg, "GET", "favourites/search" + q({ sport, q: text, kind }), operatorUserId, anonymousUserId);
|
|
363
|
+
if (!res.ok) return null;
|
|
364
|
+
return (await res.json()).results;
|
|
365
|
+
}
|
|
366
|
+
async function putFavourite(cfg, kind, id, operatorUserId, anonymousUserId) {
|
|
367
|
+
const res = await favouritesFetch(cfg, "PUT", favouritePath(kind, id), operatorUserId, anonymousUserId);
|
|
368
|
+
if (res.ok) return await res.json();
|
|
369
|
+
if (res.status !== 409) return null;
|
|
370
|
+
const body = await res.json().catch(() => null);
|
|
371
|
+
return body?.status === "atCap" ? { status: "atCap", count: body.count, cap: body.cap } : null;
|
|
372
|
+
}
|
|
373
|
+
async function deleteFavourite(cfg, kind, id, operatorUserId, anonymousUserId) {
|
|
374
|
+
return (await favouritesFetch(cfg, "DELETE", favouritePath(kind, id), operatorUserId, anonymousUserId)).ok;
|
|
375
|
+
}
|
|
376
|
+
async function clearFavourites(cfg, sport, operatorUserId, anonymousUserId) {
|
|
377
|
+
return (await favouritesFetch(cfg, "DELETE", "favourites" + q({ sport }), operatorUserId, anonymousUserId)).ok;
|
|
378
|
+
}
|
|
379
|
+
async function hideFavourite(cfg, kind, id, operatorUserId, anonymousUserId) {
|
|
380
|
+
return (await favouritesFetch(cfg, "POST", `${favouritePath(kind, id)}/hide`, operatorUserId, anonymousUserId)).ok;
|
|
381
|
+
}
|
|
296
382
|
|
|
297
383
|
// src/ndjson.ts
|
|
298
384
|
function parseLine(line) {
|
|
@@ -488,7 +574,7 @@ var Conversation = class {
|
|
|
488
574
|
}
|
|
489
575
|
sendSignal(input) {
|
|
490
576
|
const operatorUserId = input.operatorUserId ?? this.context?.operatorUserId;
|
|
491
|
-
const anonymousUserId = operatorUserId ? void 0 : input.anonymousUserId ?? this.context?.anonymousUserId;
|
|
577
|
+
const anonymousUserId = isSendableId(operatorUserId) ? void 0 : input.anonymousUserId ?? this.context?.anonymousUserId;
|
|
492
578
|
if (!operatorUserId && !anonymousUserId) {
|
|
493
579
|
throw new Error("operatorUserId or anonymousUserId is required (set it on conversation() or pass it to sendSignal)");
|
|
494
580
|
}
|
|
@@ -512,12 +598,33 @@ var Conversation = class {
|
|
|
512
598
|
getPricePresets(locale, options) {
|
|
513
599
|
return getPricePresets(this.cfg, locale, this.context?.operatorUserId, options);
|
|
514
600
|
}
|
|
601
|
+
getBuilderGrid(locale, req) {
|
|
602
|
+
return getBuilderGrid(this.cfg, locale, req);
|
|
603
|
+
}
|
|
515
604
|
getSchedule(localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) {
|
|
516
605
|
return postSchedule(this.cfg, localDate, utcOffsetMinutes, operatorUserId, anonymousUserId);
|
|
517
606
|
}
|
|
518
607
|
starLeague(competitionId, starred, operatorUserId, anonymousUserId) {
|
|
519
608
|
return postLeagueStar(this.cfg, competitionId, starred, operatorUserId, anonymousUserId);
|
|
520
609
|
}
|
|
610
|
+
getFavourites(sport, operatorUserId, anonymousUserId) {
|
|
611
|
+
return getFavourites(this.cfg, sport, operatorUserId, anonymousUserId);
|
|
612
|
+
}
|
|
613
|
+
searchFavourites(sport, query, kind, operatorUserId, anonymousUserId) {
|
|
614
|
+
return searchFavourites(this.cfg, sport, query, kind, operatorUserId, anonymousUserId);
|
|
615
|
+
}
|
|
616
|
+
putFavourite(kind, id, operatorUserId, anonymousUserId) {
|
|
617
|
+
return putFavourite(this.cfg, kind, id, operatorUserId, anonymousUserId);
|
|
618
|
+
}
|
|
619
|
+
deleteFavourite(kind, id, operatorUserId, anonymousUserId) {
|
|
620
|
+
return deleteFavourite(this.cfg, kind, id, operatorUserId, anonymousUserId);
|
|
621
|
+
}
|
|
622
|
+
clearFavourites(sport, operatorUserId, anonymousUserId) {
|
|
623
|
+
return clearFavourites(this.cfg, sport, operatorUserId, anonymousUserId);
|
|
624
|
+
}
|
|
625
|
+
hideFavourite(kind, id, operatorUserId, anonymousUserId) {
|
|
626
|
+
return hideFavourite(this.cfg, kind, id, operatorUserId, anonymousUserId);
|
|
627
|
+
}
|
|
521
628
|
getStates(matchIds, nbaGameIds, nflGameIds) {
|
|
522
629
|
return postStates(this.cfg, matchIds, nbaGameIds, nflGameIds);
|
|
523
630
|
}
|
|
@@ -567,7 +674,8 @@ var IMMEDIATE = /* @__PURE__ */ new Set([
|
|
|
567
674
|
"slip_click",
|
|
568
675
|
"slip_result",
|
|
569
676
|
"slip_remove",
|
|
570
|
-
"bet_placed"
|
|
677
|
+
"bet_placed",
|
|
678
|
+
"combo_add"
|
|
571
679
|
]);
|
|
572
680
|
var DEFERRED = /* @__PURE__ */ new Set(["match_view"]);
|
|
573
681
|
var DEFAULT_BATCH_INTERVAL_MS = 1e4;
|