@looplay/sdk 0.8.9 → 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.
- package/dist/looplay-sdk.cjs.js +167 -59
- package/dist/looplay-sdk.cjs.js.map +1 -1
- package/dist/looplay-sdk.esm.js +167 -59
- package/dist/looplay-sdk.esm.js.map +1 -1
- package/dist/looplay-sdk.min.js +5 -5
- package/dist/looplay-sdk.min.js.map +1 -1
- package/dist/types/apps/api-client.d.ts +27 -4
- package/dist/types/apps/http.d.ts +2 -2
- package/dist/types/apps/service-client.d.ts +8 -0
- package/dist/types/iframe/iframe-auth.d.ts +12 -3
- package/dist/types/looplay-sdk.d.ts +11 -2
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/looplay-sdk.cjs.js
CHANGED
|
@@ -140,8 +140,45 @@ var LooplayAuth = class {
|
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
+
// src/constants.ts
|
|
144
|
+
var DEFAULT_API_URL = "https://miniapp-api.looplay.gg";
|
|
145
|
+
function resolveEnvParentOrigin() {
|
|
146
|
+
try {
|
|
147
|
+
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('looplay-sdk.cjs.js', document.baseURI).href)) }) !== "undefined" && undefined?.VITE_PARENT_ORIGIN) {
|
|
148
|
+
const val = undefined.VITE_PARENT_ORIGIN;
|
|
149
|
+
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
150
|
+
}
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
if (typeof process !== "undefined" && process.env?.VITE_PARENT_ORIGIN) {
|
|
155
|
+
const val = process.env.VITE_PARENT_ORIGIN;
|
|
156
|
+
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
function resolveEnvApiUrl() {
|
|
163
|
+
try {
|
|
164
|
+
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('looplay-sdk.cjs.js', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
165
|
+
const val = undefined.VITE_API_URL ?? undefined.VITE_LOOPLAY_API_URL;
|
|
166
|
+
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
if (typeof process !== "undefined" && process.env) {
|
|
172
|
+
const val = process.env.VITE_API_URL ?? process.env.VITE_LOOPLAY_API_URL;
|
|
173
|
+
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
}
|
|
177
|
+
return void 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
143
180
|
// src/version.ts
|
|
144
|
-
var LOOPLAY_SDK_VERSION = "0.8.
|
|
181
|
+
var LOOPLAY_SDK_VERSION = "0.8.11";
|
|
145
182
|
|
|
146
183
|
// src/apps/http.ts
|
|
147
184
|
function getFetchFn(fetchOverride) {
|
|
@@ -167,8 +204,9 @@ var HttpClient = class {
|
|
|
167
204
|
baseUrl;
|
|
168
205
|
fetchFn;
|
|
169
206
|
defaultHeaders;
|
|
170
|
-
constructor(options) {
|
|
171
|
-
|
|
207
|
+
constructor(options = {}) {
|
|
208
|
+
const rawBaseUrl = typeof options.baseUrl === "string" && options.baseUrl.trim().length > 0 ? options.baseUrl.trim() : resolveEnvApiUrl() ?? DEFAULT_API_URL;
|
|
209
|
+
this.baseUrl = rawBaseUrl.replace(/\/$/, "");
|
|
172
210
|
this.fetchFn = getFetchFn(options.fetch);
|
|
173
211
|
this.defaultHeaders = {
|
|
174
212
|
"x-looplay-sdk-version": LOOPLAY_SDK_VERSION,
|
|
@@ -234,9 +272,18 @@ var HttpClient = class {
|
|
|
234
272
|
// src/apps/service-client.ts
|
|
235
273
|
var ServiceClient = class {
|
|
236
274
|
http;
|
|
275
|
+
playSessionTokens = /* @__PURE__ */ new Map();
|
|
276
|
+
onPlaySessionIssuedListener;
|
|
237
277
|
constructor(options) {
|
|
238
278
|
this.http = new HttpClient(options);
|
|
239
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
|
+
}
|
|
240
287
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
241
288
|
// Auth
|
|
242
289
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -270,11 +317,16 @@ var ServiceClient = class {
|
|
|
270
317
|
}
|
|
271
318
|
/** Signs a fresh `playSessionToken` — required by `completePlaySession`/`completeGameplayMatch`/`recordGameplayAction`. */
|
|
272
319
|
async startPlaySession(gameKey, auth = {}, body = {}) {
|
|
273
|
-
|
|
320
|
+
const dto = await this.http.request("POST", "/sdk/games/play-sessions/start", {
|
|
274
321
|
...auth,
|
|
275
322
|
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
276
323
|
body
|
|
277
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;
|
|
278
330
|
}
|
|
279
331
|
/**
|
|
280
332
|
* Re-issues a fresh `playSessionToken` for the SAME `playSessionId` — call
|
|
@@ -283,33 +335,44 @@ var ServiceClient = class {
|
|
|
283
335
|
* long-running sessions keep a single `playSessionId` throughout.
|
|
284
336
|
*/
|
|
285
337
|
async renewPlaySession(gameKey, auth = {}, body) {
|
|
286
|
-
|
|
338
|
+
const dto = await this.http.request("POST", "/sdk/games/play-sessions/renew", {
|
|
287
339
|
...auth,
|
|
288
340
|
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
289
341
|
body
|
|
290
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;
|
|
291
348
|
}
|
|
292
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;
|
|
293
352
|
await this.http.request("POST", "/sdk/games/play-sessions/complete", {
|
|
294
353
|
...auth,
|
|
295
354
|
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
296
|
-
body
|
|
355
|
+
body: resolvedBody
|
|
297
356
|
});
|
|
298
357
|
return true;
|
|
299
358
|
}
|
|
300
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;
|
|
301
362
|
await this.http.request("POST", "/sdk/games/matches/complete", {
|
|
302
363
|
...auth,
|
|
303
364
|
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
304
|
-
body
|
|
365
|
+
body: resolvedBody
|
|
305
366
|
});
|
|
306
367
|
return true;
|
|
307
368
|
}
|
|
308
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;
|
|
309
372
|
return this.http.request("POST", "/sdk/games/actions/record", {
|
|
310
373
|
...auth,
|
|
311
374
|
headers: { "x-game-key": gameKey, ...this.trackingHeaders(auth) },
|
|
312
|
-
body
|
|
375
|
+
body: resolvedBody
|
|
313
376
|
});
|
|
314
377
|
}
|
|
315
378
|
/**
|
|
@@ -464,13 +527,26 @@ var ApiClient = class {
|
|
|
464
527
|
playSession;
|
|
465
528
|
playSessionPromiseKey;
|
|
466
529
|
playSessionPromise;
|
|
467
|
-
constructor(options) {
|
|
468
|
-
|
|
530
|
+
constructor(options = {}) {
|
|
531
|
+
const baseUrl = typeof options.baseUrl === "string" && options.baseUrl.trim().length > 0 ? options.baseUrl.trim() : resolveEnvApiUrl() ?? DEFAULT_API_URL;
|
|
532
|
+
if (!baseUrl) throw new MissingBaseUrlError();
|
|
469
533
|
this.raw = new ServiceClient({
|
|
470
|
-
baseUrl
|
|
534
|
+
baseUrl,
|
|
471
535
|
fetch: options.fetch,
|
|
472
536
|
defaultHeaders: options.defaultHeaders
|
|
473
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
|
+
});
|
|
474
550
|
this.getAccessToken = options.getAccessToken;
|
|
475
551
|
this.getAnonymousId = options.getAnonymousId;
|
|
476
552
|
}
|
|
@@ -602,6 +678,31 @@ var ApiClient = class {
|
|
|
602
678
|
this.playSession = void 0;
|
|
603
679
|
return this.currentPlaySessionId;
|
|
604
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
|
+
}
|
|
605
706
|
async trackPlay(gameKey, playTimeSeconds) {
|
|
606
707
|
const auth = await this.resolveTrackingAuth();
|
|
607
708
|
const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();
|
|
@@ -685,43 +786,6 @@ var ApiClient = class {
|
|
|
685
786
|
}
|
|
686
787
|
};
|
|
687
788
|
|
|
688
|
-
// src/constants.ts
|
|
689
|
-
var DEFAULT_API_URL = "https://miniapp-api.looplay.gg";
|
|
690
|
-
function resolveEnvParentOrigin() {
|
|
691
|
-
try {
|
|
692
|
-
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('looplay-sdk.cjs.js', document.baseURI).href)) }) !== "undefined" && undefined?.VITE_PARENT_ORIGIN) {
|
|
693
|
-
const val = undefined.VITE_PARENT_ORIGIN;
|
|
694
|
-
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
695
|
-
}
|
|
696
|
-
} catch {
|
|
697
|
-
}
|
|
698
|
-
try {
|
|
699
|
-
if (typeof process !== "undefined" && process.env?.VITE_PARENT_ORIGIN) {
|
|
700
|
-
const val = process.env.VITE_PARENT_ORIGIN;
|
|
701
|
-
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
702
|
-
}
|
|
703
|
-
} catch {
|
|
704
|
-
}
|
|
705
|
-
return void 0;
|
|
706
|
-
}
|
|
707
|
-
function resolveEnvApiUrl() {
|
|
708
|
-
try {
|
|
709
|
-
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('looplay-sdk.cjs.js', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
710
|
-
const val = undefined.VITE_API_URL ?? undefined.VITE_LOOPLAY_API_URL;
|
|
711
|
-
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
712
|
-
}
|
|
713
|
-
} catch {
|
|
714
|
-
}
|
|
715
|
-
try {
|
|
716
|
-
if (typeof process !== "undefined" && process.env) {
|
|
717
|
-
const val = process.env.VITE_API_URL ?? process.env.VITE_LOOPLAY_API_URL;
|
|
718
|
-
if (typeof val === "string" && val.trim().length > 0) return val.trim();
|
|
719
|
-
}
|
|
720
|
-
} catch {
|
|
721
|
-
}
|
|
722
|
-
return void 0;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
789
|
// src/looplay-sdk.ts
|
|
726
790
|
var LooplaySDK = class {
|
|
727
791
|
auth;
|
|
@@ -731,21 +795,19 @@ var LooplaySDK = class {
|
|
|
731
795
|
constructor(options = {}) {
|
|
732
796
|
const {
|
|
733
797
|
auth,
|
|
734
|
-
baseUrl = resolveEnvApiUrl() ?? DEFAULT_API_URL,
|
|
735
798
|
fetch,
|
|
736
799
|
defaultHeaders
|
|
737
800
|
} = options;
|
|
801
|
+
const baseUrl = typeof options.baseUrl === "string" && options.baseUrl.trim().length > 0 ? options.baseUrl.trim() : resolveEnvApiUrl() ?? DEFAULT_API_URL;
|
|
738
802
|
if (auth) {
|
|
739
803
|
this.auth = new LooplayAuth(auth);
|
|
740
804
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
});
|
|
748
|
-
}
|
|
805
|
+
this.api = new ApiClient({
|
|
806
|
+
baseUrl,
|
|
807
|
+
fetch,
|
|
808
|
+
defaultHeaders,
|
|
809
|
+
getAccessToken: async () => this.auth?.getAccessToken()
|
|
810
|
+
});
|
|
749
811
|
}
|
|
750
812
|
async init(params) {
|
|
751
813
|
this.gameId = params.gameId;
|
|
@@ -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();
|
|
@@ -1007,7 +1088,8 @@ var LooplayIframeAuth = class {
|
|
|
1007
1088
|
return this.state.jwt;
|
|
1008
1089
|
}
|
|
1009
1090
|
getApiUrl() {
|
|
1010
|
-
|
|
1091
|
+
const raw = toOptionalString(this.state.apiUrl) ?? toOptionalString(this.options.apiUrl) ?? resolveEnvApiUrl() ?? DEFAULT_API_URL;
|
|
1092
|
+
return raw.trim();
|
|
1011
1093
|
}
|
|
1012
1094
|
/** Resolves to the configured `appId`, falling back to whatever the parent pushed as `gameId`. */
|
|
1013
1095
|
getGameId() {
|
|
@@ -1153,6 +1235,15 @@ var LooplayIframeAuth = class {
|
|
|
1153
1235
|
});
|
|
1154
1236
|
return this.client;
|
|
1155
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
|
+
}
|
|
1156
1247
|
/** Call once when the game view opens, before any play/match tracking. */
|
|
1157
1248
|
trackView() {
|
|
1158
1249
|
const gameId = this.getGameId();
|
|
@@ -1169,6 +1260,20 @@ var LooplayIframeAuth = class {
|
|
|
1169
1260
|
startPlaySession() {
|
|
1170
1261
|
return this.getClient().startPlaySession();
|
|
1171
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
|
+
}
|
|
1172
1277
|
trackPlay(playTimeSeconds) {
|
|
1173
1278
|
const gameId = this.getGameId();
|
|
1174
1279
|
if (!this.canTrack() || !gameId) {
|
|
@@ -1382,7 +1487,10 @@ ${gameId}`;
|
|
|
1382
1487
|
}
|
|
1383
1488
|
}
|
|
1384
1489
|
resolveParentOrigin() {
|
|
1385
|
-
if (this.options.parentOrigin)
|
|
1490
|
+
if (this.options.parentOrigin) {
|
|
1491
|
+
const opt = toOptionalString(this.options.parentOrigin);
|
|
1492
|
+
if (opt) return opt;
|
|
1493
|
+
}
|
|
1386
1494
|
const envOrigin = resolveEnvParentOrigin();
|
|
1387
1495
|
if (envOrigin) return envOrigin;
|
|
1388
1496
|
if (typeof document === "undefined" || !document.referrer) return null;
|