@genex-ai/embed-sdk 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GDJLPL6W.js → chunk-UOC55SJL.js} +25 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/sentry.js +1 -1
- package/package.json +1 -1
|
@@ -7,11 +7,12 @@ var state = "pending";
|
|
|
7
7
|
var user = null;
|
|
8
8
|
var localTestMode = false;
|
|
9
9
|
var embedToken;
|
|
10
|
-
var
|
|
10
|
+
var colyseusUrls;
|
|
11
11
|
var parentOrigin = null;
|
|
12
12
|
var initialized = false;
|
|
13
13
|
var redeeming = false;
|
|
14
14
|
var requestingGuest = false;
|
|
15
|
+
var identityEpoch = 0;
|
|
15
16
|
var handshakeTimeoutMs = 1e4;
|
|
16
17
|
var refreshDelayMs = 10 * 6e4;
|
|
17
18
|
var refreshRetryMs = 6e4;
|
|
@@ -110,6 +111,9 @@ function getEmbedToken() {
|
|
|
110
111
|
function getColyseusAuth() {
|
|
111
112
|
return embedToken ? { embedToken } : void 0;
|
|
112
113
|
}
|
|
114
|
+
function getColyseusUrls() {
|
|
115
|
+
return colyseusUrls ?? [];
|
|
116
|
+
}
|
|
113
117
|
function waitForAuth() {
|
|
114
118
|
if (state === "authenticated" && user) return Promise.resolve({ user });
|
|
115
119
|
if (state === "blocked") return Promise.reject(new Error("genex embed auth: blocked"));
|
|
@@ -416,6 +420,7 @@ async function fetchDashboardOrigins() {
|
|
|
416
420
|
async function redeemTicket(ticket) {
|
|
417
421
|
if (!config || localTestMode || redeeming || state !== "pending" && state !== "guest") return;
|
|
418
422
|
const upgradingFromGuest = state === "guest";
|
|
423
|
+
const epoch = ++identityEpoch;
|
|
419
424
|
redeeming = true;
|
|
420
425
|
try {
|
|
421
426
|
const res = await doFetch(`${config.apiUrl}/api/embed/session`, {
|
|
@@ -423,16 +428,17 @@ async function redeemTicket(ticket) {
|
|
|
423
428
|
headers: { "Content-Type": "application/json" },
|
|
424
429
|
body: JSON.stringify({ ticket })
|
|
425
430
|
});
|
|
431
|
+
if (epoch !== identityEpoch) return;
|
|
426
432
|
if (!res.ok) {
|
|
427
433
|
emit("error", { error: new Error(`ticket redemption failed (${res.status})`) });
|
|
428
434
|
if (!upgradingFromGuest) await handleRedeemFailure();
|
|
429
435
|
return;
|
|
430
436
|
}
|
|
431
437
|
const body = await res.json();
|
|
438
|
+
if (epoch !== identityEpoch) return;
|
|
432
439
|
embedToken = body.embedToken;
|
|
433
440
|
user = body.user;
|
|
434
|
-
|
|
435
|
-
void colyseusUrl;
|
|
441
|
+
colyseusUrls = body.colyseus?.urls;
|
|
436
442
|
state = "authenticated";
|
|
437
443
|
clearRetryFlag();
|
|
438
444
|
removeOverlay();
|
|
@@ -447,6 +453,7 @@ async function redeemTicket(ticket) {
|
|
|
447
453
|
for (const waiter of playerWaiters.splice(0)) waiter.resolve({ user, guest: false });
|
|
448
454
|
emit("authenticated", ctx);
|
|
449
455
|
} catch (error) {
|
|
456
|
+
if (epoch !== identityEpoch) return;
|
|
450
457
|
emit("error", { error });
|
|
451
458
|
if (!upgradingFromGuest) await handleRedeemFailure();
|
|
452
459
|
} finally {
|
|
@@ -456,6 +463,7 @@ async function redeemTicket(ticket) {
|
|
|
456
463
|
async function requestGuestSession() {
|
|
457
464
|
if (!config || localTestMode || requestingGuest || redeeming) return;
|
|
458
465
|
if (state !== "pending" && state !== "guest") return;
|
|
466
|
+
const epoch = ++identityEpoch;
|
|
459
467
|
requestingGuest = true;
|
|
460
468
|
try {
|
|
461
469
|
const res = await doFetch(`${config.apiUrl}/api/embed/guest-session`, {
|
|
@@ -463,17 +471,20 @@ async function requestGuestSession() {
|
|
|
463
471
|
headers: { "Content-Type": "application/json" },
|
|
464
472
|
body: JSON.stringify({ slug: config.slug })
|
|
465
473
|
});
|
|
474
|
+
if (epoch !== identityEpoch) return;
|
|
466
475
|
if (!res.ok) {
|
|
467
476
|
emit("error", { error: new Error(`guest session failed (${res.status})`) });
|
|
468
477
|
enterBlocked();
|
|
469
478
|
return;
|
|
470
479
|
}
|
|
471
480
|
const body = await res.json();
|
|
481
|
+
if (epoch !== identityEpoch) return;
|
|
472
482
|
embedToken = body.embedToken;
|
|
473
483
|
user = body.user;
|
|
474
|
-
|
|
484
|
+
colyseusUrls = body.colyseus?.urls;
|
|
475
485
|
enterGuest();
|
|
476
486
|
} catch (error) {
|
|
487
|
+
if (epoch !== identityEpoch) return;
|
|
477
488
|
emit("error", { error });
|
|
478
489
|
enterBlocked();
|
|
479
490
|
} finally {
|
|
@@ -551,18 +562,22 @@ function scheduleRefresh() {
|
|
|
551
562
|
}
|
|
552
563
|
async function refreshToken() {
|
|
553
564
|
if (!config || state !== "authenticated" && state !== "guest" || !embedToken) return;
|
|
565
|
+
const epoch = identityEpoch;
|
|
566
|
+
const tokenAtStart = embedToken;
|
|
554
567
|
let status;
|
|
555
568
|
try {
|
|
556
569
|
const res = await doFetch(`${config.apiUrl}/api/embed/session/refresh`, {
|
|
557
570
|
method: "POST",
|
|
558
|
-
headers: { Authorization: `Bearer ${
|
|
571
|
+
headers: { Authorization: `Bearer ${tokenAtStart}` },
|
|
559
572
|
// Best-effort completion if the tab starts unloading mid-refresh; zero
|
|
560
573
|
// security consequence either way (worst case the token just expires).
|
|
561
574
|
keepalive: true
|
|
562
575
|
});
|
|
563
576
|
status = res.status;
|
|
577
|
+
if (epoch !== identityEpoch || embedToken !== tokenAtStart) return;
|
|
564
578
|
if (res.ok) {
|
|
565
579
|
const body = await res.json();
|
|
580
|
+
if (epoch !== identityEpoch || embedToken !== tokenAtStart) return;
|
|
566
581
|
embedToken = body.embedToken;
|
|
567
582
|
scheduleRefresh();
|
|
568
583
|
return;
|
|
@@ -570,6 +585,7 @@ async function refreshToken() {
|
|
|
570
585
|
} catch {
|
|
571
586
|
status = void 0;
|
|
572
587
|
}
|
|
588
|
+
if (epoch !== identityEpoch || embedToken !== tokenAtStart) return;
|
|
573
589
|
if (status === 401) {
|
|
574
590
|
if (state === "guest") {
|
|
575
591
|
void requestGuestSession();
|
|
@@ -586,6 +602,7 @@ async function refreshToken() {
|
|
|
586
602
|
}
|
|
587
603
|
function enterBlocked() {
|
|
588
604
|
if (state === "blocked") return;
|
|
605
|
+
identityEpoch++;
|
|
589
606
|
state = "blocked";
|
|
590
607
|
user = null;
|
|
591
608
|
embedToken = void 0;
|
|
@@ -724,11 +741,12 @@ function __resetForTests(overrides) {
|
|
|
724
741
|
user = null;
|
|
725
742
|
localTestMode = false;
|
|
726
743
|
embedToken = void 0;
|
|
727
|
-
|
|
744
|
+
colyseusUrls = void 0;
|
|
728
745
|
parentOrigin = null;
|
|
729
746
|
initialized = false;
|
|
730
747
|
redeeming = false;
|
|
731
748
|
requestingGuest = false;
|
|
749
|
+
identityEpoch++;
|
|
732
750
|
listeners.clear();
|
|
733
751
|
authWaiters = [];
|
|
734
752
|
playerWaiters = [];
|
|
@@ -748,6 +766,7 @@ export {
|
|
|
748
766
|
getUser,
|
|
749
767
|
getEmbedToken,
|
|
750
768
|
getColyseusAuth,
|
|
769
|
+
getColyseusUrls,
|
|
751
770
|
waitForAuth,
|
|
752
771
|
waitForPlayer,
|
|
753
772
|
on,
|
package/dist/index.d.ts
CHANGED
|
@@ -116,7 +116,7 @@ declare function getUser(): EmbedUser | null;
|
|
|
116
116
|
*/
|
|
117
117
|
declare function getEmbedToken(): string | undefined;
|
|
118
118
|
/**
|
|
119
|
-
* The credential for multiplayer: pass as `connect({ ..., auth: getColyseusAuth() })`
|
|
119
|
+
* The credential for multiplayer: pass as `connect({ ..., auth: () => getColyseusAuth() })`
|
|
120
120
|
* AFTER `await waitForPlayer()` — the relay rejects tokenless joins, but
|
|
121
121
|
* accepts guest tokens. Read it fresh at every connect() call (tokens rotate
|
|
122
122
|
* ~every 10 minutes). NEVER log this value.
|
|
@@ -124,6 +124,9 @@ declare function getEmbedToken(): string | undefined;
|
|
|
124
124
|
declare function getColyseusAuth(): {
|
|
125
125
|
embedToken: string;
|
|
126
126
|
} | undefined;
|
|
127
|
+
/** The relay URLs for this session (server-owned; a regional list when configured). Pass to
|
|
128
|
+
* connect()/matchmake() as `urls` so the SDK joins the lowest-latency one; single-url fallback. */
|
|
129
|
+
declare function getColyseusUrls(): string[];
|
|
127
130
|
/**
|
|
128
131
|
* Resolves with the signed-in ACCOUNT once authenticated; rejects if the
|
|
129
132
|
* session ends up blocked. THE gate for /state saves and any account-bound
|
|
@@ -220,4 +223,4 @@ declare function __resetForTests(overrides?: {
|
|
|
220
223
|
refreshRetryMs?: number;
|
|
221
224
|
}): void;
|
|
222
225
|
|
|
223
|
-
export { type AuthState, type EmbedConfig, type EmbedEvent, type EmbedUser, type Leaderboard, type LeaderboardEntry, type PlayerStateResult, type SaveStateResult, type SubmitScoreResult, type WorldStateResult, __resetForTests, _stashTicketFromUrl, getAuthState, getColyseusAuth, getEmbedToken, getLeaderboard, getUser, initEmbed, isEmbedded, loadPlayerState, loadWorldState, on, savePlayerState, saveWorldState, submitScore, waitForAuth, waitForPlayer };
|
|
226
|
+
export { type AuthState, type EmbedConfig, type EmbedEvent, type EmbedUser, type Leaderboard, type LeaderboardEntry, type PlayerStateResult, type SaveStateResult, type SubmitScoreResult, type WorldStateResult, __resetForTests, _stashTicketFromUrl, getAuthState, getColyseusAuth, getColyseusUrls, getEmbedToken, getLeaderboard, getUser, initEmbed, isEmbedded, loadPlayerState, loadWorldState, on, savePlayerState, saveWorldState, submitScore, waitForAuth, waitForPlayer };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
_stashTicketFromUrl,
|
|
4
4
|
getAuthState,
|
|
5
5
|
getColyseusAuth,
|
|
6
|
+
getColyseusUrls,
|
|
6
7
|
getEmbedToken,
|
|
7
8
|
getLeaderboard,
|
|
8
9
|
getUser,
|
|
@@ -16,12 +17,13 @@ import {
|
|
|
16
17
|
submitScore,
|
|
17
18
|
waitForAuth,
|
|
18
19
|
waitForPlayer
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-UOC55SJL.js";
|
|
20
21
|
export {
|
|
21
22
|
__resetForTests,
|
|
22
23
|
_stashTicketFromUrl,
|
|
23
24
|
getAuthState,
|
|
24
25
|
getColyseusAuth,
|
|
26
|
+
getColyseusUrls,
|
|
25
27
|
getEmbedToken,
|
|
26
28
|
getLeaderboard,
|
|
27
29
|
getUser,
|
package/dist/sentry.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/embed-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Player identity + durable game state for genex games — signed-in or guest play, per-player save slots, shared world state, and soft-trust leaderboards.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|