@series-inc/venus-sdk 3.0.4 → 3.1.0-beta.0
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 +324 -123
- package/dist/{AdsApi-CNGRf6j0.d.mts → AdsApi-meVfUcZy.d.mts} +37 -25
- package/dist/{AdsApi-CNGRf6j0.d.ts → AdsApi-meVfUcZy.d.ts} +37 -25
- package/dist/chunk-2PDL7CQK.mjs +26 -0
- package/dist/chunk-2PDL7CQK.mjs.map +1 -0
- package/dist/{chunk-PXWCNWJ6.mjs → chunk-EMVTVSGL.mjs} +421 -109
- package/dist/chunk-EMVTVSGL.mjs.map +1 -0
- package/dist/chunk-IZLOB7DV.mjs +343 -0
- package/dist/chunk-IZLOB7DV.mjs.map +1 -0
- package/dist/{chunk-W7IPHM67.mjs → chunk-QABXMFND.mjs} +3 -26
- package/dist/chunk-QABXMFND.mjs.map +1 -0
- package/dist/core-5JLON75E.mjs +4 -0
- package/dist/{core-R3FHW62G.mjs.map → core-5JLON75E.mjs.map} +1 -1
- package/dist/index.cjs +768 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +140 -25
- package/dist/index.d.ts +140 -25
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/dist/venus-api/index.cjs +452 -101
- package/dist/venus-api/index.cjs.map +1 -1
- package/dist/venus-api/index.d.mts +2 -2
- package/dist/venus-api/index.d.ts +2 -2
- package/dist/venus-api/index.mjs +46 -3
- package/dist/venus-api/index.mjs.map +1 -1
- package/dist/vite/index.cjs +534 -0
- package/dist/vite/index.cjs.map +1 -0
- package/dist/vite/index.mjs +527 -0
- package/dist/vite/index.mjs.map +1 -0
- package/dist/webview/index.cjs +346 -0
- package/dist/webview/index.cjs.map +1 -0
- package/dist/webview/index.d.mts +17 -0
- package/dist/webview/index.d.ts +17 -0
- package/dist/webview/index.mjs +4 -0
- package/dist/webview/index.mjs.map +1 -0
- package/package.json +19 -1
- package/dist/chunk-PXWCNWJ6.mjs.map +0 -1
- package/dist/chunk-W7IPHM67.mjs.map +0 -1
- package/dist/core-R3FHW62G.mjs +0 -3
package/dist/index.cjs
CHANGED
|
@@ -329,11 +329,11 @@ var VenusMessageId = /* @__PURE__ */ ((VenusMessageId2) => {
|
|
|
329
329
|
VenusMessageId2["H5_SIMULATION_GET_AVAILABLE_ITEMS"] = "H5_SIMULATION_GET_AVAILABLE_ITEMS";
|
|
330
330
|
VenusMessageId2["H5_SIMULATION_VALIDATE_ASSIGNMENT"] = "H5_SIMULATION_VALIDATE_ASSIGNMENT";
|
|
331
331
|
VenusMessageId2["H5_SIMULATION_BATCH_OPERATIONS"] = "H5_SIMULATION_BATCH_OPERATIONS";
|
|
332
|
-
VenusMessageId2["
|
|
332
|
+
VenusMessageId2["H5_LEADERBOARD_CREATE_SCORE_TOKEN"] = "H5_LEADERBOARD_CREATE_SCORE_TOKEN";
|
|
333
333
|
VenusMessageId2["H5_LEADERBOARD_SUBMIT_SCORE"] = "H5_LEADERBOARD_SUBMIT_SCORE";
|
|
334
|
-
VenusMessageId2["
|
|
335
|
-
VenusMessageId2["
|
|
336
|
-
VenusMessageId2["
|
|
334
|
+
VenusMessageId2["H5_LEADERBOARD_GET_PAGED_SCORES"] = "H5_LEADERBOARD_GET_PAGED_SCORES";
|
|
335
|
+
VenusMessageId2["H5_LEADERBOARD_GET_PODIUM_SCORES"] = "H5_LEADERBOARD_GET_PODIUM_SCORES";
|
|
336
|
+
VenusMessageId2["H5_LEADERBOARD_GET_MY_RANK"] = "H5_LEADERBOARD_GET_MY_RANK";
|
|
337
337
|
VenusMessageId2["H5_ROOM_CREATE"] = "H5_ROOM_CREATE";
|
|
338
338
|
VenusMessageId2["H5_ROOM_JOIN"] = "H5_ROOM_JOIN";
|
|
339
339
|
VenusMessageId2["H5_ROOM_JOIN_OR_CREATE"] = "H5_ROOM_JOIN_OR_CREATE";
|
|
@@ -3364,9 +3364,11 @@ function isPacificDaylightTime(date) {
|
|
|
3364
3364
|
|
|
3365
3365
|
// src/time/HostTimeApi.ts
|
|
3366
3366
|
var HostTimeApi = class {
|
|
3367
|
-
constructor(rpcClient) {
|
|
3367
|
+
constructor(rpcClient, venusApi) {
|
|
3368
3368
|
__publicField(this, "rpcClient");
|
|
3369
|
+
__publicField(this, "venusApi");
|
|
3369
3370
|
this.rpcClient = rpcClient;
|
|
3371
|
+
this.venusApi = venusApi;
|
|
3370
3372
|
}
|
|
3371
3373
|
async requestTimeAsync() {
|
|
3372
3374
|
const response = await this.rpcClient.call(
|
|
@@ -3376,13 +3378,7 @@ var HostTimeApi = class {
|
|
|
3376
3378
|
return response;
|
|
3377
3379
|
}
|
|
3378
3380
|
formatTime(timestamp, options) {
|
|
3379
|
-
|
|
3380
|
-
const windowVenus = window.venus;
|
|
3381
|
-
if (windowVenus._config.locale) {
|
|
3382
|
-
locale = windowVenus._config.locale;
|
|
3383
|
-
} else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
|
|
3384
|
-
locale = windowVenus._config.environment.browserInfo.language;
|
|
3385
|
-
}
|
|
3381
|
+
const locale = this.venusApi.getLocale();
|
|
3386
3382
|
const date = new Date(timestamp);
|
|
3387
3383
|
const dateTimeOptions = {
|
|
3388
3384
|
dateStyle: options.dateStyle || "medium",
|
|
@@ -3394,13 +3390,7 @@ var HostTimeApi = class {
|
|
|
3394
3390
|
}
|
|
3395
3391
|
formatNumber(value, options) {
|
|
3396
3392
|
try {
|
|
3397
|
-
|
|
3398
|
-
const windowVenus = window.venus;
|
|
3399
|
-
if (windowVenus._config.locale) {
|
|
3400
|
-
locale = windowVenus._config.locale;
|
|
3401
|
-
} else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
|
|
3402
|
-
locale = windowVenus._config.environment.browserInfo.language;
|
|
3403
|
-
}
|
|
3393
|
+
const locale = this.venusApi.getLocale();
|
|
3404
3394
|
const numberOptions = {
|
|
3405
3395
|
style: options?.style || "decimal",
|
|
3406
3396
|
minimumFractionDigits: options?.minimumFractionDigits || 0,
|
|
@@ -3463,7 +3453,7 @@ var MockTimeApi = class {
|
|
|
3463
3453
|
this.venusApi = venusApi;
|
|
3464
3454
|
}
|
|
3465
3455
|
formatNumber(value, options) {
|
|
3466
|
-
const locale = this.getLocale();
|
|
3456
|
+
const locale = this.venusApi.getLocale();
|
|
3467
3457
|
const numberOptions = {
|
|
3468
3458
|
style: options?.style || "decimal",
|
|
3469
3459
|
minimumFractionDigits: options?.minimumFractionDigits || 0,
|
|
@@ -3474,7 +3464,7 @@ var MockTimeApi = class {
|
|
|
3474
3464
|
return value.toLocaleString(locale, numberOptions);
|
|
3475
3465
|
}
|
|
3476
3466
|
formatTime(timestamp, options) {
|
|
3477
|
-
const locale = this.getLocale();
|
|
3467
|
+
const locale = this.venusApi.getLocale();
|
|
3478
3468
|
const date = new Date(timestamp);
|
|
3479
3469
|
const dateTimeOptions = {
|
|
3480
3470
|
dateStyle: options.dateStyle || "medium",
|
|
@@ -3554,16 +3544,6 @@ var MockTimeApi = class {
|
|
|
3554
3544
|
});
|
|
3555
3545
|
return timeInfo;
|
|
3556
3546
|
}
|
|
3557
|
-
getLocale() {
|
|
3558
|
-
const venusApi = this.venusApi;
|
|
3559
|
-
let locale = "en-US";
|
|
3560
|
-
if (venusApi._mock.user && venusApi._mock.user.locale) {
|
|
3561
|
-
locale = venusApi._mock.user.locale;
|
|
3562
|
-
} else if (venusApi._mock.environment && venusApi._mock.environment.browserInfo.language) {
|
|
3563
|
-
locale = venusApi._mock.environment.browserInfo.language;
|
|
3564
|
-
}
|
|
3565
|
-
return locale;
|
|
3566
|
-
}
|
|
3567
3547
|
};
|
|
3568
3548
|
|
|
3569
3549
|
// src/time/index.ts
|
|
@@ -3583,12 +3563,181 @@ function initializeTime(venusApi, host) {
|
|
|
3583
3563
|
}
|
|
3584
3564
|
|
|
3585
3565
|
// src/version.ts
|
|
3586
|
-
var SDK_VERSION = "3.0.
|
|
3566
|
+
var SDK_VERSION = "3.1.0-beta.0";
|
|
3587
3567
|
|
|
3588
3568
|
// src/shared-assets/consts.ts
|
|
3589
3569
|
var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
|
|
3590
3570
|
var CharacterAssetsCdnPath = "burger-time/Character.stow";
|
|
3591
3571
|
|
|
3572
|
+
// src/shared-assets/embeddedLibrariesManifest.ts
|
|
3573
|
+
var DEFAULT_SHARED_LIB_CDN_BASE = "https://venus-static-01293ak.web.app/libs";
|
|
3574
|
+
var EMBEDDED_LIBRARIES = [
|
|
3575
|
+
{
|
|
3576
|
+
libraryKey: "phaser@3.90.0",
|
|
3577
|
+
assetKey: "library:phaser@3.90.0",
|
|
3578
|
+
packageName: "phaser",
|
|
3579
|
+
version: "3.90.0",
|
|
3580
|
+
globalVar: "Phaser",
|
|
3581
|
+
cdnPath: "phaser/3.90.0/phaser.min.js",
|
|
3582
|
+
moduleSpecifiers: [{ match: "exact", value: "phaser" }],
|
|
3583
|
+
loadStage: 0,
|
|
3584
|
+
enabled: true
|
|
3585
|
+
},
|
|
3586
|
+
{
|
|
3587
|
+
libraryKey: "react@18.3.1",
|
|
3588
|
+
assetKey: "library:react@18.3.1",
|
|
3589
|
+
packageName: "react",
|
|
3590
|
+
version: "18.3.1",
|
|
3591
|
+
globalVar: "React",
|
|
3592
|
+
cdnPath: "react/18.3.1/react.production.min.js",
|
|
3593
|
+
moduleSpecifiers: [
|
|
3594
|
+
{ match: "exact", value: "react", behavior: "namespace" },
|
|
3595
|
+
{ match: "exact", value: "react/jsx-runtime", behavior: "react-jsx-runtime" },
|
|
3596
|
+
{
|
|
3597
|
+
match: "exact",
|
|
3598
|
+
value: "react/jsx-dev-runtime",
|
|
3599
|
+
behavior: "react-jsx-dev-runtime"
|
|
3600
|
+
}
|
|
3601
|
+
],
|
|
3602
|
+
loadStage: 0,
|
|
3603
|
+
// Must load before ReactDOM
|
|
3604
|
+
enabled: true
|
|
3605
|
+
},
|
|
3606
|
+
{
|
|
3607
|
+
libraryKey: "react-dom@18.3.1",
|
|
3608
|
+
assetKey: "library:react-dom@18.3.1",
|
|
3609
|
+
packageName: "react-dom",
|
|
3610
|
+
version: "18.3.1",
|
|
3611
|
+
globalVar: "ReactDOM",
|
|
3612
|
+
cdnPath: "react-dom/18.3.1/react-dom.production.min.js",
|
|
3613
|
+
moduleSpecifiers: [
|
|
3614
|
+
{ match: "exact", value: "react-dom", behavior: "namespace" },
|
|
3615
|
+
{ match: "exact", value: "react-dom/client", behavior: "namespace" }
|
|
3616
|
+
],
|
|
3617
|
+
loadStage: 1,
|
|
3618
|
+
// Depends on React (stage 0)
|
|
3619
|
+
enabled: true
|
|
3620
|
+
},
|
|
3621
|
+
{
|
|
3622
|
+
libraryKey: "three@0.170.0",
|
|
3623
|
+
assetKey: "library:three@0.170.0",
|
|
3624
|
+
packageName: "three",
|
|
3625
|
+
version: "0.170.0",
|
|
3626
|
+
globalVar: "THREE",
|
|
3627
|
+
cdnPath: "three/r170/three.min.js",
|
|
3628
|
+
moduleSpecifiers: [
|
|
3629
|
+
{ match: "exact", value: "three", behavior: "namespace" },
|
|
3630
|
+
{ match: "prefix", value: "three/examples/jsm/", behavior: "namespace" }
|
|
3631
|
+
],
|
|
3632
|
+
loadStage: 0,
|
|
3633
|
+
enabled: true
|
|
3634
|
+
},
|
|
3635
|
+
{
|
|
3636
|
+
libraryKey: "matter-js@0.19.0",
|
|
3637
|
+
assetKey: "library:matter-js@0.19.0",
|
|
3638
|
+
packageName: "matter-js",
|
|
3639
|
+
version: "0.19.0",
|
|
3640
|
+
globalVar: "Matter",
|
|
3641
|
+
cdnPath: "matter-js/0.19.0/matter.min.js",
|
|
3642
|
+
moduleSpecifiers: [{ match: "exact", value: "matter-js" }],
|
|
3643
|
+
loadStage: 0,
|
|
3644
|
+
enabled: true
|
|
3645
|
+
},
|
|
3646
|
+
{
|
|
3647
|
+
libraryKey: "inkjs@2.2.0",
|
|
3648
|
+
assetKey: "library:inkjs@2.2.0",
|
|
3649
|
+
packageName: "inkjs",
|
|
3650
|
+
version: "2.2.0",
|
|
3651
|
+
globalVar: "inkjs",
|
|
3652
|
+
cdnPath: "inkjs/2.2.0/ink.min.js",
|
|
3653
|
+
moduleSpecifiers: [{ match: "exact", value: "inkjs" }],
|
|
3654
|
+
loadStage: 0,
|
|
3655
|
+
enabled: true
|
|
3656
|
+
},
|
|
3657
|
+
{
|
|
3658
|
+
libraryKey: "zustand@5.0.3",
|
|
3659
|
+
assetKey: "library:zustand@5.0.3",
|
|
3660
|
+
packageName: "zustand",
|
|
3661
|
+
version: "5.0.3",
|
|
3662
|
+
globalVar: "zustand",
|
|
3663
|
+
cdnPath: "zustand/5.0.3/zustand.min.js",
|
|
3664
|
+
moduleSpecifiers: [
|
|
3665
|
+
{ match: "exact", value: "zustand" },
|
|
3666
|
+
{ match: "exact", value: "zustand/middleware" }
|
|
3667
|
+
],
|
|
3668
|
+
loadStage: 0,
|
|
3669
|
+
enabled: true
|
|
3670
|
+
},
|
|
3671
|
+
{
|
|
3672
|
+
libraryKey: "ammo.js@2024.11",
|
|
3673
|
+
assetKey: "library:ammo.js@2024.11",
|
|
3674
|
+
packageName: "ammo.js",
|
|
3675
|
+
version: "2024.11",
|
|
3676
|
+
globalVar: "Ammo",
|
|
3677
|
+
cdnPath: "ammo/2024.11/ammo.js",
|
|
3678
|
+
moduleSpecifiers: [
|
|
3679
|
+
{ match: "exact", value: "ammo.js" },
|
|
3680
|
+
{ match: "exact", value: "ammo.js/builds/ammo.wasm.js" }
|
|
3681
|
+
],
|
|
3682
|
+
loadStage: 0,
|
|
3683
|
+
enabled: false
|
|
3684
|
+
// Not ready yet - WASM loading needs additional work
|
|
3685
|
+
}
|
|
3686
|
+
];
|
|
3687
|
+
var EMBEDDED_LIBRARY_BY_KEY = EMBEDDED_LIBRARIES.reduce(
|
|
3688
|
+
(acc, lib) => {
|
|
3689
|
+
acc[lib.libraryKey] = lib;
|
|
3690
|
+
return acc;
|
|
3691
|
+
},
|
|
3692
|
+
{}
|
|
3693
|
+
);
|
|
3694
|
+
var MODULE_TO_LIBRARY_SPECIFIERS = EMBEDDED_LIBRARIES.filter(
|
|
3695
|
+
(lib) => lib.enabled
|
|
3696
|
+
).flatMap(
|
|
3697
|
+
(lib) => lib.moduleSpecifiers.map((specifier) => ({
|
|
3698
|
+
...specifier,
|
|
3699
|
+
libraryKey: lib.libraryKey
|
|
3700
|
+
}))
|
|
3701
|
+
);
|
|
3702
|
+
function getLibraryDefinition(libraryKey) {
|
|
3703
|
+
const definition = EMBEDDED_LIBRARY_BY_KEY[libraryKey];
|
|
3704
|
+
if (!definition) {
|
|
3705
|
+
const availableKeys = Object.keys(EMBEDDED_LIBRARY_BY_KEY).join(", ");
|
|
3706
|
+
throw new Error(
|
|
3707
|
+
`Unsupported embedded library: ${libraryKey}. Available libraries: ${availableKeys}`
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
return definition;
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
// src/shared-assets/base64Utils.ts
|
|
3714
|
+
function base64ToArrayBuffer(base64) {
|
|
3715
|
+
const binaryString = atob(base64);
|
|
3716
|
+
const len = binaryString.length;
|
|
3717
|
+
const bytes = new Uint8Array(len);
|
|
3718
|
+
for (let i = 0; i < len; i++) {
|
|
3719
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
3720
|
+
}
|
|
3721
|
+
return bytes.buffer;
|
|
3722
|
+
}
|
|
3723
|
+
function base64ToUtf8(base64) {
|
|
3724
|
+
if (typeof TextDecoder !== "undefined") {
|
|
3725
|
+
const decoder = new TextDecoder("utf-8");
|
|
3726
|
+
const buffer = base64ToArrayBuffer(base64);
|
|
3727
|
+
return decoder.decode(new Uint8Array(buffer));
|
|
3728
|
+
}
|
|
3729
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.Buffer !== "undefined") {
|
|
3730
|
+
const BufferCtor = globalThis.Buffer;
|
|
3731
|
+
return BufferCtor.from(base64, "base64").toString("utf-8");
|
|
3732
|
+
}
|
|
3733
|
+
const binaryString = atob(base64);
|
|
3734
|
+
let result = "";
|
|
3735
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
3736
|
+
result += String.fromCharCode(binaryString.charCodeAt(i));
|
|
3737
|
+
}
|
|
3738
|
+
return decodeURIComponent(escape(result));
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3592
3741
|
// src/shared-assets/RpcSharedAssetsApi.ts
|
|
3593
3742
|
var RpcSharedAssetsApi = class {
|
|
3594
3743
|
constructor(rpcClient, venusApi) {
|
|
@@ -3627,16 +3776,33 @@ var RpcSharedAssetsApi = class {
|
|
|
3627
3776
|
}
|
|
3628
3777
|
}
|
|
3629
3778
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3779
|
+
async loadLibraryCode(libraryKey) {
|
|
3780
|
+
const definition = getLibraryDefinition(libraryKey);
|
|
3781
|
+
try {
|
|
3782
|
+
const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
|
|
3783
|
+
assetKey: definition.assetKey
|
|
3784
|
+
});
|
|
3785
|
+
return base64ToUtf8(response.base64Data);
|
|
3786
|
+
} catch (err) {
|
|
3787
|
+
console.error(
|
|
3788
|
+
`[Venus Libraries] Failed to load ${libraryKey} from host via RPC:`,
|
|
3789
|
+
err
|
|
3790
|
+
);
|
|
3791
|
+
console.warn(
|
|
3792
|
+
`[Venus Libraries] Falling back to CDN for ${libraryKey}. This may indicate an asset packaging issue.`
|
|
3793
|
+
);
|
|
3794
|
+
try {
|
|
3795
|
+
const cdnUrl = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
|
|
3796
|
+
const response = await this.venusApi.cdn.fetchFromCdn(cdnUrl);
|
|
3797
|
+
return await response.text();
|
|
3798
|
+
} catch (cdnError) {
|
|
3799
|
+
throw new Error(
|
|
3800
|
+
`Failed to load embedded library ${libraryKey}: RPC failed, CDN fallback failed: ${cdnError.message}`
|
|
3801
|
+
);
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3637
3804
|
}
|
|
3638
|
-
|
|
3639
|
-
}
|
|
3805
|
+
};
|
|
3640
3806
|
|
|
3641
3807
|
// src/shared-assets/MockSharedAssetsApi.ts
|
|
3642
3808
|
var MockSharedAssetsApi = class {
|
|
@@ -3652,49 +3818,114 @@ var MockSharedAssetsApi = class {
|
|
|
3652
3818
|
const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
|
|
3653
3819
|
return await blob.arrayBuffer();
|
|
3654
3820
|
}
|
|
3821
|
+
async loadLibraryCode(libraryKey) {
|
|
3822
|
+
const definition = getLibraryDefinition(libraryKey);
|
|
3823
|
+
const url = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
|
|
3824
|
+
const response = await this.venusApi.cdn.fetchFromCdn(url);
|
|
3825
|
+
return await response.text();
|
|
3826
|
+
}
|
|
3655
3827
|
};
|
|
3656
3828
|
|
|
3829
|
+
// src/leaderboard/utils.ts
|
|
3830
|
+
var HASH_ALGORITHM_WEB_CRYPTO = "SHA-256";
|
|
3831
|
+
var HASH_ALGORITHM_NODE = "sha256";
|
|
3832
|
+
async function computeScoreHash(score, duration, token, sealingNonce, sealingSecret) {
|
|
3833
|
+
const payload = `score:${score}|duration:${duration}|token:${token}`;
|
|
3834
|
+
const fullPayload = `${payload}|nonce:${sealingNonce}`;
|
|
3835
|
+
const encoder = new TextEncoder();
|
|
3836
|
+
const keyData = encoder.encode(sealingSecret);
|
|
3837
|
+
const messageData = encoder.encode(fullPayload);
|
|
3838
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
3839
|
+
"raw",
|
|
3840
|
+
keyData,
|
|
3841
|
+
{ name: "HMAC", hash: HASH_ALGORITHM_WEB_CRYPTO },
|
|
3842
|
+
false,
|
|
3843
|
+
["sign"]
|
|
3844
|
+
);
|
|
3845
|
+
const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageData);
|
|
3846
|
+
return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3657
3849
|
// src/leaderboard/RpcLeaderboardApi.ts
|
|
3658
3850
|
var RpcLeaderboardApi = class {
|
|
3659
3851
|
constructor(rpcClient) {
|
|
3660
3852
|
__publicField(this, "rpcClient");
|
|
3853
|
+
/** Cache of score tokens for automatic hash computation */
|
|
3854
|
+
__publicField(this, "tokenCache", /* @__PURE__ */ new Map());
|
|
3661
3855
|
this.rpcClient = rpcClient;
|
|
3662
3856
|
}
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3857
|
+
/**
|
|
3858
|
+
* Create a score token for submitting a score.
|
|
3859
|
+
* Token is cached for automatic hash computation if score sealing is enabled.
|
|
3860
|
+
*
|
|
3861
|
+
* @param mode - Optional game mode
|
|
3862
|
+
* @returns Score token with sealing data if enabled
|
|
3863
|
+
*/
|
|
3864
|
+
async createScoreToken(mode) {
|
|
3865
|
+
const token = await this.rpcClient.call(
|
|
3866
|
+
"H5_LEADERBOARD_CREATE_SCORE_TOKEN" /* H5_LEADERBOARD_CREATE_SCORE_TOKEN */,
|
|
3666
3867
|
mode ? { mode } : {}
|
|
3667
3868
|
);
|
|
3869
|
+
this.tokenCache.set(token.token, token);
|
|
3870
|
+
return token;
|
|
3668
3871
|
}
|
|
3669
|
-
|
|
3872
|
+
/**
|
|
3873
|
+
* Submit a score to the leaderboard.
|
|
3874
|
+
* Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
|
|
3875
|
+
*
|
|
3876
|
+
* @param params - Score submission parameters
|
|
3877
|
+
* @returns Submission result with acceptance status and rank
|
|
3878
|
+
* @throws Error if token not found in cache
|
|
3879
|
+
*/
|
|
3880
|
+
async submitScore(params) {
|
|
3881
|
+
let hash;
|
|
3882
|
+
if (params.token) {
|
|
3883
|
+
const cachedToken = this.tokenCache.get(params.token);
|
|
3884
|
+
if (!cachedToken) {
|
|
3885
|
+
throw new Error(
|
|
3886
|
+
"Invalid token: not found in cache. Did you call createScoreToken() first?"
|
|
3887
|
+
);
|
|
3888
|
+
}
|
|
3889
|
+
if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
|
|
3890
|
+
hash = await computeScoreHash(
|
|
3891
|
+
params.score,
|
|
3892
|
+
params.duration,
|
|
3893
|
+
params.token,
|
|
3894
|
+
cachedToken.sealingNonce,
|
|
3895
|
+
cachedToken.sealingSecret
|
|
3896
|
+
);
|
|
3897
|
+
}
|
|
3898
|
+
this.tokenCache.delete(params.token);
|
|
3899
|
+
}
|
|
3670
3900
|
return this.rpcClient.call(
|
|
3671
3901
|
"H5_LEADERBOARD_SUBMIT_SCORE" /* H5_LEADERBOARD_SUBMIT_SCORE */,
|
|
3672
3902
|
{
|
|
3673
|
-
|
|
3674
|
-
score,
|
|
3675
|
-
|
|
3676
|
-
mode:
|
|
3677
|
-
telemetry:
|
|
3678
|
-
metadata:
|
|
3679
|
-
hash
|
|
3903
|
+
token: params.token,
|
|
3904
|
+
score: params.score,
|
|
3905
|
+
duration: params.duration,
|
|
3906
|
+
mode: params.mode,
|
|
3907
|
+
telemetry: params.telemetry,
|
|
3908
|
+
metadata: params.metadata,
|
|
3909
|
+
hash
|
|
3910
|
+
// undefined if no sealing, computed if sealing enabled
|
|
3680
3911
|
}
|
|
3681
3912
|
);
|
|
3682
3913
|
}
|
|
3683
|
-
|
|
3914
|
+
getPagedScores(options) {
|
|
3684
3915
|
return this.rpcClient.call(
|
|
3685
|
-
"
|
|
3916
|
+
"H5_LEADERBOARD_GET_PAGED_SCORES" /* H5_LEADERBOARD_GET_PAGED_SCORES */,
|
|
3686
3917
|
options ?? {}
|
|
3687
3918
|
);
|
|
3688
3919
|
}
|
|
3689
|
-
|
|
3920
|
+
getMyRank(options) {
|
|
3690
3921
|
return this.rpcClient.call(
|
|
3691
|
-
"
|
|
3922
|
+
"H5_LEADERBOARD_GET_MY_RANK" /* H5_LEADERBOARD_GET_MY_RANK */,
|
|
3692
3923
|
options ?? {}
|
|
3693
3924
|
);
|
|
3694
3925
|
}
|
|
3695
|
-
|
|
3926
|
+
getPodiumScores(options) {
|
|
3696
3927
|
return this.rpcClient.call(
|
|
3697
|
-
"
|
|
3928
|
+
"H5_LEADERBOARD_GET_PODIUM_SCORES" /* H5_LEADERBOARD_GET_PODIUM_SCORES */,
|
|
3698
3929
|
options ?? {}
|
|
3699
3930
|
);
|
|
3700
3931
|
}
|
|
@@ -3703,17 +3934,31 @@ var RpcLeaderboardApi = class {
|
|
|
3703
3934
|
// src/leaderboard/MockLeaderboardApi.ts
|
|
3704
3935
|
var MockLeaderboardApi = class {
|
|
3705
3936
|
constructor(options) {
|
|
3706
|
-
__publicField(this, "
|
|
3937
|
+
__publicField(this, "tokens", /* @__PURE__ */ new Map());
|
|
3938
|
+
/** Cache of score tokens for automatic hash computation */
|
|
3939
|
+
__publicField(this, "tokenCache", /* @__PURE__ */ new Map());
|
|
3707
3940
|
__publicField(this, "entriesByMode", /* @__PURE__ */ new Map());
|
|
3708
|
-
__publicField(this, "
|
|
3709
|
-
__publicField(this, "
|
|
3710
|
-
|
|
3711
|
-
|
|
3941
|
+
__publicField(this, "tokenCounter", 0);
|
|
3942
|
+
__publicField(this, "enableScoreSealing", false);
|
|
3943
|
+
__publicField(this, "scoreSealingSecret", "mock-leaderboard-secret-key");
|
|
3944
|
+
if (options?.enableScoreSealing) {
|
|
3945
|
+
this.enableScoreSealing = true;
|
|
3946
|
+
}
|
|
3947
|
+
if (options?.scoreSealingSecret) {
|
|
3948
|
+
this.scoreSealingSecret = options.scoreSealingSecret;
|
|
3712
3949
|
}
|
|
3713
3950
|
}
|
|
3951
|
+
/**
|
|
3952
|
+
* Configure mock leaderboard settings
|
|
3953
|
+
*
|
|
3954
|
+
* @param options - Configuration options
|
|
3955
|
+
*/
|
|
3714
3956
|
configure(options) {
|
|
3715
|
-
if (typeof options.
|
|
3716
|
-
this.
|
|
3957
|
+
if (typeof options.enableScoreSealing === "boolean") {
|
|
3958
|
+
this.enableScoreSealing = options.enableScoreSealing;
|
|
3959
|
+
}
|
|
3960
|
+
if (options.scoreSealingSecret) {
|
|
3961
|
+
this.scoreSealingSecret = options.scoreSealingSecret;
|
|
3717
3962
|
}
|
|
3718
3963
|
}
|
|
3719
3964
|
generateNonce() {
|
|
@@ -3730,83 +3975,149 @@ var MockLeaderboardApi = class {
|
|
|
3730
3975
|
}
|
|
3731
3976
|
return this.entriesByMode.get(key);
|
|
3732
3977
|
}
|
|
3733
|
-
|
|
3734
|
-
|
|
3978
|
+
/**
|
|
3979
|
+
* Create a mock score token for testing.
|
|
3980
|
+
* Token is cached for automatic hash computation if score sealing is enabled.
|
|
3981
|
+
*
|
|
3982
|
+
* @param mode - Optional game mode
|
|
3983
|
+
* @returns Score token with sealing data if enabled
|
|
3984
|
+
*/
|
|
3985
|
+
async createScoreToken(mode) {
|
|
3986
|
+
const token = `mock_token_${++this.tokenCounter}`;
|
|
3735
3987
|
const startTime = Date.now();
|
|
3736
3988
|
const expiresAt = startTime + 36e5;
|
|
3737
3989
|
const resolvedMode = mode || "default";
|
|
3738
|
-
const
|
|
3739
|
-
this.
|
|
3740
|
-
|
|
3990
|
+
const sealingNonce = this.enableScoreSealing ? this.generateNonce() : null;
|
|
3991
|
+
const sealingSecret = this.enableScoreSealing ? this.scoreSealingSecret : null;
|
|
3992
|
+
this.tokens.set(token, {
|
|
3993
|
+
id: token,
|
|
3741
3994
|
expiresAt,
|
|
3742
3995
|
mode: resolvedMode,
|
|
3743
|
-
|
|
3996
|
+
sealingNonce,
|
|
3744
3997
|
used: false
|
|
3745
3998
|
});
|
|
3746
|
-
|
|
3747
|
-
|
|
3999
|
+
const result = {
|
|
4000
|
+
token,
|
|
3748
4001
|
startTime,
|
|
3749
4002
|
expiresAt,
|
|
3750
|
-
|
|
4003
|
+
sealingNonce,
|
|
4004
|
+
sealingSecret,
|
|
3751
4005
|
mode: resolvedMode
|
|
3752
4006
|
};
|
|
4007
|
+
this.tokenCache.set(token, result);
|
|
4008
|
+
return result;
|
|
3753
4009
|
}
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
4010
|
+
/**
|
|
4011
|
+
* Submit a mock score to the leaderboard.
|
|
4012
|
+
* Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
|
|
4013
|
+
*
|
|
4014
|
+
* @param params - Score submission parameters
|
|
4015
|
+
* @returns Submission result with acceptance status and rank
|
|
4016
|
+
* @throws Error if token not found in cache or validation fails
|
|
4017
|
+
*/
|
|
4018
|
+
async submitScore(params) {
|
|
4019
|
+
let hash;
|
|
4020
|
+
if (params.token) {
|
|
4021
|
+
const cachedToken = this.tokenCache.get(params.token);
|
|
4022
|
+
if (!cachedToken) {
|
|
4023
|
+
throw new Error(
|
|
4024
|
+
"Invalid token: not found in cache. Did you call createScoreToken() first?"
|
|
4025
|
+
);
|
|
4026
|
+
}
|
|
4027
|
+
if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
|
|
4028
|
+
hash = await computeScoreHash(
|
|
4029
|
+
params.score,
|
|
4030
|
+
params.duration,
|
|
4031
|
+
params.token,
|
|
4032
|
+
cachedToken.sealingNonce,
|
|
4033
|
+
cachedToken.sealingSecret
|
|
4034
|
+
);
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
if (!params.token) {
|
|
4038
|
+
const mode = params.mode || "default";
|
|
4039
|
+
const submittedAt2 = Date.now();
|
|
4040
|
+
const entry2 = {
|
|
4041
|
+
profileId: `mock_profile`,
|
|
4042
|
+
username: "Mock Player",
|
|
4043
|
+
avatarUrl: null,
|
|
4044
|
+
score: params.score,
|
|
4045
|
+
duration: params.duration,
|
|
4046
|
+
submittedAt: submittedAt2,
|
|
4047
|
+
token: "simple-mode",
|
|
4048
|
+
rank: null,
|
|
4049
|
+
zScore: null,
|
|
4050
|
+
isAnomaly: false,
|
|
4051
|
+
trustScore: 50,
|
|
4052
|
+
metadata: params.metadata ?? null,
|
|
4053
|
+
isSeed: false
|
|
4054
|
+
};
|
|
4055
|
+
const modeEntries2 = this.getEntriesForMode(mode);
|
|
4056
|
+
modeEntries2.push(entry2);
|
|
4057
|
+
modeEntries2.sort((a, b) => {
|
|
4058
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
4059
|
+
return a.submittedAt - b.submittedAt;
|
|
4060
|
+
});
|
|
4061
|
+
modeEntries2.forEach((e, index) => {
|
|
4062
|
+
modeEntries2[index] = { ...e, rank: index + 1 };
|
|
4063
|
+
});
|
|
4064
|
+
const inserted2 = modeEntries2.find((e) => e.submittedAt === submittedAt2);
|
|
4065
|
+
return {
|
|
4066
|
+
accepted: true,
|
|
4067
|
+
rank: inserted2?.rank ?? null
|
|
4068
|
+
};
|
|
4069
|
+
}
|
|
4070
|
+
const scoreToken = this.tokens.get(params.token);
|
|
4071
|
+
if (!scoreToken) {
|
|
4072
|
+
throw new Error("Invalid score token");
|
|
3758
4073
|
}
|
|
3759
|
-
if (
|
|
3760
|
-
throw new Error("Invalid or expired
|
|
4074
|
+
if (scoreToken.expiresAt < Date.now()) {
|
|
4075
|
+
throw new Error("Invalid or expired score token");
|
|
3761
4076
|
}
|
|
3762
|
-
if (
|
|
3763
|
-
throw new Error("
|
|
4077
|
+
if (scoreToken.used) {
|
|
4078
|
+
throw new Error("Score token already used");
|
|
3764
4079
|
}
|
|
3765
|
-
if (
|
|
3766
|
-
throw new Error("Submission mode does not match
|
|
4080
|
+
if (params.mode && params.mode !== scoreToken.mode) {
|
|
4081
|
+
throw new Error("Submission mode does not match token mode");
|
|
3767
4082
|
}
|
|
3768
|
-
if (
|
|
3769
|
-
throw new Error("Score hash
|
|
4083
|
+
if (scoreToken.sealingNonce && !hash) {
|
|
4084
|
+
throw new Error("Score hash required when score sealing is enabled");
|
|
3770
4085
|
}
|
|
3771
4086
|
const submittedAt = Date.now();
|
|
3772
4087
|
const entry = {
|
|
3773
4088
|
profileId: `mock_profile`,
|
|
3774
4089
|
username: "Mock Player",
|
|
3775
4090
|
avatarUrl: null,
|
|
3776
|
-
score,
|
|
3777
|
-
|
|
4091
|
+
score: params.score,
|
|
4092
|
+
duration: params.duration,
|
|
3778
4093
|
submittedAt,
|
|
3779
|
-
|
|
4094
|
+
token: params.token,
|
|
3780
4095
|
rank: null,
|
|
3781
4096
|
zScore: null,
|
|
3782
4097
|
isAnomaly: false,
|
|
3783
4098
|
trustScore: 50,
|
|
3784
|
-
metadata:
|
|
4099
|
+
metadata: params.metadata ?? null,
|
|
3785
4100
|
isSeed: false
|
|
3786
4101
|
};
|
|
3787
|
-
const modeEntries = this.getEntriesForMode(
|
|
4102
|
+
const modeEntries = this.getEntriesForMode(scoreToken.mode);
|
|
3788
4103
|
modeEntries.push(entry);
|
|
3789
4104
|
modeEntries.sort((a, b) => {
|
|
3790
|
-
if (b.score !== a.score)
|
|
3791
|
-
return b.score - a.score;
|
|
3792
|
-
}
|
|
4105
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
3793
4106
|
return a.submittedAt - b.submittedAt;
|
|
3794
4107
|
});
|
|
3795
4108
|
modeEntries.forEach((e, index) => {
|
|
3796
|
-
modeEntries[index] = {
|
|
3797
|
-
...e,
|
|
3798
|
-
rank: index + 1
|
|
3799
|
-
};
|
|
4109
|
+
modeEntries[index] = { ...e, rank: index + 1 };
|
|
3800
4110
|
});
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
4111
|
+
scoreToken.used = true;
|
|
4112
|
+
scoreToken.sealingNonce = null;
|
|
4113
|
+
this.tokenCache.delete(params.token);
|
|
4114
|
+
const inserted = modeEntries.find((e) => e.token === params.token && e.submittedAt === submittedAt);
|
|
3804
4115
|
return {
|
|
3805
4116
|
accepted: true,
|
|
3806
4117
|
rank: inserted?.rank ?? null
|
|
3807
4118
|
};
|
|
3808
4119
|
}
|
|
3809
|
-
async
|
|
4120
|
+
async getPagedScores(options) {
|
|
3810
4121
|
const limit = options?.limit ?? 10;
|
|
3811
4122
|
const mode = options?.mode ?? "default";
|
|
3812
4123
|
const modeEntries = [...this.getEntriesForMode(mode)];
|
|
@@ -3822,7 +4133,7 @@ var MockLeaderboardApi = class {
|
|
|
3822
4133
|
periodInstance: options?.period ?? "alltime"
|
|
3823
4134
|
};
|
|
3824
4135
|
}
|
|
3825
|
-
async
|
|
4136
|
+
async getMyRank(_options) {
|
|
3826
4137
|
const mode = _options?.mode ?? "default";
|
|
3827
4138
|
const modeEntries = this.getEntriesForMode(mode);
|
|
3828
4139
|
const playerEntry = modeEntries[0] ?? null;
|
|
@@ -3835,7 +4146,7 @@ var MockLeaderboardApi = class {
|
|
|
3835
4146
|
periodInstance: _options?.period ?? "alltime"
|
|
3836
4147
|
};
|
|
3837
4148
|
}
|
|
3838
|
-
async
|
|
4149
|
+
async getPodiumScores(options) {
|
|
3839
4150
|
const mode = options?.mode ?? "default";
|
|
3840
4151
|
const modeEntries = [...this.getEntriesForMode(mode)];
|
|
3841
4152
|
const topCount = Math.max(1, Math.min(options?.topCount ?? 3, 10));
|
|
@@ -5222,7 +5533,7 @@ var RemoteHost = class {
|
|
|
5222
5533
|
this.popups = new RpcPopupsApi(rpcClient);
|
|
5223
5534
|
this.profile = new HostProfileApi();
|
|
5224
5535
|
this.cdn = new HostCdnApi(getCdnBaseUrl());
|
|
5225
|
-
this.time = new HostTimeApi(rpcClient);
|
|
5536
|
+
this.time = new HostTimeApi(rpcClient, venusApi);
|
|
5226
5537
|
this.post = new RpcPostApi(rpcClient);
|
|
5227
5538
|
this.ai = new RpcAiApi(rpcClient);
|
|
5228
5539
|
this.haptics = new RpcHapticsApi(rpcClient);
|
|
@@ -5313,10 +5624,356 @@ function initializeSocial(venusApi, host) {
|
|
|
5313
5624
|
};
|
|
5314
5625
|
}
|
|
5315
5626
|
|
|
5627
|
+
// src/webview/webviewLibraryShimSource.ts
|
|
5628
|
+
var WEBVIEW_LIBRARY_SHIM_SOURCE = `
|
|
5629
|
+
(function () {
|
|
5630
|
+
if (typeof window === 'undefined') {
|
|
5631
|
+
return;
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5634
|
+
if (window.__venusLibraryShim && window.__venusLibraryShim.__initialized) {
|
|
5635
|
+
return;
|
|
5636
|
+
}
|
|
5637
|
+
|
|
5638
|
+
var RESPONSE_TYPE = 'H5_RESPONSE';
|
|
5639
|
+
var REQUEST_TYPE = 'H5_LOAD_EMBEDDED_ASSET';
|
|
5640
|
+
var REQUEST_TIMEOUT_MS = 12000;
|
|
5641
|
+
var pendingRequests = new Map();
|
|
5642
|
+
|
|
5643
|
+
function ensureConfig() {
|
|
5644
|
+
if (!window.__venusLibrariesConfig) {
|
|
5645
|
+
window.__venusLibrariesConfig = {
|
|
5646
|
+
enabled: false,
|
|
5647
|
+
required: [],
|
|
5648
|
+
manifest: {},
|
|
5649
|
+
cdnBase: ''
|
|
5650
|
+
};
|
|
5651
|
+
}
|
|
5652
|
+
if (!window.__venusLibrariesConfig.manifest) {
|
|
5653
|
+
window.__venusLibrariesConfig.manifest = {};
|
|
5654
|
+
}
|
|
5655
|
+
if (!Array.isArray(window.__venusLibrariesConfig.required)) {
|
|
5656
|
+
window.__venusLibrariesConfig.required = [];
|
|
5657
|
+
}
|
|
5658
|
+
return window.__venusLibrariesConfig;
|
|
5659
|
+
}
|
|
5660
|
+
|
|
5661
|
+
function ensureExportsRegistry() {
|
|
5662
|
+
if (!window.__venusLibraryExports) {
|
|
5663
|
+
window.__venusLibraryExports = {};
|
|
5664
|
+
}
|
|
5665
|
+
return window.__venusLibraryExports;
|
|
5666
|
+
}
|
|
5667
|
+
|
|
5668
|
+
function hasHostBridge() {
|
|
5669
|
+
return !!(window.ReactNativeWebView && typeof window.ReactNativeWebView.postMessage === 'function');
|
|
5670
|
+
}
|
|
5671
|
+
|
|
5672
|
+
function registerResponseListeners() {
|
|
5673
|
+
if (window.__venusLibraryShim && window.__venusLibraryShim.__listenerRegistered) {
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5677
|
+
function handleMessage(event) {
|
|
5678
|
+
var payload = parsePayload(event && event.data);
|
|
5679
|
+
if (!payload || payload.type !== RESPONSE_TYPE || !payload.data) {
|
|
5680
|
+
return;
|
|
5681
|
+
}
|
|
5682
|
+
var requestId = payload.data.requestId;
|
|
5683
|
+
if (!requestId || !pendingRequests.has(requestId)) {
|
|
5684
|
+
return;
|
|
5685
|
+
}
|
|
5686
|
+
var pending = pendingRequests.get(requestId);
|
|
5687
|
+
pendingRequests.delete(requestId);
|
|
5688
|
+
clearTimeout(pending.timeout);
|
|
5689
|
+
|
|
5690
|
+
if (payload.data.success === false) {
|
|
5691
|
+
pending.reject(new Error(payload.data.error || 'Embedded library load failed'));
|
|
5692
|
+
return;
|
|
5693
|
+
}
|
|
5694
|
+
|
|
5695
|
+
var value = payload.data.value || payload.data;
|
|
5696
|
+
if (!value || !value.base64Data) {
|
|
5697
|
+
pending.reject(new Error('Embedded library response was missing base64Data'));
|
|
5698
|
+
return;
|
|
5699
|
+
}
|
|
5700
|
+
|
|
5701
|
+
pending.resolve(value.base64Data);
|
|
5702
|
+
}
|
|
5703
|
+
|
|
5704
|
+
if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
|
|
5705
|
+
document.addEventListener('message', handleMessage, false);
|
|
5706
|
+
}
|
|
5707
|
+
if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
|
|
5708
|
+
window.addEventListener('message', handleMessage, false);
|
|
5709
|
+
}
|
|
5710
|
+
|
|
5711
|
+
if (!window.__venusLibraryShim) {
|
|
5712
|
+
window.__venusLibraryShim = {};
|
|
5713
|
+
}
|
|
5714
|
+
window.__venusLibraryShim.__listenerRegistered = true;
|
|
5715
|
+
}
|
|
5716
|
+
|
|
5717
|
+
function parsePayload(raw) {
|
|
5718
|
+
if (!raw || typeof raw !== 'string') {
|
|
5719
|
+
return null;
|
|
5720
|
+
}
|
|
5721
|
+
try {
|
|
5722
|
+
return JSON.parse(raw);
|
|
5723
|
+
} catch (error) {
|
|
5724
|
+
return null;
|
|
5725
|
+
}
|
|
5726
|
+
}
|
|
5727
|
+
|
|
5728
|
+
function createRequestId(libraryKey) {
|
|
5729
|
+
var sanitized = '';
|
|
5730
|
+
for (var i = 0; i < libraryKey.length; i++) {
|
|
5731
|
+
var c = libraryKey.charAt(i);
|
|
5732
|
+
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '-' || c === '_') {
|
|
5733
|
+
sanitized += c;
|
|
5734
|
+
} else {
|
|
5735
|
+
sanitized += '_';
|
|
5736
|
+
}
|
|
5737
|
+
}
|
|
5738
|
+
return 'embedded-lib-' + sanitized + '-' + Date.now() + '-' + Math.random().toString(36).slice(2);
|
|
5739
|
+
}
|
|
5740
|
+
|
|
5741
|
+
function postHostRequest(assetKey, requestId) {
|
|
5742
|
+
if (!hasHostBridge()) {
|
|
5743
|
+
throw new Error('Host bridge is unavailable');
|
|
5744
|
+
}
|
|
5745
|
+
var bridge = window.ReactNativeWebView;
|
|
5746
|
+
var message = {
|
|
5747
|
+
type: REQUEST_TYPE,
|
|
5748
|
+
direction: 'H5_TO_APP',
|
|
5749
|
+
data: {
|
|
5750
|
+
requestId: requestId,
|
|
5751
|
+
assetKey: assetKey
|
|
5752
|
+
},
|
|
5753
|
+
instanceId: (window._venusInitState && window._venusInitState.poolId) || 'unknown',
|
|
5754
|
+
timestamp: Date.now()
|
|
5755
|
+
};
|
|
5756
|
+
bridge.postMessage(JSON.stringify(message));
|
|
5757
|
+
}
|
|
5758
|
+
|
|
5759
|
+
function loadLibraryViaHost(assetKey, libraryKey) {
|
|
5760
|
+
return new Promise(function (resolve, reject) {
|
|
5761
|
+
var requestId = createRequestId(libraryKey);
|
|
5762
|
+
var timeout = setTimeout(function () {
|
|
5763
|
+
pendingRequests.delete(requestId);
|
|
5764
|
+
reject(new Error('Timed out loading embedded library: ' + libraryKey));
|
|
5765
|
+
}, REQUEST_TIMEOUT_MS);
|
|
5766
|
+
|
|
5767
|
+
pendingRequests.set(requestId, { resolve: resolve, reject: reject, timeout: timeout });
|
|
5768
|
+
|
|
5769
|
+
try {
|
|
5770
|
+
postHostRequest(assetKey, requestId);
|
|
5771
|
+
} catch (error) {
|
|
5772
|
+
pendingRequests.delete(requestId);
|
|
5773
|
+
clearTimeout(timeout);
|
|
5774
|
+
reject(error);
|
|
5775
|
+
}
|
|
5776
|
+
});
|
|
5777
|
+
}
|
|
5778
|
+
|
|
5779
|
+
function buildCdnUrl(config, entry) {
|
|
5780
|
+
var base = config.cdnBase || '';
|
|
5781
|
+
if (!base.endsWith('/')) {
|
|
5782
|
+
base += '/';
|
|
5783
|
+
}
|
|
5784
|
+
var path = entry.cdnPath;
|
|
5785
|
+
if (path.charAt(0) === '/') {
|
|
5786
|
+
path = path.substring(1);
|
|
5787
|
+
}
|
|
5788
|
+
return base + path;
|
|
5789
|
+
}
|
|
5790
|
+
|
|
5791
|
+
async function loadLibraryViaCdn(config, entry, libraryKey) {
|
|
5792
|
+
if (!config.cdnBase) {
|
|
5793
|
+
throw new Error('CDN base URL is not configured');
|
|
5794
|
+
}
|
|
5795
|
+
var url = buildCdnUrl(config, entry);
|
|
5796
|
+
var response = await fetch(url, { credentials: 'omit' });
|
|
5797
|
+
if (!response.ok) {
|
|
5798
|
+
throw new Error('Failed to fetch embedded library from CDN: ' + libraryKey);
|
|
5799
|
+
}
|
|
5800
|
+
return await response.text();
|
|
5801
|
+
}
|
|
5802
|
+
|
|
5803
|
+
function decodeBase64ToUtf8(base64) {
|
|
5804
|
+
if (typeof base64 !== 'string') {
|
|
5805
|
+
throw new Error('Invalid base64 payload');
|
|
5806
|
+
}
|
|
5807
|
+
|
|
5808
|
+
if (typeof atob === 'function') {
|
|
5809
|
+
var binary = atob(base64);
|
|
5810
|
+
if (typeof TextDecoder !== 'undefined') {
|
|
5811
|
+
var len = binary.length;
|
|
5812
|
+
var bytes = new Uint8Array(len);
|
|
5813
|
+
for (var i = 0; i < len; i++) {
|
|
5814
|
+
bytes[i] = binary.charCodeAt(i);
|
|
5815
|
+
}
|
|
5816
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
5817
|
+
}
|
|
5818
|
+
return decodeURIComponent(escape(binary));
|
|
5819
|
+
}
|
|
5820
|
+
|
|
5821
|
+
var bufferCtor = (typeof globalThis !== 'undefined' && globalThis.Buffer) || (typeof window !== 'undefined' && window.Buffer);
|
|
5822
|
+
if (bufferCtor) {
|
|
5823
|
+
return bufferCtor.from(base64, 'base64').toString('utf-8');
|
|
5824
|
+
}
|
|
5825
|
+
|
|
5826
|
+
throw new Error('No base64 decoder available');
|
|
5827
|
+
}
|
|
5828
|
+
|
|
5829
|
+
function evaluateLibrarySource(libraryKey, globalVar, source) {
|
|
5830
|
+
var registry = ensureExportsRegistry();
|
|
5831
|
+
if (!source) {
|
|
5832
|
+
throw new Error('Embedded library source was empty for ' + libraryKey);
|
|
5833
|
+
}
|
|
5834
|
+
|
|
5835
|
+
var previousValue = window[globalVar];
|
|
5836
|
+
try {
|
|
5837
|
+
var executor = new Function(source + '\\n//# sourceURL=venus-library-' + libraryKey + '.js');
|
|
5838
|
+
executor.call(window);
|
|
5839
|
+
} catch (error) {
|
|
5840
|
+
throw new Error('Failed to evaluate embedded library ' + libraryKey + ': ' + (error && error.message ? error.message : error));
|
|
5841
|
+
}
|
|
5842
|
+
|
|
5843
|
+
var exported = window[globalVar] || previousValue;
|
|
5844
|
+
if (!exported) {
|
|
5845
|
+
throw new Error('Embedded library ' + libraryKey + ' did not register ' + globalVar);
|
|
5846
|
+
}
|
|
5847
|
+
|
|
5848
|
+
registry[libraryKey] = exported;
|
|
5849
|
+
return exported;
|
|
5850
|
+
}
|
|
5851
|
+
|
|
5852
|
+
async function ensureLibraryLoaded(config, libraryKey) {
|
|
5853
|
+
var registry = ensureExportsRegistry();
|
|
5854
|
+
if (registry[libraryKey]) {
|
|
5855
|
+
return registry[libraryKey];
|
|
5856
|
+
}
|
|
5857
|
+
|
|
5858
|
+
var entry = config.manifest && config.manifest[libraryKey];
|
|
5859
|
+
if (!entry) {
|
|
5860
|
+
throw new Error('No manifest entry for embedded library ' + libraryKey);
|
|
5861
|
+
}
|
|
5862
|
+
|
|
5863
|
+
var source = null;
|
|
5864
|
+
if (config.useHost !== false && hasHostBridge()) {
|
|
5865
|
+
try {
|
|
5866
|
+
var base64 = await loadLibraryViaHost(entry.assetKey, libraryKey);
|
|
5867
|
+
source = decodeBase64ToUtf8(base64);
|
|
5868
|
+
} catch (error) {
|
|
5869
|
+
// Log the RPC error loudly before fallback
|
|
5870
|
+
console.error('[Venus Libraries] Failed to load ' + libraryKey + ' from host via RPC:', error);
|
|
5871
|
+
console.warn('[Venus Libraries] Falling back to CDN for ' + libraryKey + '. This may indicate an asset packaging issue.');
|
|
5872
|
+
}
|
|
5873
|
+
}
|
|
5874
|
+
|
|
5875
|
+
if (!source) {
|
|
5876
|
+
source = await loadLibraryViaCdn(config, entry, libraryKey);
|
|
5877
|
+
}
|
|
5878
|
+
|
|
5879
|
+
return evaluateLibrarySource(libraryKey, entry.globalVar, source);
|
|
5880
|
+
}
|
|
5881
|
+
|
|
5882
|
+
async function bootstrap() {
|
|
5883
|
+
try {
|
|
5884
|
+
registerResponseListeners();
|
|
5885
|
+
getBootstrapPromise();
|
|
5886
|
+
|
|
5887
|
+
var config = ensureConfig();
|
|
5888
|
+
|
|
5889
|
+
if (!config.enabled) {
|
|
5890
|
+
if (bootstrapResolve) bootstrapResolve();
|
|
5891
|
+
return;
|
|
5892
|
+
}
|
|
5893
|
+
|
|
5894
|
+
if (!Array.isArray(config.required) || config.required.length === 0) {
|
|
5895
|
+
if (bootstrapResolve) bootstrapResolve();
|
|
5896
|
+
return;
|
|
5897
|
+
}
|
|
5898
|
+
|
|
5899
|
+
// Group libraries by load stage for parallel loading within stages
|
|
5900
|
+
var librariesByStage = {};
|
|
5901
|
+
for (var i = 0; i < config.required.length; i++) {
|
|
5902
|
+
var libraryKey = config.required[i];
|
|
5903
|
+
var entry = config.manifest[libraryKey];
|
|
5904
|
+
var stage = entry.loadStage || 0;
|
|
5905
|
+
if (!librariesByStage[stage]) librariesByStage[stage] = [];
|
|
5906
|
+
librariesByStage[stage].push(libraryKey);
|
|
5907
|
+
}
|
|
5908
|
+
|
|
5909
|
+
// Load stages sequentially, libraries within each stage in parallel
|
|
5910
|
+
var stages = Object.keys(librariesByStage).sort(function(a, b) {
|
|
5911
|
+
return parseInt(a, 10) - parseInt(b, 10);
|
|
5912
|
+
});
|
|
5913
|
+
|
|
5914
|
+
for (var s = 0; s < stages.length; s++) {
|
|
5915
|
+
var stage = stages[s];
|
|
5916
|
+
var libs = librariesByStage[stage];
|
|
5917
|
+
|
|
5918
|
+
// Load all libraries in this stage in parallel
|
|
5919
|
+
var stagePromises = libs.map(function(libraryKey) {
|
|
5920
|
+
return ensureLibraryLoaded(config, libraryKey).catch(function(error) {
|
|
5921
|
+
console.error('[Venus Libraries] Failed to load library ' + libraryKey, error);
|
|
5922
|
+
throw error;
|
|
5923
|
+
});
|
|
5924
|
+
});
|
|
5925
|
+
|
|
5926
|
+
await Promise.all(stagePromises);
|
|
5927
|
+
}
|
|
5928
|
+
|
|
5929
|
+
if (bootstrapResolve) bootstrapResolve();
|
|
5930
|
+
} catch (error) {
|
|
5931
|
+
console.error('[Venus Libraries] Bootstrap error', error);
|
|
5932
|
+
if (bootstrapReject) bootstrapReject(error);
|
|
5933
|
+
throw error;
|
|
5934
|
+
}
|
|
5935
|
+
}
|
|
5936
|
+
|
|
5937
|
+
// Create a promise that resolves when bootstrap completes
|
|
5938
|
+
var bootstrapPromise = null;
|
|
5939
|
+
var bootstrapResolve = null;
|
|
5940
|
+
var bootstrapReject = null;
|
|
5941
|
+
|
|
5942
|
+
function getBootstrapPromise() {
|
|
5943
|
+
if (!bootstrapPromise) {
|
|
5944
|
+
bootstrapPromise = new Promise(function(resolve, reject) {
|
|
5945
|
+
bootstrapResolve = resolve;
|
|
5946
|
+
bootstrapReject = reject;
|
|
5947
|
+
});
|
|
5948
|
+
}
|
|
5949
|
+
return bootstrapPromise;
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
window.__venusLibraryShim = {
|
|
5953
|
+
bootstrap: bootstrap,
|
|
5954
|
+
ready: getBootstrapPromise,
|
|
5955
|
+
getExports: function (libraryKey) {
|
|
5956
|
+
var registry = ensureExportsRegistry();
|
|
5957
|
+
return registry[libraryKey];
|
|
5958
|
+
},
|
|
5959
|
+
__initialized: true,
|
|
5960
|
+
};
|
|
5961
|
+
})();
|
|
5962
|
+
`;
|
|
5963
|
+
function getWebviewLibraryShimSource() {
|
|
5964
|
+
return WEBVIEW_LIBRARY_SHIM_SOURCE;
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
exports.DEFAULT_SHARED_LIB_CDN_BASE = DEFAULT_SHARED_LIB_CDN_BASE;
|
|
5968
|
+
exports.EMBEDDED_LIBRARIES = EMBEDDED_LIBRARIES;
|
|
5969
|
+
exports.EMBEDDED_LIBRARY_BY_KEY = EMBEDDED_LIBRARY_BY_KEY;
|
|
5970
|
+
exports.HASH_ALGORITHM_NODE = HASH_ALGORITHM_NODE;
|
|
5971
|
+
exports.HASH_ALGORITHM_WEB_CRYPTO = HASH_ALGORITHM_WEB_CRYPTO;
|
|
5316
5972
|
exports.HapticFeedbackStyle = HapticFeedbackStyle;
|
|
5317
5973
|
exports.HostCdnApi = HostCdnApi;
|
|
5318
5974
|
exports.HostProfileApi = HostProfileApi;
|
|
5319
5975
|
exports.HostTimeApi = HostTimeApi;
|
|
5976
|
+
exports.MODULE_TO_LIBRARY_SPECIFIERS = MODULE_TO_LIBRARY_SPECIFIERS;
|
|
5320
5977
|
exports.MockAdsApi = MockAdsApi;
|
|
5321
5978
|
exports.MockAiApi = MockAiApi;
|
|
5322
5979
|
exports.MockAnalyticsApi = MockAnalyticsApi;
|
|
@@ -5360,8 +6017,14 @@ exports.RpcSocialApi = RpcSocialApi;
|
|
|
5360
6017
|
exports.RpcStorageApi = RpcStorageApi;
|
|
5361
6018
|
exports.SDK_VERSION = SDK_VERSION;
|
|
5362
6019
|
exports.VenusMessageId = VenusMessageId;
|
|
6020
|
+
exports.WEBVIEW_LIBRARY_SHIM_SOURCE = WEBVIEW_LIBRARY_SHIM_SOURCE;
|
|
6021
|
+
exports.base64ToArrayBuffer = base64ToArrayBuffer;
|
|
6022
|
+
exports.base64ToUtf8 = base64ToUtf8;
|
|
6023
|
+
exports.computeScoreHash = computeScoreHash;
|
|
5363
6024
|
exports.createHost = createHost;
|
|
5364
6025
|
exports.createMockStorageApi = createMockStorageApi;
|
|
6026
|
+
exports.getLibraryDefinition = getLibraryDefinition;
|
|
6027
|
+
exports.getWebviewLibraryShimSource = getWebviewLibraryShimSource;
|
|
5365
6028
|
exports.initializeAds = initializeAds;
|
|
5366
6029
|
exports.initializeAi = initializeAi;
|
|
5367
6030
|
exports.initializeAnalytics = initializeAnalytics;
|