@looplay/sdk 0.8.7 → 0.8.9
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/README.md +10 -9
- package/dist/looplay-sdk.cjs.js +72 -14
- package/dist/looplay-sdk.cjs.js.map +1 -1
- package/dist/looplay-sdk.esm.js +69 -15
- 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/constants.d.ts +20 -0
- package/dist/types/iframe/iframe-auth.d.ts +7 -6
- package/dist/types/iframe/types.d.ts +4 -4
- package/dist/types/index.d.ts +1 -0
- package/dist/types/looplay-sdk.d.ts +7 -0
- package/dist/types/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,6 @@ import { LooplayIframeAuth } from '@looplay/sdk';
|
|
|
35
35
|
|
|
36
36
|
export const looplayAuth = new LooplayIframeAuth({
|
|
37
37
|
appId: 'YOUR_APP_ID', // from your creator dashboard — required
|
|
38
|
-
apiUrl: 'https://api.looplay.gg',
|
|
39
38
|
});
|
|
40
39
|
```
|
|
41
40
|
|
|
@@ -64,10 +63,11 @@ backward compatibility, but you should set one regardless).
|
|
|
64
63
|
import { LooplayIframeAuth } from '@looplay/sdk';
|
|
65
64
|
|
|
66
65
|
// 1. Initialize the SDK
|
|
66
|
+
// apiUrl and parentOrigin are automatically configured:
|
|
67
|
+
// - parentOrigin defaults to import.meta.env.VITE_PARENT_ORIGIN (or document.referrer)
|
|
68
|
+
// - apiUrl defaults to import.meta.env.VITE_API_URL (or 'https://api.looplay.gg')
|
|
67
69
|
export const looplayAuth = new LooplayIframeAuth({
|
|
68
70
|
appId: 'YOUR_APP_ID', // from your creator dashboard
|
|
69
|
-
apiUrl: 'https://api.looplay.gg', // required for standalone builds; optional inside the iframe
|
|
70
|
-
parentOrigin: import.meta.env.VITE_PARENT_ORIGIN, // restrict the accepted postMessage origin
|
|
71
71
|
|
|
72
72
|
// Optional: Auto-request rewarded ads after match activity
|
|
73
73
|
autoRequestAds: {
|
|
@@ -309,7 +309,6 @@ directly, no bundler needed:
|
|
|
309
309
|
<script>
|
|
310
310
|
const looplayAuth = new LooplaySDK.LooplayIframeAuth({
|
|
311
311
|
appId: 'YOUR_APP_ID',
|
|
312
|
-
apiUrl: 'https://api.looplay.gg',
|
|
313
312
|
});
|
|
314
313
|
looplayAuth.init();
|
|
315
314
|
looplayAuth.initLifecycleTracking();
|
|
@@ -334,11 +333,13 @@ that's a separate opt-in browser bundle, only needed if you want
|
|
|
334
333
|
</script>
|
|
335
334
|
```
|
|
336
335
|
|
|
337
|
-
**Security note**: the origin check relies on `parentOrigin` (explicit option
|
|
338
|
-
or `
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
336
|
+
**Security note**: the origin check relies on `parentOrigin` (explicit option
|
|
337
|
+
or `import.meta.env.VITE_PARENT_ORIGIN`), falling back to `document.referrer`.
|
|
338
|
+
Referrer can be stripped by `Referrer-Policy`, browser privacy settings, or
|
|
339
|
+
extensions — when that happens and no `parentOrigin` or `VITE_PARENT_ORIGIN` is configured,
|
|
340
|
+
the check is skipped and `LooplayIframeAuth` logs a `console.warn`. Configure
|
|
341
|
+
`VITE_PARENT_ORIGIN` in your environment or pass `parentOrigin` explicitly
|
|
342
|
+
in production embeds instead of relying solely on the referrer fallback.
|
|
342
343
|
|
|
343
344
|
**Lifecycle**: call `dispose()` when tearing down (route change, HMR, test
|
|
344
345
|
cleanup) to remove the `message` listener and clear subscribers:
|
package/dist/looplay-sdk.cjs.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
3
4
|
// src/errors.ts
|
|
4
5
|
var LooplaySDKError = class extends Error {
|
|
5
6
|
constructor(message) {
|
|
@@ -684,6 +685,43 @@ var ApiClient = class {
|
|
|
684
685
|
}
|
|
685
686
|
};
|
|
686
687
|
|
|
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
|
+
|
|
687
725
|
// src/looplay-sdk.ts
|
|
688
726
|
var LooplaySDK = class {
|
|
689
727
|
auth;
|
|
@@ -691,7 +729,12 @@ var LooplaySDK = class {
|
|
|
691
729
|
gameId;
|
|
692
730
|
initialized = false;
|
|
693
731
|
constructor(options = {}) {
|
|
694
|
-
const {
|
|
732
|
+
const {
|
|
733
|
+
auth,
|
|
734
|
+
baseUrl = resolveEnvApiUrl() ?? DEFAULT_API_URL,
|
|
735
|
+
fetch,
|
|
736
|
+
defaultHeaders
|
|
737
|
+
} = options;
|
|
695
738
|
if (auth) {
|
|
696
739
|
this.auth = new LooplayAuth(auth);
|
|
697
740
|
}
|
|
@@ -776,9 +819,23 @@ var LooplaySDK = class {
|
|
|
776
819
|
if (!this.api) throw new MissingBaseUrlError();
|
|
777
820
|
await this.api.listGameAssets(params.gameId);
|
|
778
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* Best-effort self-report — must never block init(). A missing/misconfigured
|
|
824
|
+
* whitelist (a separate setup step from SDK integration) makes the backend
|
|
825
|
+
* reject this call; if that rejection propagated, the whole init() would
|
|
826
|
+
* reject too and every other SDK method would throw NotInitializedError,
|
|
827
|
+
* breaking a game over what's really just an unfinished onboarding step.
|
|
828
|
+
*/
|
|
779
829
|
async detectIntegration(params) {
|
|
780
830
|
if (!this.api) return;
|
|
781
|
-
|
|
831
|
+
try {
|
|
832
|
+
await this.api.detectIntegration(params.gameId);
|
|
833
|
+
} catch (error) {
|
|
834
|
+
console.warn(
|
|
835
|
+
"[LooplaySDK] detectIntegration failed (SDK will still initialize) \u2014 check that this game has a whitelisted origin/domain configured:",
|
|
836
|
+
error
|
|
837
|
+
);
|
|
838
|
+
}
|
|
782
839
|
}
|
|
783
840
|
};
|
|
784
841
|
|
|
@@ -950,7 +1007,7 @@ var LooplayIframeAuth = class {
|
|
|
950
1007
|
return this.state.jwt;
|
|
951
1008
|
}
|
|
952
1009
|
getApiUrl() {
|
|
953
|
-
return this.state.apiUrl ?? this.options.apiUrl ??
|
|
1010
|
+
return this.state.apiUrl ?? this.options.apiUrl ?? resolveEnvApiUrl() ?? DEFAULT_API_URL;
|
|
954
1011
|
}
|
|
955
1012
|
/** Resolves to the configured `appId`, falling back to whatever the parent pushed as `gameId`. */
|
|
956
1013
|
getGameId() {
|
|
@@ -1152,12 +1209,13 @@ var LooplayIframeAuth = class {
|
|
|
1152
1209
|
}
|
|
1153
1210
|
/**
|
|
1154
1211
|
* Idempotent; auto-emits GAME_STARTED exactly once per distinct auth
|
|
1155
|
-
* session (bearer or anonymous)
|
|
1156
|
-
*
|
|
1157
|
-
*
|
|
1158
|
-
*
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1212
|
+
* session (bearer or anonymous). SDK integration self-reporting for the
|
|
1213
|
+
* iframe path lives in `detectIntegrationOnce()` (fired from `setState()`
|
|
1214
|
+
* on every auth/config change, not gated behind lifecycle tracking being
|
|
1215
|
+
* enabled at all) — without it, games embedded via iframe would never
|
|
1216
|
+
* trigger the active detect call, only the passive heartbeat that
|
|
1217
|
+
* tracking calls leave behind (which doesn't fire while the game is still
|
|
1218
|
+
* IN_REVIEW/not LIVE, since tracking is blocked until then).
|
|
1161
1219
|
*/
|
|
1162
1220
|
initLifecycleTracking() {
|
|
1163
1221
|
if (this.lifecycleTrackingInitialized || typeof window === "undefined")
|
|
@@ -1168,11 +1226,6 @@ var LooplayIframeAuth = class {
|
|
|
1168
1226
|
const key = this.getTrackingKey();
|
|
1169
1227
|
if (!key || this.lastGameStartedKey === key) return;
|
|
1170
1228
|
this.lastGameStartedKey = key;
|
|
1171
|
-
const gameId = this.getGameId();
|
|
1172
|
-
if (gameId) {
|
|
1173
|
-
this.debug("auto detectIntegration dispatch", { gameId });
|
|
1174
|
-
void this.getClient().detectIntegration(gameId).catch(() => void 0);
|
|
1175
|
-
}
|
|
1176
1229
|
this.debug("auto GAME_STARTED dispatch");
|
|
1177
1230
|
void this.emitGameEvent("GAME_STARTED");
|
|
1178
1231
|
});
|
|
@@ -1330,6 +1383,8 @@ ${gameId}`;
|
|
|
1330
1383
|
}
|
|
1331
1384
|
resolveParentOrigin() {
|
|
1332
1385
|
if (this.options.parentOrigin) return this.options.parentOrigin;
|
|
1386
|
+
const envOrigin = resolveEnvParentOrigin();
|
|
1387
|
+
if (envOrigin) return envOrigin;
|
|
1333
1388
|
if (typeof document === "undefined" || !document.referrer) return null;
|
|
1334
1389
|
try {
|
|
1335
1390
|
return new URL(document.referrer).origin;
|
|
@@ -1373,6 +1428,7 @@ ${gameId}`;
|
|
|
1373
1428
|
|
|
1374
1429
|
exports.ApiClient = ApiClient;
|
|
1375
1430
|
exports.BrowserLocalStorageAuthStorage = BrowserLocalStorageAuthStorage;
|
|
1431
|
+
exports.DEFAULT_API_URL = DEFAULT_API_URL;
|
|
1376
1432
|
exports.HttpClient = HttpClient;
|
|
1377
1433
|
exports.HttpError = HttpError;
|
|
1378
1434
|
exports.LOOPLAY_SDK_VERSION = LOOPLAY_SDK_VERSION;
|
|
@@ -1387,5 +1443,7 @@ exports.NotAuthenticatedError = NotAuthenticatedError;
|
|
|
1387
1443
|
exports.NotInitializedError = NotInitializedError;
|
|
1388
1444
|
exports.ServiceClient = ServiceClient;
|
|
1389
1445
|
exports.TelegramAuthProvider = TelegramAuthProvider;
|
|
1446
|
+
exports.resolveEnvApiUrl = resolveEnvApiUrl;
|
|
1447
|
+
exports.resolveEnvParentOrigin = resolveEnvParentOrigin;
|
|
1390
1448
|
//# sourceMappingURL=looplay-sdk.cjs.js.map
|
|
1391
1449
|
//# sourceMappingURL=looplay-sdk.cjs.js.map
|