@looplay/sdk 0.8.6 → 0.8.7
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/looplay-sdk.cjs.js +70 -10
- package/dist/looplay-sdk.cjs.js.map +1 -1
- package/dist/looplay-sdk.esm.js +70 -11
- package/dist/looplay-sdk.esm.js.map +1 -1
- package/dist/looplay-sdk.min.js +5 -3
- package/dist/looplay-sdk.min.js.map +1 -1
- package/dist/types/apps/LooplaySDK.types.d.ts +6 -0
- package/dist/types/apps/api-client.d.ts +3 -0
- package/dist/types/apps/service-client.d.ts +8 -1
- package/dist/types/iframe/iframe-auth.d.ts +9 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +1 -1
package/dist/looplay-sdk.esm.js
CHANGED
|
@@ -137,6 +137,9 @@ var LooplayAuth = class {
|
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
+
// src/version.ts
|
|
141
|
+
var LOOPLAY_SDK_VERSION = "0.8.5";
|
|
142
|
+
|
|
140
143
|
// src/apps/http.ts
|
|
141
144
|
function getFetchFn(fetchOverride) {
|
|
142
145
|
if (fetchOverride) {
|
|
@@ -164,7 +167,10 @@ var HttpClient = class {
|
|
|
164
167
|
constructor(options) {
|
|
165
168
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
166
169
|
this.fetchFn = getFetchFn(options.fetch);
|
|
167
|
-
this.defaultHeaders =
|
|
170
|
+
this.defaultHeaders = {
|
|
171
|
+
"x-looplay-sdk-version": LOOPLAY_SDK_VERSION,
|
|
172
|
+
...options.defaultHeaders ?? {}
|
|
173
|
+
};
|
|
168
174
|
}
|
|
169
175
|
async request(method, path, options) {
|
|
170
176
|
const url = this.buildUrl(path, options?.query);
|
|
@@ -267,6 +273,19 @@ var ServiceClient = class {
|
|
|
267
273
|
body
|
|
268
274
|
});
|
|
269
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Re-issues a fresh `playSessionToken` for the SAME `playSessionId` — call
|
|
278
|
+
* this instead of `startPlaySession` when refreshing an about-to-expire
|
|
279
|
+
* (or just-expired, within the server's renewal grace window) token, so
|
|
280
|
+
* long-running sessions keep a single `playSessionId` throughout.
|
|
281
|
+
*/
|
|
282
|
+
async renewPlaySession(gameKey, auth = {}, body) {
|
|
283
|
+
return this.http.request("POST", "/sdk/games/play-sessions/renew", {
|
|
284
|
+
...auth,
|
|
285
|
+
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
286
|
+
body
|
|
287
|
+
});
|
|
288
|
+
}
|
|
270
289
|
async completePlaySession(gameKey, auth, body) {
|
|
271
290
|
await this.http.request("POST", "/sdk/games/play-sessions/complete", {
|
|
272
291
|
...auth,
|
|
@@ -436,9 +455,11 @@ var ApiClient = class {
|
|
|
436
455
|
getAccessToken;
|
|
437
456
|
getAnonymousId;
|
|
438
457
|
trackingSession;
|
|
458
|
+
trackingSessionPromiseKey;
|
|
439
459
|
trackingSessionPromise;
|
|
440
460
|
currentPlaySessionId;
|
|
441
461
|
playSession;
|
|
462
|
+
playSessionPromiseKey;
|
|
442
463
|
playSessionPromise;
|
|
443
464
|
constructor(options) {
|
|
444
465
|
if (!options.baseUrl) throw new MissingBaseUrlError();
|
|
@@ -479,7 +500,10 @@ var ApiClient = class {
|
|
|
479
500
|
const bearerToken = await this.getAccessToken?.();
|
|
480
501
|
const anonId = bearerToken ? void 0 : this.getAnonymousId?.();
|
|
481
502
|
if (!bearerToken && !anonId) throw new NotAuthenticatedError();
|
|
482
|
-
const session = await this.ensureTrackingSession(
|
|
503
|
+
const session = await this.ensureTrackingSession(
|
|
504
|
+
bearerToken ? `bearer:${bearerToken}` : `anon:${anonId}`,
|
|
505
|
+
anonId
|
|
506
|
+
);
|
|
483
507
|
return {
|
|
484
508
|
bearerToken,
|
|
485
509
|
anonId,
|
|
@@ -492,14 +516,16 @@ var ApiClient = class {
|
|
|
492
516
|
* session. Swallows failures — tracking calls still work without it,
|
|
493
517
|
* just without unified session tracing.
|
|
494
518
|
*/
|
|
495
|
-
async ensureTrackingSession(anonId) {
|
|
519
|
+
async ensureTrackingSession(cacheKey, anonId) {
|
|
496
520
|
const now = Date.now();
|
|
497
|
-
if (this.trackingSession && this.trackingSession.expiresAtMs > now + 3e4) {
|
|
521
|
+
if (this.trackingSession && this.trackingSession.cacheKey === cacheKey && this.trackingSession.expiresAtMs > now + 3e4) {
|
|
498
522
|
return this.trackingSession;
|
|
499
523
|
}
|
|
500
|
-
if (!this.trackingSessionPromise) {
|
|
524
|
+
if (!this.trackingSessionPromise || this.trackingSessionPromiseKey !== cacheKey) {
|
|
525
|
+
this.trackingSessionPromiseKey = cacheKey;
|
|
501
526
|
this.trackingSessionPromise = this.raw.bootstrapTrackingSession(anonId).then((dto) => {
|
|
502
527
|
this.trackingSession = {
|
|
528
|
+
cacheKey,
|
|
503
529
|
trackingSessionId: dto.trackingSessionId,
|
|
504
530
|
anonTrackingToken: dto.trackingToken,
|
|
505
531
|
expiresAtMs: new Date(dto.expiresAt).getTime()
|
|
@@ -507,10 +533,18 @@ var ApiClient = class {
|
|
|
507
533
|
return this.trackingSession;
|
|
508
534
|
}).catch(() => void 0).finally(() => {
|
|
509
535
|
this.trackingSessionPromise = void 0;
|
|
536
|
+
this.trackingSessionPromiseKey = void 0;
|
|
510
537
|
});
|
|
511
538
|
}
|
|
512
539
|
return this.trackingSessionPromise;
|
|
513
540
|
}
|
|
541
|
+
getTrackingAuthKey(auth) {
|
|
542
|
+
return [
|
|
543
|
+
auth.bearerToken ? `bearer:${auth.bearerToken}` : `anon:${auth.anonId ?? ""}`,
|
|
544
|
+
auth.trackingSessionId ?? "",
|
|
545
|
+
auth.anonTrackingToken ?? ""
|
|
546
|
+
].join("\n");
|
|
547
|
+
}
|
|
514
548
|
/**
|
|
515
549
|
* Signs (and caches until near expiry) the `playSessionToken` required by
|
|
516
550
|
* `trackPlay`/`trackMatch`/`emit` for the current play session — does not
|
|
@@ -519,12 +553,20 @@ var ApiClient = class {
|
|
|
519
553
|
*/
|
|
520
554
|
async ensurePlaySession(gameKey, auth, playSessionId) {
|
|
521
555
|
const now = Date.now();
|
|
522
|
-
|
|
556
|
+
const cacheKey = [gameKey, playSessionId, this.getTrackingAuthKey(auth)].join("\n");
|
|
557
|
+
if (this.playSession && this.playSession.cacheKey === cacheKey && this.playSession.gameKey === gameKey && this.playSession.playSessionId === playSessionId && this.playSession.expiresAtMs > now + 1e4) {
|
|
523
558
|
return this.playSession;
|
|
524
559
|
}
|
|
525
|
-
|
|
526
|
-
|
|
560
|
+
const previous = this.playSession && this.playSession.cacheKey === cacheKey && this.playSession.gameKey === gameKey && this.playSession.playSessionId === playSessionId ? this.playSession : void 0;
|
|
561
|
+
if (!this.playSessionPromise || this.playSessionPromiseKey !== cacheKey) {
|
|
562
|
+
this.playSessionPromiseKey = cacheKey;
|
|
563
|
+
const issue = previous ? this.raw.renewPlaySession(gameKey, auth, {
|
|
564
|
+
playSessionId,
|
|
565
|
+
playSessionToken: previous.playSessionToken
|
|
566
|
+
}).catch(() => this.raw.startPlaySession(gameKey, auth, { playSessionId })) : this.raw.startPlaySession(gameKey, auth, { playSessionId });
|
|
567
|
+
this.playSessionPromise = issue.then((dto) => {
|
|
527
568
|
this.playSession = {
|
|
569
|
+
cacheKey,
|
|
528
570
|
gameKey,
|
|
529
571
|
playSessionId: dto.playSessionId,
|
|
530
572
|
playSessionToken: dto.playSessionToken,
|
|
@@ -533,6 +575,7 @@ var ApiClient = class {
|
|
|
533
575
|
return this.playSession;
|
|
534
576
|
}).finally(() => {
|
|
535
577
|
this.playSessionPromise = void 0;
|
|
578
|
+
this.playSessionPromiseKey = void 0;
|
|
536
579
|
});
|
|
537
580
|
}
|
|
538
581
|
return this.playSessionPromise;
|
|
@@ -1105,7 +1148,15 @@ var LooplayIframeAuth = class {
|
|
|
1105
1148
|
this.debug("emitGameEvent dispatched", { gameId, actionCode, ...opts });
|
|
1106
1149
|
return this.getClient().emit(gameId, actionCode, opts);
|
|
1107
1150
|
}
|
|
1108
|
-
/**
|
|
1151
|
+
/**
|
|
1152
|
+
* Idempotent; auto-emits GAME_STARTED exactly once per distinct auth
|
|
1153
|
+
* session (bearer or anonymous), and self-reports SDK integration the
|
|
1154
|
+
* same way the standalone `LooplaySDK.init()` does — without this, games
|
|
1155
|
+
* embedded via iframe never trigger the active detect call, only the
|
|
1156
|
+
* passive heartbeat that tracking calls leave behind (which doesn't fire
|
|
1157
|
+
* at all while the game is still IN_REVIEW/not LIVE, since tracking is
|
|
1158
|
+
* blocked until then).
|
|
1159
|
+
*/
|
|
1109
1160
|
initLifecycleTracking() {
|
|
1110
1161
|
if (this.lifecycleTrackingInitialized || typeof window === "undefined")
|
|
1111
1162
|
return;
|
|
@@ -1115,6 +1166,11 @@ var LooplayIframeAuth = class {
|
|
|
1115
1166
|
const key = this.getTrackingKey();
|
|
1116
1167
|
if (!key || this.lastGameStartedKey === key) return;
|
|
1117
1168
|
this.lastGameStartedKey = key;
|
|
1169
|
+
const gameId = this.getGameId();
|
|
1170
|
+
if (gameId) {
|
|
1171
|
+
this.debug("auto detectIntegration dispatch", { gameId });
|
|
1172
|
+
void this.getClient().detectIntegration(gameId).catch(() => void 0);
|
|
1173
|
+
}
|
|
1118
1174
|
this.debug("auto GAME_STARTED dispatch");
|
|
1119
1175
|
void this.emitGameEvent("GAME_STARTED");
|
|
1120
1176
|
});
|
|
@@ -1234,8 +1290,11 @@ ${identity}`;
|
|
|
1234
1290
|
}
|
|
1235
1291
|
}
|
|
1236
1292
|
setState(next) {
|
|
1293
|
+
const currentApiUrl = this.getApiUrl();
|
|
1237
1294
|
this.state = next;
|
|
1238
|
-
this.
|
|
1295
|
+
if (this.getApiUrl() !== currentApiUrl) {
|
|
1296
|
+
this.client = null;
|
|
1297
|
+
}
|
|
1239
1298
|
this.debug("auth state updated", {
|
|
1240
1299
|
gameId: this.getGameId(),
|
|
1241
1300
|
apiUrl: this.getApiUrl(),
|
|
@@ -1310,6 +1369,6 @@ ${gameId}`;
|
|
|
1310
1369
|
}
|
|
1311
1370
|
};
|
|
1312
1371
|
|
|
1313
|
-
export { ApiClient, BrowserLocalStorageAuthStorage, HttpClient, HttpError, LooplayAuth, LooplayIframeAuth, LooplaySDK, LooplaySDKError, MemoryAuthStorage, MissingAuthError, MissingBaseUrlError, NotAuthenticatedError, NotInitializedError, ServiceClient, TelegramAuthProvider };
|
|
1372
|
+
export { ApiClient, BrowserLocalStorageAuthStorage, HttpClient, HttpError, LOOPLAY_SDK_VERSION, LooplayAuth, LooplayIframeAuth, LooplaySDK, LooplaySDKError, MemoryAuthStorage, MissingAuthError, MissingBaseUrlError, NotAuthenticatedError, NotInitializedError, ServiceClient, TelegramAuthProvider };
|
|
1314
1373
|
//# sourceMappingURL=looplay-sdk.esm.js.map
|
|
1315
1374
|
//# sourceMappingURL=looplay-sdk.esm.js.map
|