@heybox/hb-sdk 0.6.7-alpha.0 → 0.6.7-alpha.2
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 +3 -3
- package/dist/cli-chunks/{build-mTmtBJbp.cjs → build-CQmYxfxm.cjs} +25 -29
- package/dist/cli-chunks/{context-wI8oXc58.cjs → context-ChkYWwH_.cjs} +23 -122
- package/dist/cli-chunks/{create-DEwECU7u.cjs → create-CC5r_8bL.cjs} +1 -1
- package/dist/cli-chunks/{dev-BZ7FJEeZ.cjs → dev-CD-38TgO.cjs} +110 -21
- package/dist/cli-chunks/{doctor-DbJQPPs2.cjs → doctor-43yEfVr0.cjs} +1 -1
- package/dist/cli-chunks/{index-UecHob74.cjs → index-BM6oH2Hs.cjs} +3 -3
- package/dist/cli-chunks/{runtime-permission-env-BSs4uCNa.cjs → index-BQm5XmMC.cjs} +0 -71
- package/dist/cli-chunks/{index-Df14XqmW.cjs → index-CQnkS0Z8.cjs} +14 -14
- package/dist/cli-chunks/{login-BzSUtgRH.cjs → login-BmisXAdp.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-D2Hx7XPp.cjs → project-vite-D9_v57vp.cjs} +1 -1
- package/dist/cli-chunks/{remote-BZiSfXOm.cjs → remote-BXtT6M2f.cjs} +22 -40
- package/dist/cli-chunks/{runtime-gate--rPXjiG6.cjs → runtime-gate-B2MQf1vc.cjs} +3 -3
- package/dist/cli-chunks/{session-CqycMFvy.cjs → session-BjtjhtPg.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/main.js +187 -21
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/vite.cjs.js +50 -28
- package/dist/vite.esm.js +50 -28
- package/package.json +1 -1
- package/skill/references/api-root.md +7 -9
- package/skill/skill.json +4 -4
- package/types/vite/html-policy.d.ts +0 -1
- package/types/vite/index.d.ts +1 -0
- package/types/vite/runtime-permission-env.d.ts +0 -9
|
@@ -3707,25 +3707,61 @@ function stringifyMiniProgramRuntimeJsonData(data, options) {
|
|
|
3707
3707
|
}
|
|
3708
3708
|
|
|
3709
3709
|
const LEADERBOARD_KEY_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
3710
|
+
const DEFAULT_LEADERBOARD_KEY = 'default';
|
|
3710
3711
|
const DEFAULT_LEADERBOARD_LIST_LIMIT = 20;
|
|
3711
3712
|
const MAX_LEADERBOARD_LIST_LIMIT = 100;
|
|
3712
3713
|
const MAX_LEADERBOARD_EXTRA_BYTES = 2048;
|
|
3713
3714
|
const MAX_LEADERBOARD_SAFE_SCORE = Number.MAX_SAFE_INTEGER;
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3715
|
+
const LEADERBOARD_READ_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
3716
|
+
const MAX_LEADERBOARD_LIST_CACHE_ENTRIES = 250;
|
|
3717
|
+
const MAX_LEADERBOARD_CACHE_BUCKETS = 3;
|
|
3718
|
+
/** 创建一组共享读缓存的排行榜 handler。 */
|
|
3719
|
+
function createMiniProgramRuntimeLeaderboardHandlers(options) {
|
|
3720
|
+
const store = createLeaderboardReadStore();
|
|
3721
|
+
return {
|
|
3722
|
+
async submit(payload) {
|
|
3723
|
+
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.submit', 'submit');
|
|
3724
|
+
const bucketKey = createLeaderboardBucketKey(options, request.key);
|
|
3725
|
+
return submitLeaderboardEntry(request, options, () => store.invalidateMutableReads(bucketKey));
|
|
3726
|
+
},
|
|
3727
|
+
async getList(payload) {
|
|
3728
|
+
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getList', 'list');
|
|
3729
|
+
const bucketKey = createLeaderboardBucketKey(options, request.key);
|
|
3730
|
+
const cacheKey = createLeaderboardCacheKey('list', request.limit, request.cursor ?? null);
|
|
3731
|
+
return store.read(bucketKey, 'list', cacheKey, () => requestLeaderboardList(request, options));
|
|
3732
|
+
},
|
|
3733
|
+
async getCurrentUserEntry(payload) {
|
|
3734
|
+
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getCurrentUserEntry', 'keyOnly');
|
|
3735
|
+
const userId = await readCurrentUserId(options.platformAdapter);
|
|
3736
|
+
const bucketKey = createLeaderboardBucketKey(options, request.key);
|
|
3737
|
+
const cacheKey = createLeaderboardCacheKey('current', userId);
|
|
3738
|
+
return store.read(bucketKey, 'current', cacheKey, () => requestCurrentUserLeaderboardEntry(request, userId, options));
|
|
3739
|
+
},
|
|
3740
|
+
async deleteCurrentUserEntry(payload) {
|
|
3741
|
+
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.deleteCurrentUserEntry', 'keyOnly');
|
|
3742
|
+
const bucketKey = createLeaderboardBucketKey(options, request.key);
|
|
3743
|
+
return deleteCurrentUserLeaderboardEntry(request, options, () => store.invalidateMutableReads(bucketKey));
|
|
3744
|
+
},
|
|
3745
|
+
async getInfo(payload) {
|
|
3746
|
+
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getInfo', 'keyOnly');
|
|
3747
|
+
const bucketKey = createLeaderboardBucketKey(options, request.key);
|
|
3748
|
+
const cacheKey = createLeaderboardCacheKey('info');
|
|
3749
|
+
return store.read(bucketKey, 'info', cacheKey, () => requestLeaderboardInfo(request, options));
|
|
3750
|
+
},
|
|
3751
|
+
};
|
|
3752
|
+
}
|
|
3753
|
+
async function submitLeaderboardEntry(request, options, onAdapterSuccess) {
|
|
3717
3754
|
const userId = await readCurrentUserId(options.platformAdapter);
|
|
3718
3755
|
const entry = await options.platformAdapter.cloud.leaderboard.submit({
|
|
3719
3756
|
...request,
|
|
3720
3757
|
miniProgramId: options.identity?.miniProgramId,
|
|
3721
3758
|
userId,
|
|
3722
3759
|
});
|
|
3760
|
+
onAdapterSuccess?.();
|
|
3723
3761
|
assertLeaderboardEntry(entry, 'cloud.leaderboard.submit');
|
|
3724
3762
|
return entry;
|
|
3725
3763
|
}
|
|
3726
|
-
|
|
3727
|
-
async function getMiniProgramRuntimeLeaderboardList(payload, options) {
|
|
3728
|
-
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getList', 'list');
|
|
3764
|
+
async function requestLeaderboardList(request, options) {
|
|
3729
3765
|
const result = await options.platformAdapter.cloud.leaderboard.getList({
|
|
3730
3766
|
...request,
|
|
3731
3767
|
miniProgramId: options.identity?.miniProgramId,
|
|
@@ -3743,10 +3779,7 @@ async function getMiniProgramRuntimeLeaderboardList(payload, options) {
|
|
|
3743
3779
|
}
|
|
3744
3780
|
return result;
|
|
3745
3781
|
}
|
|
3746
|
-
|
|
3747
|
-
async function getMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options) {
|
|
3748
|
-
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getCurrentUserEntry', 'keyOnly');
|
|
3749
|
-
const userId = await readCurrentUserId(options.platformAdapter);
|
|
3782
|
+
async function requestCurrentUserLeaderboardEntry(request, userId, options) {
|
|
3750
3783
|
const entry = await options.platformAdapter.cloud.leaderboard.getCurrentUserEntry({
|
|
3751
3784
|
...request,
|
|
3752
3785
|
miniProgramId: options.identity?.miniProgramId,
|
|
@@ -3757,24 +3790,21 @@ async function getMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options
|
|
|
3757
3790
|
}
|
|
3758
3791
|
return entry;
|
|
3759
3792
|
}
|
|
3760
|
-
|
|
3761
|
-
async function deleteMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options) {
|
|
3762
|
-
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.deleteCurrentUserEntry', 'keyOnly');
|
|
3793
|
+
async function deleteCurrentUserLeaderboardEntry(request, options, onAdapterSuccess) {
|
|
3763
3794
|
const userId = await readCurrentUserId(options.platformAdapter);
|
|
3764
3795
|
const result = await options.platformAdapter.cloud.leaderboard.deleteCurrentUserEntry({
|
|
3765
3796
|
...request,
|
|
3766
3797
|
miniProgramId: options.identity?.miniProgramId,
|
|
3767
3798
|
userId,
|
|
3768
3799
|
});
|
|
3800
|
+
onAdapterSuccess?.();
|
|
3769
3801
|
assertMiniProgramRuntimeRecord(result, 'cloud.leaderboard.deleteCurrentUserEntry 返回值必须是对象');
|
|
3770
3802
|
if (typeof result.deleted !== 'boolean') {
|
|
3771
3803
|
throw createMiniProgramRuntimeBridgeError('INVALID_RESPONSE', 'cloud.leaderboard.deleteCurrentUserEntry 返回的 deleted 必须是布尔值');
|
|
3772
3804
|
}
|
|
3773
3805
|
return result;
|
|
3774
3806
|
}
|
|
3775
|
-
|
|
3776
|
-
async function getMiniProgramRuntimeLeaderboardInfo(payload, options) {
|
|
3777
|
-
const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getInfo', 'keyOnly');
|
|
3807
|
+
async function requestLeaderboardInfo(request, options) {
|
|
3778
3808
|
const info = await options.platformAdapter.cloud.leaderboard.getInfo({
|
|
3779
3809
|
...request,
|
|
3780
3810
|
miniProgramId: options.identity?.miniProgramId,
|
|
@@ -3791,6 +3821,138 @@ async function getMiniProgramRuntimeLeaderboardInfo(payload, options) {
|
|
|
3791
3821
|
}
|
|
3792
3822
|
return info;
|
|
3793
3823
|
}
|
|
3824
|
+
function createLeaderboardReadStore() {
|
|
3825
|
+
const buckets = new Map();
|
|
3826
|
+
const inflight = new Map();
|
|
3827
|
+
function getOrCreateBucket(bucketKey) {
|
|
3828
|
+
const bucket = buckets.get(bucketKey);
|
|
3829
|
+
if (bucket) {
|
|
3830
|
+
return bucket;
|
|
3831
|
+
}
|
|
3832
|
+
pruneExpiredBuckets();
|
|
3833
|
+
if (buckets.size >= MAX_LEADERBOARD_CACHE_BUCKETS) {
|
|
3834
|
+
return undefined;
|
|
3835
|
+
}
|
|
3836
|
+
const nextBucket = {
|
|
3837
|
+
generation: 0,
|
|
3838
|
+
caches: {
|
|
3839
|
+
list: new Map(),
|
|
3840
|
+
current: new Map(),
|
|
3841
|
+
info: new Map(),
|
|
3842
|
+
},
|
|
3843
|
+
};
|
|
3844
|
+
buckets.set(bucketKey, nextBucket);
|
|
3845
|
+
return nextBucket;
|
|
3846
|
+
}
|
|
3847
|
+
function read(bucketKey, kind, cacheKey, request) {
|
|
3848
|
+
const bucket = getOrCreateBucket(bucketKey);
|
|
3849
|
+
const cache = bucket?.caches[kind];
|
|
3850
|
+
const cached = cache?.get(cacheKey);
|
|
3851
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
3852
|
+
return Promise.resolve(cached.value);
|
|
3853
|
+
}
|
|
3854
|
+
cache?.delete(cacheKey);
|
|
3855
|
+
const inflightKey = createLeaderboardInflightKey(bucketKey, cacheKey);
|
|
3856
|
+
const existingInflight = inflight.get(inflightKey);
|
|
3857
|
+
if (existingInflight) {
|
|
3858
|
+
return existingInflight.promise;
|
|
3859
|
+
}
|
|
3860
|
+
const requestGeneration = bucket?.generation;
|
|
3861
|
+
const promise = request()
|
|
3862
|
+
.then((result) => {
|
|
3863
|
+
if (bucket && cache && bucket.generation === requestGeneration) {
|
|
3864
|
+
if (kind === 'list') {
|
|
3865
|
+
if (cache.size >= MAX_LEADERBOARD_LIST_CACHE_ENTRIES) {
|
|
3866
|
+
cache.delete(cache.keys().next().value);
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
else {
|
|
3870
|
+
cache.clear();
|
|
3871
|
+
}
|
|
3872
|
+
cache.set(cacheKey, {
|
|
3873
|
+
expiresAt: Date.now() + LEADERBOARD_READ_CACHE_TTL_MS,
|
|
3874
|
+
value: result,
|
|
3875
|
+
});
|
|
3876
|
+
}
|
|
3877
|
+
return result;
|
|
3878
|
+
})
|
|
3879
|
+
.finally(() => {
|
|
3880
|
+
if (inflight.get(inflightKey)?.promise === promise) {
|
|
3881
|
+
inflight.delete(inflightKey);
|
|
3882
|
+
}
|
|
3883
|
+
if (bucket) {
|
|
3884
|
+
removeEmptyBucket(bucketKey, bucket);
|
|
3885
|
+
}
|
|
3886
|
+
});
|
|
3887
|
+
inflight.set(inflightKey, { bucketKey, promise });
|
|
3888
|
+
return promise;
|
|
3889
|
+
}
|
|
3890
|
+
function invalidateMutableReads(bucketKey) {
|
|
3891
|
+
invalidateInflight(bucketKey);
|
|
3892
|
+
const bucket = buckets.get(bucketKey);
|
|
3893
|
+
if (!bucket) {
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3896
|
+
bucket.generation += 1;
|
|
3897
|
+
bucket.caches.list.clear();
|
|
3898
|
+
bucket.caches.current.clear();
|
|
3899
|
+
}
|
|
3900
|
+
function invalidateInflight(bucketKey) {
|
|
3901
|
+
inflight.forEach((entry, inflightKey) => {
|
|
3902
|
+
if (entry.bucketKey === bucketKey) {
|
|
3903
|
+
inflight.delete(inflightKey);
|
|
3904
|
+
}
|
|
3905
|
+
});
|
|
3906
|
+
}
|
|
3907
|
+
function pruneExpiredBuckets() {
|
|
3908
|
+
const now = Date.now();
|
|
3909
|
+
for (const [bucketKey, bucket] of buckets) {
|
|
3910
|
+
removeExpiredCacheEntries(bucket, now);
|
|
3911
|
+
if (isBucketEmpty(bucketKey, bucket)) {
|
|
3912
|
+
buckets.delete(bucketKey);
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
function removeEmptyBucket(bucketKey, bucket) {
|
|
3917
|
+
removeExpiredCacheEntries(bucket, Date.now());
|
|
3918
|
+
if (buckets.get(bucketKey) === bucket && isBucketEmpty(bucketKey, bucket)) {
|
|
3919
|
+
buckets.delete(bucketKey);
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
function removeExpiredCacheEntries(bucket, now) {
|
|
3923
|
+
Object.values(bucket.caches).forEach((cache) => {
|
|
3924
|
+
cache.forEach((entry, cacheKey) => {
|
|
3925
|
+
if (entry.expiresAt <= now) {
|
|
3926
|
+
cache.delete(cacheKey);
|
|
3927
|
+
}
|
|
3928
|
+
});
|
|
3929
|
+
});
|
|
3930
|
+
}
|
|
3931
|
+
function isBucketEmpty(bucketKey, bucket) {
|
|
3932
|
+
return !hasInflight(bucketKey) && Object.values(bucket.caches).every(cache => cache.size === 0);
|
|
3933
|
+
}
|
|
3934
|
+
function hasInflight(bucketKey) {
|
|
3935
|
+
for (const entry of inflight.values()) {
|
|
3936
|
+
if (entry.bucketKey === bucketKey) {
|
|
3937
|
+
return true;
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
return false;
|
|
3941
|
+
}
|
|
3942
|
+
return {
|
|
3943
|
+
read,
|
|
3944
|
+
invalidateMutableReads,
|
|
3945
|
+
};
|
|
3946
|
+
}
|
|
3947
|
+
function createLeaderboardBucketKey(options, key) {
|
|
3948
|
+
return JSON.stringify([options.identity?.miniProgramId ?? null, key ?? DEFAULT_LEADERBOARD_KEY]);
|
|
3949
|
+
}
|
|
3950
|
+
function createLeaderboardCacheKey(kind, ...parts) {
|
|
3951
|
+
return JSON.stringify([kind, ...parts]);
|
|
3952
|
+
}
|
|
3953
|
+
function createLeaderboardInflightKey(bucketKey, cacheKey) {
|
|
3954
|
+
return JSON.stringify([bucketKey, cacheKey]);
|
|
3955
|
+
}
|
|
3794
3956
|
function readLeaderboardPayload(payload, methodName, shape) {
|
|
3795
3957
|
if (payload === undefined && shape !== 'submit') {
|
|
3796
3958
|
return shape === 'list' ? { limit: DEFAULT_LEADERBOARD_LIST_LIMIT } : {};
|
|
@@ -5505,6 +5667,10 @@ class MiniProgramMockRuntime {
|
|
|
5505
5667
|
this.vibrates = [];
|
|
5506
5668
|
this.openAppPages = [];
|
|
5507
5669
|
this.evaluateRuntimePermission = createMiniProgramRuntimePermissionEvaluator(options.runtimePermissions);
|
|
5670
|
+
this.leaderboardHandlers = createMiniProgramRuntimeLeaderboardHandlers({
|
|
5671
|
+
identity: options.identity,
|
|
5672
|
+
platformAdapter: adapter,
|
|
5673
|
+
});
|
|
5508
5674
|
}
|
|
5509
5675
|
async runMethod(method, payload) {
|
|
5510
5676
|
if (!isMiniProgramMockRuntimeMethod(method)) {
|
|
@@ -5634,19 +5800,19 @@ class MiniProgramMockRuntime {
|
|
|
5634
5800
|
return requestMiniProgramRuntimeNetwork(payload, this.adapter);
|
|
5635
5801
|
}
|
|
5636
5802
|
submitLeaderboardEntry(payload) {
|
|
5637
|
-
return
|
|
5803
|
+
return this.leaderboardHandlers.submit(payload);
|
|
5638
5804
|
}
|
|
5639
5805
|
getLeaderboardList(payload) {
|
|
5640
|
-
return
|
|
5806
|
+
return this.leaderboardHandlers.getList(payload);
|
|
5641
5807
|
}
|
|
5642
5808
|
getCurrentUserLeaderboardEntry(payload) {
|
|
5643
|
-
return
|
|
5809
|
+
return this.leaderboardHandlers.getCurrentUserEntry(payload);
|
|
5644
5810
|
}
|
|
5645
5811
|
deleteCurrentUserLeaderboardEntry(payload) {
|
|
5646
|
-
return
|
|
5812
|
+
return this.leaderboardHandlers.deleteCurrentUserEntry(payload);
|
|
5647
5813
|
}
|
|
5648
5814
|
getLeaderboardInfo(payload) {
|
|
5649
|
-
return
|
|
5815
|
+
return this.leaderboardHandlers.getInfo(payload);
|
|
5650
5816
|
}
|
|
5651
5817
|
async showToast(payload) {
|
|
5652
5818
|
const toast = readShowToastPayload(payload);
|
package/dist/index.cjs.js
CHANGED
package/dist/index.esm.js
CHANGED
package/dist/vite.cjs.js
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
var node_fs = require('node:fs');
|
|
4
4
|
var path = require('node:path');
|
|
5
|
-
var node_async_hooks = require('node:async_hooks');
|
|
6
5
|
|
|
7
6
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
8
7
|
/** 构建时替换为当前发布包的实际版本。 */
|
|
9
8
|
const HB_SDK_VERSION = typeof undefined === 'string'
|
|
10
9
|
? undefined
|
|
11
|
-
: '0.6.7-alpha.
|
|
10
|
+
: '0.6.7-alpha.2';
|
|
12
11
|
|
|
13
12
|
var re = {exports: {}};
|
|
14
13
|
|
|
@@ -11433,13 +11432,17 @@ function walk$1(node, visit) {
|
|
|
11433
11432
|
|
|
11434
11433
|
const FORBIDDEN_RESOURCE_HINTS = new Set(['dns-prefetch', 'preconnect', 'prerender']);
|
|
11435
11434
|
const RELATIVE_URL_BASE = new URL('https://heybox-relative.invalid/');
|
|
11435
|
+
const OFFICIAL_RESOURCE_ROOT_DOMAINS = ['xiaoheihe.cn', 'max-c.com', 'debugmode.cn', 'maxjia.com'];
|
|
11436
|
+
const OFFICIAL_RESOURCE_SOURCES = OFFICIAL_RESOURCE_ROOT_DOMAINS.flatMap(rootDomain => [
|
|
11437
|
+
`https://${rootDomain}`,
|
|
11438
|
+
`https://*.${rootDomain}`,
|
|
11439
|
+
]);
|
|
11436
11440
|
const URL_ATTRIBUTES = {
|
|
11437
11441
|
audio: ['src'],
|
|
11438
11442
|
embed: ['src'],
|
|
11439
11443
|
iframe: ['src'],
|
|
11440
11444
|
img: ['src'],
|
|
11441
11445
|
input: ['src'],
|
|
11442
|
-
link: ['href'],
|
|
11443
11446
|
object: ['data'],
|
|
11444
11447
|
script: ['src'],
|
|
11445
11448
|
source: ['src', 'srcset'],
|
|
@@ -11449,11 +11452,11 @@ const URL_ATTRIBUTES = {
|
|
|
11449
11452
|
const PRODUCTION_CSP = [
|
|
11450
11453
|
"default-src 'none'",
|
|
11451
11454
|
"connect-src 'none'",
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11455
|
+
`script-src 'self' 'unsafe-inline' ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11456
|
+
`style-src 'self' 'unsafe-inline' ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11457
|
+
`img-src 'self' data: blob: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11458
|
+
`font-src 'self' data: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11459
|
+
`media-src 'self' blob: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11457
11460
|
"manifest-src 'self'",
|
|
11458
11461
|
"frame-src 'none'",
|
|
11459
11462
|
"child-src 'none'",
|
|
@@ -11472,9 +11475,6 @@ function enforceMiniappHtmlPolicy(html, options = {}) {
|
|
|
11472
11475
|
removePlatformCspMarkers(document);
|
|
11473
11476
|
walk(document, element => validateElement(element));
|
|
11474
11477
|
injectMiniappRuntimeGate(document);
|
|
11475
|
-
if (options.skipPlatformCsp) {
|
|
11476
|
-
return serialize(document);
|
|
11477
|
-
}
|
|
11478
11478
|
const content = options.hmrWebSocketUrl
|
|
11479
11479
|
? PRODUCTION_CSP.replace("connect-src 'none'", `connect-src ${options.hmrWebSocketUrl}`)
|
|
11480
11480
|
: PRODUCTION_CSP;
|
|
@@ -11511,19 +11511,25 @@ function validateElement(element) {
|
|
|
11511
11511
|
if (forbidden) {
|
|
11512
11512
|
throw new Error(`index.html 不允许 rel="${forbidden}"`);
|
|
11513
11513
|
}
|
|
11514
|
-
if (rels.includes('
|
|
11514
|
+
if (rels.includes('stylesheet')) {
|
|
11515
|
+
validateResourceUrl(attrs.get('href'), '<link rel="stylesheet" href>', false, true);
|
|
11516
|
+
}
|
|
11517
|
+
else if (rels.includes('preload') || rels.includes('modulepreload')) {
|
|
11515
11518
|
validateRelativeUrl(attrs.get('href'), `<link rel="${rels.includes('modulepreload') ? 'modulepreload' : 'preload'}" href>`, false);
|
|
11516
11519
|
}
|
|
11520
|
+
else {
|
|
11521
|
+
validateRelativeUrl(attrs.get('href'), '<link href>', false);
|
|
11522
|
+
}
|
|
11517
11523
|
}
|
|
11518
11524
|
for (const attribute of URL_ATTRIBUTES[tagName] ?? []) {
|
|
11519
11525
|
const value = attrs.get(attribute);
|
|
11520
11526
|
if (attribute === 'srcset') {
|
|
11521
11527
|
for (const candidate of (value ?? '').split(',').map(item => item.trim().split(/\s+/)[0]).filter(Boolean)) {
|
|
11522
|
-
|
|
11528
|
+
validateResourceUrl(candidate, `<${tagName} ${attribute}>`, true, supportsOfficialResourceUrl(tagName, attribute));
|
|
11523
11529
|
}
|
|
11524
11530
|
}
|
|
11525
11531
|
else {
|
|
11526
|
-
|
|
11532
|
+
validateResourceUrl(value, `<${tagName} ${attribute}>`, true, supportsOfficialResourceUrl(tagName, attribute));
|
|
11527
11533
|
}
|
|
11528
11534
|
}
|
|
11529
11535
|
}
|
|
@@ -11538,16 +11544,43 @@ function removePlatformCspMarkers(node) {
|
|
|
11538
11544
|
for (const child of node.childNodes)
|
|
11539
11545
|
removePlatformCspMarkers(child);
|
|
11540
11546
|
}
|
|
11541
|
-
function
|
|
11547
|
+
function supportsOfficialResourceUrl(tagName, attribute) {
|
|
11548
|
+
return ((tagName === 'script' && attribute === 'src') ||
|
|
11549
|
+
(tagName === 'img' && attribute === 'src') ||
|
|
11550
|
+
(tagName === 'source' && (attribute === 'src' || attribute === 'srcset')) ||
|
|
11551
|
+
(tagName === 'audio' && attribute === 'src') ||
|
|
11552
|
+
(tagName === 'track' && attribute === 'src') ||
|
|
11553
|
+
(tagName === 'video' && (attribute === 'src' || attribute === 'poster')));
|
|
11554
|
+
}
|
|
11555
|
+
function validateResourceUrl(value, label, allowDataBlob, allowOfficialResourceUrl) {
|
|
11542
11556
|
if (!value || value.startsWith('#'))
|
|
11543
11557
|
return;
|
|
11544
11558
|
const normalized = value.trim().toLowerCase();
|
|
11545
11559
|
if (allowDataBlob && (normalized.startsWith('data:') || normalized.startsWith('blob:')))
|
|
11546
11560
|
return;
|
|
11561
|
+
if (allowOfficialResourceUrl && isOfficialResourceUrl(value))
|
|
11562
|
+
return;
|
|
11547
11563
|
if (!isRelativeUrl(value, normalized)) {
|
|
11548
11564
|
throw new Error(`${label} 必须使用相对路径${allowDataBlob ? '或明确的 data:/blob: URL' : ''}:${value}`);
|
|
11549
11565
|
}
|
|
11550
11566
|
}
|
|
11567
|
+
function validateRelativeUrl(value, label, allowDataBlob) {
|
|
11568
|
+
validateResourceUrl(value, label, allowDataBlob, false);
|
|
11569
|
+
}
|
|
11570
|
+
function isOfficialResourceUrl(value) {
|
|
11571
|
+
try {
|
|
11572
|
+
const url = new URL(value);
|
|
11573
|
+
if (url.protocol !== 'https:' || url.username || url.password)
|
|
11574
|
+
return false;
|
|
11575
|
+
const hostname = url.hostname.toLowerCase();
|
|
11576
|
+
if (hostname.endsWith('.'))
|
|
11577
|
+
return false;
|
|
11578
|
+
return OFFICIAL_RESOURCE_ROOT_DOMAINS.some(rootDomain => hostname === rootDomain || hostname.endsWith(`.${rootDomain}`));
|
|
11579
|
+
}
|
|
11580
|
+
catch {
|
|
11581
|
+
return false;
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11551
11584
|
function isRelativeUrl(value, normalized) {
|
|
11552
11585
|
const browserNormalized = normalized.replace(/[\t\n\r]/g, '');
|
|
11553
11586
|
if (browserNormalized.includes('\\') || browserNormalized.startsWith('//'))
|
|
@@ -11584,19 +11617,9 @@ function walk(node, visit) {
|
|
|
11584
11617
|
walk(node.content, visit);
|
|
11585
11618
|
}
|
|
11586
11619
|
|
|
11587
|
-
const HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV = 'HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN';
|
|
11588
|
-
const HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV = 'HB_SDK_RUNTIME_PERMISSION_CONTEXT';
|
|
11589
|
-
const VERIFIED_RUNTIME_PERMISSION_CONTEXT = 'verified';
|
|
11590
|
-
new node_async_hooks.AsyncLocalStorage();
|
|
11591
|
-
Promise.resolve();
|
|
11592
|
-
function shouldSkipMiniappPlatformCspFromEnv(env = process.env) {
|
|
11593
|
-
return env[HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV] === VERIFIED_RUNTIME_PERMISSION_CONTEXT && env[HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV] === '1';
|
|
11594
|
-
}
|
|
11595
|
-
|
|
11596
11620
|
const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
|
|
11597
11621
|
const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
|
|
11598
11622
|
function miniappManifest() {
|
|
11599
|
-
const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
|
|
11600
11623
|
let root = process.cwd();
|
|
11601
11624
|
let outDir = 'dist';
|
|
11602
11625
|
let command = 'build';
|
|
@@ -11628,7 +11651,6 @@ function miniappManifest() {
|
|
|
11628
11651
|
transformIndexHtml(html) {
|
|
11629
11652
|
return enforceMiniappHtmlPolicy(html, {
|
|
11630
11653
|
...(command === 'serve' ? { hmrWebSocketUrl } : {}),
|
|
11631
|
-
skipPlatformCsp,
|
|
11632
11654
|
});
|
|
11633
11655
|
},
|
|
11634
11656
|
async closeBundle() {
|
|
@@ -11651,7 +11673,7 @@ function miniappManifest() {
|
|
|
11651
11673
|
if (!htmlFiles.includes(indexHtmlPath)) {
|
|
11652
11674
|
throw new Error('构建产物必须包含入口 dist/index.html');
|
|
11653
11675
|
}
|
|
11654
|
-
node_fs.writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(node_fs.readFileSync(indexHtmlPath, 'utf8')
|
|
11676
|
+
node_fs.writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(node_fs.readFileSync(indexHtmlPath, 'utf8')));
|
|
11655
11677
|
const manifestPath = path.join(outputRoot, 'manifest.json');
|
|
11656
11678
|
node_fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
11657
11679
|
node_fs.writeFileSync(manifestPath, renderMiniappManifest({ version, sdkVersion }));
|
|
@@ -11693,7 +11715,7 @@ function resolveHmrWebSocketUrl(resolved) {
|
|
|
11693
11715
|
if (hmr === false)
|
|
11694
11716
|
return undefined;
|
|
11695
11717
|
const options = typeof hmr === 'object' ? hmr : {};
|
|
11696
|
-
const protocol = options.protocol ?? 'ws';
|
|
11718
|
+
const protocol = options.protocol ?? (resolved.server.https ? 'wss' : 'ws');
|
|
11697
11719
|
const configuredHost = options.host ?? resolved.server.host;
|
|
11698
11720
|
const host = typeof configuredHost === 'string' && configuredHost !== '0.0.0.0' ? configuredHost : '127.0.0.1';
|
|
11699
11721
|
const port = options.clientPort ?? options.port ?? resolved.server.port;
|
package/dist/vite.esm.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { readFileSync, existsSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
3
|
|
|
5
4
|
/** 构建时替换为当前发布包的实际版本。 */
|
|
6
5
|
const HB_SDK_VERSION = typeof undefined === 'string'
|
|
7
6
|
? undefined
|
|
8
|
-
: '0.6.7-alpha.
|
|
7
|
+
: '0.6.7-alpha.2';
|
|
9
8
|
|
|
10
9
|
var re = {exports: {}};
|
|
11
10
|
|
|
@@ -11430,13 +11429,17 @@ function walk$1(node, visit) {
|
|
|
11430
11429
|
|
|
11431
11430
|
const FORBIDDEN_RESOURCE_HINTS = new Set(['dns-prefetch', 'preconnect', 'prerender']);
|
|
11432
11431
|
const RELATIVE_URL_BASE = new URL('https://heybox-relative.invalid/');
|
|
11432
|
+
const OFFICIAL_RESOURCE_ROOT_DOMAINS = ['xiaoheihe.cn', 'max-c.com', 'debugmode.cn', 'maxjia.com'];
|
|
11433
|
+
const OFFICIAL_RESOURCE_SOURCES = OFFICIAL_RESOURCE_ROOT_DOMAINS.flatMap(rootDomain => [
|
|
11434
|
+
`https://${rootDomain}`,
|
|
11435
|
+
`https://*.${rootDomain}`,
|
|
11436
|
+
]);
|
|
11433
11437
|
const URL_ATTRIBUTES = {
|
|
11434
11438
|
audio: ['src'],
|
|
11435
11439
|
embed: ['src'],
|
|
11436
11440
|
iframe: ['src'],
|
|
11437
11441
|
img: ['src'],
|
|
11438
11442
|
input: ['src'],
|
|
11439
|
-
link: ['href'],
|
|
11440
11443
|
object: ['data'],
|
|
11441
11444
|
script: ['src'],
|
|
11442
11445
|
source: ['src', 'srcset'],
|
|
@@ -11446,11 +11449,11 @@ const URL_ATTRIBUTES = {
|
|
|
11446
11449
|
const PRODUCTION_CSP = [
|
|
11447
11450
|
"default-src 'none'",
|
|
11448
11451
|
"connect-src 'none'",
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11452
|
+
`script-src 'self' 'unsafe-inline' ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11453
|
+
`style-src 'self' 'unsafe-inline' ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11454
|
+
`img-src 'self' data: blob: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11455
|
+
`font-src 'self' data: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11456
|
+
`media-src 'self' blob: ${OFFICIAL_RESOURCE_SOURCES.join(' ')}`,
|
|
11454
11457
|
"manifest-src 'self'",
|
|
11455
11458
|
"frame-src 'none'",
|
|
11456
11459
|
"child-src 'none'",
|
|
@@ -11469,9 +11472,6 @@ function enforceMiniappHtmlPolicy(html, options = {}) {
|
|
|
11469
11472
|
removePlatformCspMarkers(document);
|
|
11470
11473
|
walk(document, element => validateElement(element));
|
|
11471
11474
|
injectMiniappRuntimeGate(document);
|
|
11472
|
-
if (options.skipPlatformCsp) {
|
|
11473
|
-
return serialize(document);
|
|
11474
|
-
}
|
|
11475
11475
|
const content = options.hmrWebSocketUrl
|
|
11476
11476
|
? PRODUCTION_CSP.replace("connect-src 'none'", `connect-src ${options.hmrWebSocketUrl}`)
|
|
11477
11477
|
: PRODUCTION_CSP;
|
|
@@ -11508,19 +11508,25 @@ function validateElement(element) {
|
|
|
11508
11508
|
if (forbidden) {
|
|
11509
11509
|
throw new Error(`index.html 不允许 rel="${forbidden}"`);
|
|
11510
11510
|
}
|
|
11511
|
-
if (rels.includes('
|
|
11511
|
+
if (rels.includes('stylesheet')) {
|
|
11512
|
+
validateResourceUrl(attrs.get('href'), '<link rel="stylesheet" href>', false, true);
|
|
11513
|
+
}
|
|
11514
|
+
else if (rels.includes('preload') || rels.includes('modulepreload')) {
|
|
11512
11515
|
validateRelativeUrl(attrs.get('href'), `<link rel="${rels.includes('modulepreload') ? 'modulepreload' : 'preload'}" href>`, false);
|
|
11513
11516
|
}
|
|
11517
|
+
else {
|
|
11518
|
+
validateRelativeUrl(attrs.get('href'), '<link href>', false);
|
|
11519
|
+
}
|
|
11514
11520
|
}
|
|
11515
11521
|
for (const attribute of URL_ATTRIBUTES[tagName] ?? []) {
|
|
11516
11522
|
const value = attrs.get(attribute);
|
|
11517
11523
|
if (attribute === 'srcset') {
|
|
11518
11524
|
for (const candidate of (value ?? '').split(',').map(item => item.trim().split(/\s+/)[0]).filter(Boolean)) {
|
|
11519
|
-
|
|
11525
|
+
validateResourceUrl(candidate, `<${tagName} ${attribute}>`, true, supportsOfficialResourceUrl(tagName, attribute));
|
|
11520
11526
|
}
|
|
11521
11527
|
}
|
|
11522
11528
|
else {
|
|
11523
|
-
|
|
11529
|
+
validateResourceUrl(value, `<${tagName} ${attribute}>`, true, supportsOfficialResourceUrl(tagName, attribute));
|
|
11524
11530
|
}
|
|
11525
11531
|
}
|
|
11526
11532
|
}
|
|
@@ -11535,16 +11541,43 @@ function removePlatformCspMarkers(node) {
|
|
|
11535
11541
|
for (const child of node.childNodes)
|
|
11536
11542
|
removePlatformCspMarkers(child);
|
|
11537
11543
|
}
|
|
11538
|
-
function
|
|
11544
|
+
function supportsOfficialResourceUrl(tagName, attribute) {
|
|
11545
|
+
return ((tagName === 'script' && attribute === 'src') ||
|
|
11546
|
+
(tagName === 'img' && attribute === 'src') ||
|
|
11547
|
+
(tagName === 'source' && (attribute === 'src' || attribute === 'srcset')) ||
|
|
11548
|
+
(tagName === 'audio' && attribute === 'src') ||
|
|
11549
|
+
(tagName === 'track' && attribute === 'src') ||
|
|
11550
|
+
(tagName === 'video' && (attribute === 'src' || attribute === 'poster')));
|
|
11551
|
+
}
|
|
11552
|
+
function validateResourceUrl(value, label, allowDataBlob, allowOfficialResourceUrl) {
|
|
11539
11553
|
if (!value || value.startsWith('#'))
|
|
11540
11554
|
return;
|
|
11541
11555
|
const normalized = value.trim().toLowerCase();
|
|
11542
11556
|
if (allowDataBlob && (normalized.startsWith('data:') || normalized.startsWith('blob:')))
|
|
11543
11557
|
return;
|
|
11558
|
+
if (allowOfficialResourceUrl && isOfficialResourceUrl(value))
|
|
11559
|
+
return;
|
|
11544
11560
|
if (!isRelativeUrl(value, normalized)) {
|
|
11545
11561
|
throw new Error(`${label} 必须使用相对路径${allowDataBlob ? '或明确的 data:/blob: URL' : ''}:${value}`);
|
|
11546
11562
|
}
|
|
11547
11563
|
}
|
|
11564
|
+
function validateRelativeUrl(value, label, allowDataBlob) {
|
|
11565
|
+
validateResourceUrl(value, label, allowDataBlob, false);
|
|
11566
|
+
}
|
|
11567
|
+
function isOfficialResourceUrl(value) {
|
|
11568
|
+
try {
|
|
11569
|
+
const url = new URL(value);
|
|
11570
|
+
if (url.protocol !== 'https:' || url.username || url.password)
|
|
11571
|
+
return false;
|
|
11572
|
+
const hostname = url.hostname.toLowerCase();
|
|
11573
|
+
if (hostname.endsWith('.'))
|
|
11574
|
+
return false;
|
|
11575
|
+
return OFFICIAL_RESOURCE_ROOT_DOMAINS.some(rootDomain => hostname === rootDomain || hostname.endsWith(`.${rootDomain}`));
|
|
11576
|
+
}
|
|
11577
|
+
catch {
|
|
11578
|
+
return false;
|
|
11579
|
+
}
|
|
11580
|
+
}
|
|
11548
11581
|
function isRelativeUrl(value, normalized) {
|
|
11549
11582
|
const browserNormalized = normalized.replace(/[\t\n\r]/g, '');
|
|
11550
11583
|
if (browserNormalized.includes('\\') || browserNormalized.startsWith('//'))
|
|
@@ -11581,19 +11614,9 @@ function walk(node, visit) {
|
|
|
11581
11614
|
walk(node.content, visit);
|
|
11582
11615
|
}
|
|
11583
11616
|
|
|
11584
|
-
const HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV = 'HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN';
|
|
11585
|
-
const HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV = 'HB_SDK_RUNTIME_PERMISSION_CONTEXT';
|
|
11586
|
-
const VERIFIED_RUNTIME_PERMISSION_CONTEXT = 'verified';
|
|
11587
|
-
new AsyncLocalStorage();
|
|
11588
|
-
Promise.resolve();
|
|
11589
|
-
function shouldSkipMiniappPlatformCspFromEnv(env = process.env) {
|
|
11590
|
-
return env[HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV] === VERIFIED_RUNTIME_PERMISSION_CONTEXT && env[HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV] === '1';
|
|
11591
|
-
}
|
|
11592
|
-
|
|
11593
11617
|
const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
|
|
11594
11618
|
const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
|
|
11595
11619
|
function miniappManifest() {
|
|
11596
|
-
const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
|
|
11597
11620
|
let root = process.cwd();
|
|
11598
11621
|
let outDir = 'dist';
|
|
11599
11622
|
let command = 'build';
|
|
@@ -11625,7 +11648,6 @@ function miniappManifest() {
|
|
|
11625
11648
|
transformIndexHtml(html) {
|
|
11626
11649
|
return enforceMiniappHtmlPolicy(html, {
|
|
11627
11650
|
...(command === 'serve' ? { hmrWebSocketUrl } : {}),
|
|
11628
|
-
skipPlatformCsp,
|
|
11629
11651
|
});
|
|
11630
11652
|
},
|
|
11631
11653
|
async closeBundle() {
|
|
@@ -11648,7 +11670,7 @@ function miniappManifest() {
|
|
|
11648
11670
|
if (!htmlFiles.includes(indexHtmlPath)) {
|
|
11649
11671
|
throw new Error('构建产物必须包含入口 dist/index.html');
|
|
11650
11672
|
}
|
|
11651
|
-
writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(readFileSync(indexHtmlPath, 'utf8')
|
|
11673
|
+
writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(readFileSync(indexHtmlPath, 'utf8')));
|
|
11652
11674
|
const manifestPath = path.join(outputRoot, 'manifest.json');
|
|
11653
11675
|
mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
11654
11676
|
writeFileSync(manifestPath, renderMiniappManifest({ version, sdkVersion }));
|
|
@@ -11690,7 +11712,7 @@ function resolveHmrWebSocketUrl(resolved) {
|
|
|
11690
11712
|
if (hmr === false)
|
|
11691
11713
|
return undefined;
|
|
11692
11714
|
const options = typeof hmr === 'object' ? hmr : {};
|
|
11693
|
-
const protocol = options.protocol ?? 'ws';
|
|
11715
|
+
const protocol = options.protocol ?? (resolved.server.https ? 'wss' : 'ws');
|
|
11694
11716
|
const configuredHost = options.host ?? resolved.server.host;
|
|
11695
11717
|
const host = typeof configuredHost === 'string' && configuredHost !== '0.0.0.0' ? configuredHost : '127.0.0.1';
|
|
11696
11718
|
const port = options.clientPort ?? options.port ?? resolved.server.port;
|