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