@looplay/sdk 0.8.10 → 0.8.11

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.
@@ -178,7 +178,7 @@ function resolveEnvApiUrl() {
178
178
  }
179
179
 
180
180
  // src/version.ts
181
- var LOOPLAY_SDK_VERSION = "0.8.10";
181
+ var LOOPLAY_SDK_VERSION = "0.8.11";
182
182
 
183
183
  // src/apps/http.ts
184
184
  function getFetchFn(fetchOverride) {
@@ -272,9 +272,18 @@ var HttpClient = class {
272
272
  // src/apps/service-client.ts
273
273
  var ServiceClient = class {
274
274
  http;
275
+ playSessionTokens = /* @__PURE__ */ new Map();
276
+ onPlaySessionIssuedListener;
275
277
  constructor(options) {
276
278
  this.http = new HttpClient(options);
277
279
  }
280
+ /**
281
+ * Internal hook for ApiClient to subscribe to issued/renewed play sessions.
282
+ * @internal
283
+ */
284
+ _setOnPlaySessionIssued(listener) {
285
+ this.onPlaySessionIssuedListener = listener;
286
+ }
278
287
  // ─────────────────────────────────────────────────────────────────────────────
279
288
  // Auth
280
289
  // ─────────────────────────────────────────────────────────────────────────────
@@ -308,11 +317,16 @@ var ServiceClient = class {
308
317
  }
309
318
  /** Signs a fresh `playSessionToken` — required by `completePlaySession`/`completeGameplayMatch`/`recordGameplayAction`. */
310
319
  async startPlaySession(gameKey, auth = {}, body = {}) {
311
- return this.http.request("POST", "/sdk/games/play-sessions/start", {
320
+ const dto = await this.http.request("POST", "/sdk/games/play-sessions/start", {
312
321
  ...auth,
313
322
  headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
314
323
  body
315
324
  });
325
+ if (dto?.playSessionId && dto?.playSessionToken) {
326
+ this.playSessionTokens.set(dto.playSessionId, dto.playSessionToken);
327
+ }
328
+ this.onPlaySessionIssuedListener?.(dto, gameKey, auth);
329
+ return dto;
316
330
  }
317
331
  /**
318
332
  * Re-issues a fresh `playSessionToken` for the SAME `playSessionId` — call
@@ -321,33 +335,44 @@ var ServiceClient = class {
321
335
  * long-running sessions keep a single `playSessionId` throughout.
322
336
  */
323
337
  async renewPlaySession(gameKey, auth = {}, body) {
324
- return this.http.request("POST", "/sdk/games/play-sessions/renew", {
338
+ const dto = await this.http.request("POST", "/sdk/games/play-sessions/renew", {
325
339
  ...auth,
326
340
  headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
327
341
  body
328
342
  });
343
+ if (dto?.playSessionId && dto?.playSessionToken) {
344
+ this.playSessionTokens.set(dto.playSessionId, dto.playSessionToken);
345
+ }
346
+ this.onPlaySessionIssuedListener?.(dto, gameKey, auth);
347
+ return dto;
329
348
  }
330
349
  async completePlaySession(gameKey, auth, body) {
350
+ const playSessionToken = body.playSessionToken || (body.playSessionId ? this.playSessionTokens.get(body.playSessionId) : void 0);
351
+ const resolvedBody = playSessionToken ? { ...body, playSessionToken } : body;
331
352
  await this.http.request("POST", "/sdk/games/play-sessions/complete", {
332
353
  ...auth,
333
354
  headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
334
- body
355
+ body: resolvedBody
335
356
  });
336
357
  return true;
337
358
  }
338
359
  async completeGameplayMatch(gameKey, auth, body) {
360
+ const playSessionToken = body.playSessionToken || (body.playSessionId ? this.playSessionTokens.get(body.playSessionId) : void 0);
361
+ const resolvedBody = playSessionToken ? { ...body, playSessionToken } : body;
339
362
  await this.http.request("POST", "/sdk/games/matches/complete", {
340
363
  ...auth,
341
364
  headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
342
- body
365
+ body: resolvedBody
343
366
  });
344
367
  return true;
345
368
  }
346
369
  async recordGameplayAction(gameKey, auth, body) {
370
+ const playSessionToken = body.playSessionToken || (body.playSessionId ? this.playSessionTokens.get(body.playSessionId) : void 0);
371
+ const resolvedBody = playSessionToken ? { ...body, playSessionToken } : body;
347
372
  return this.http.request("POST", "/sdk/games/actions/record", {
348
373
  ...auth,
349
374
  headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
350
- body
375
+ body: resolvedBody
351
376
  });
352
377
  }
353
378
  /**
@@ -510,6 +535,18 @@ var ApiClient = class {
510
535
  fetch: options.fetch,
511
536
  defaultHeaders: options.defaultHeaders
512
537
  });
538
+ this.raw._setOnPlaySessionIssued((dto, gameKey, auth) => {
539
+ if (dto?.playSessionId && dto?.playSessionToken) {
540
+ this.currentPlaySessionId = dto.playSessionId;
541
+ this.playSession = {
542
+ cacheKey: [gameKey, dto.playSessionId, this.getTrackingAuthKey(auth)].join(":"),
543
+ gameKey,
544
+ playSessionId: dto.playSessionId,
545
+ playSessionToken: dto.playSessionToken,
546
+ expiresAtMs: dto.expiresAt ? new Date(dto.expiresAt).getTime() : Date.now() + 2 * 3600 * 1e3
547
+ };
548
+ }
549
+ });
513
550
  this.getAccessToken = options.getAccessToken;
514
551
  this.getAnonymousId = options.getAnonymousId;
515
552
  }
@@ -641,6 +678,31 @@ var ApiClient = class {
641
678
  this.playSession = void 0;
642
679
  return this.currentPlaySessionId;
643
680
  }
681
+ /**
682
+ * Starts a new play session on the server and caches the signed immediately.
683
+ */
684
+ async startPlaySessionAsync(gameKey, body = {}) {
685
+ const auth = await this.resolveTrackingAuth();
686
+ const playSessionId = body.playSessionId ?? this.currentPlaySessionId ?? this.startPlaySession();
687
+ return this.raw.startPlaySession(gameKey, auth, { ...body, playSessionId });
688
+ }
689
+ /**
690
+ * Explicitly sets or updates the active play session token cache.
691
+ */
692
+ setPlaySession(playSession) {
693
+ this.currentPlaySessionId = playSession.playSessionId;
694
+ this.playSession = {
695
+ cacheKey: [playSession.gameKey, playSession.playSessionId].join(":"),
696
+ gameKey: playSession.gameKey,
697
+ playSessionId: playSession.playSessionId,
698
+ playSessionToken: playSession.playSessionToken,
699
+ expiresAtMs: playSession.expiresAtMs ?? Date.now() + 2 * 3600 * 1e3
700
+ };
701
+ }
702
+ /** Returns the active cached play session, or undefined if none has been issued yet. */
703
+ getCurrentPlaySession() {
704
+ return this.playSession;
705
+ }
644
706
  async trackPlay(gameKey, playTimeSeconds) {
645
707
  const auth = await this.resolveTrackingAuth();
646
708
  const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();
@@ -760,6 +822,15 @@ var LooplaySDK = class {
760
822
  getGameId() {
761
823
  return this.gameId;
762
824
  }
825
+ get currentPlaySessionId() {
826
+ return this.api?.currentPlaySessionId;
827
+ }
828
+ get playSession() {
829
+ return this.api?.playSession;
830
+ }
831
+ unsafeRaw() {
832
+ return this.api?.unsafeRaw();
833
+ }
763
834
  async getMyProfile() {
764
835
  this.assertInitialized();
765
836
  if (!this.api) throw new MissingBaseUrlError();
@@ -778,6 +849,16 @@ var LooplaySDK = class {
778
849
  if (!this.api) throw new MissingBaseUrlError();
779
850
  return this.api.startPlaySession();
780
851
  }
852
+ /**
853
+ * Starts a new play session asynchronously on the backend; returns the issued PlaySessionDto
854
+ * (containing playSessionId and playSessionToken).
855
+ */
856
+ async startPlaySessionAsync(body) {
857
+ this.assertInitialized();
858
+ if (!this.api) throw new MissingBaseUrlError();
859
+ if (!this.gameId) throw new NotInitializedError();
860
+ return this.api.startPlaySessionAsync(this.gameId, body);
861
+ }
781
862
  async trackPlay(playTimeSeconds) {
782
863
  this.assertInitialized();
783
864
  if (!this.api) throw new MissingBaseUrlError();
@@ -1154,6 +1235,15 @@ var LooplayIframeAuth = class {
1154
1235
  });
1155
1236
  return this.client;
1156
1237
  }
1238
+ get currentPlaySessionId() {
1239
+ return this.getClient().currentPlaySessionId;
1240
+ }
1241
+ get playSession() {
1242
+ return this.getClient().playSession;
1243
+ }
1244
+ unsafeRaw() {
1245
+ return this.getClient().unsafeRaw();
1246
+ }
1157
1247
  /** Call once when the game view opens, before any play/match tracking. */
1158
1248
  trackView() {
1159
1249
  const gameId = this.getGameId();
@@ -1170,6 +1260,20 @@ var LooplayIframeAuth = class {
1170
1260
  startPlaySession() {
1171
1261
  return this.getClient().startPlaySession();
1172
1262
  }
1263
+ /**
1264
+ * Starts a new play session asynchronously on the backend; returns the issued PlaySessionDto
1265
+ * (containing playSessionId and playSessionToken) or null if auth/tracking is not ready.
1266
+ */
1267
+ async startPlaySessionAsync(body) {
1268
+ const gameId = this.getGameId();
1269
+ if (!this.canTrack() || !gameId) {
1270
+ this.debug("startPlaySessionAsync skipped; auth is not ready", {
1271
+ hasGameId: Boolean(gameId)
1272
+ });
1273
+ return null;
1274
+ }
1275
+ return this.getClient().startPlaySessionAsync(gameId, body);
1276
+ }
1173
1277
  trackPlay(playTimeSeconds) {
1174
1278
  const gameId = this.getGameId();
1175
1279
  if (!this.canTrack() || !gameId) {