@heybox/hb-sdk 0.4.4 → 0.4.6
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 +78 -29
- package/dist/cli-chunks/{create-DAW1oAnH.cjs → create-BahMMgJH.cjs} +1 -1
- package/dist/cli-chunks/{dev-BA_4fnzO.cjs → dev-CTuXVPpU.cjs} +1 -1
- package/dist/cli-chunks/{doctor-Bbv8Lzu_.cjs → doctor-9gg3ZIvt.cjs} +1 -1
- package/dist/cli-chunks/{index-D7-awGYB.cjs → index-CLne_LW7.cjs} +3 -3
- package/dist/cli-chunks/{index-Bboot1us.cjs → index-DuwxUSkq.cjs} +181 -44
- package/dist/cli-chunks/{login-BQo2pIkq.cjs → login-OqaEx-Wd.cjs} +153 -2
- package/dist/cli-chunks/{deploy-BaLyuR1X.cjs → remote-zX17hOT4.cjs} +1008 -304
- package/dist/cli-chunks/{session-DiyDXvXu.cjs → session-D7lF9mpd.cjs} +347 -9
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/main.js +430 -391
- package/dist/miniapp-publish.cjs.js +30 -0
- package/dist/miniapp-publish.esm.js +16 -1
- package/dist/templates/vue3-vite-ts/README.md.ejs +1 -1
- package/dist/templates/vue3-vite-ts/package.json.ejs +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +25 -18
- package/skill/references/api-root.md +2 -2
- package/skill/references/cli.md +120 -350
- package/skill/scripts/sync-references.mjs +84 -5
- package/skill/skill.json +4 -4
- package/types/miniapp-publish/index.d.ts +15 -0
|
@@ -3303,65 +3303,6 @@ async function loginAndGetMiniProgramRuntimeUserInfo(platformAdapter) {
|
|
|
3303
3303
|
return getMiniProgramRuntimeUserInfo(platformAdapter);
|
|
3304
3304
|
}
|
|
3305
3305
|
|
|
3306
|
-
function getMiniProgramRuntimeWindowInfo(platformAdapter) {
|
|
3307
|
-
const metrics = platformAdapter.viewport.getViewportMetrics();
|
|
3308
|
-
const windowWidth = getViewportWidth(metrics);
|
|
3309
|
-
const windowHeight = getViewportHeight(metrics);
|
|
3310
|
-
const screenWidth = getPositiveNumber(metrics.screenWidth, windowWidth);
|
|
3311
|
-
const screenHeight = getPositiveNumber(metrics.screenHeight, windowHeight);
|
|
3312
|
-
const navigationBarHeight = getNavigationBarHeight(platformAdapter);
|
|
3313
|
-
const safeAreaHeight = Math.max(windowHeight - navigationBarHeight, 0);
|
|
3314
|
-
return {
|
|
3315
|
-
pixelRatio: getPositiveNumber(metrics.pixelRatio, 1),
|
|
3316
|
-
screenWidth,
|
|
3317
|
-
screenHeight,
|
|
3318
|
-
windowWidth,
|
|
3319
|
-
windowHeight,
|
|
3320
|
-
statusBarHeight: navigationBarHeight,
|
|
3321
|
-
safeArea: {
|
|
3322
|
-
left: 0,
|
|
3323
|
-
right: windowWidth,
|
|
3324
|
-
top: navigationBarHeight,
|
|
3325
|
-
bottom: windowHeight,
|
|
3326
|
-
width: windowWidth,
|
|
3327
|
-
height: safeAreaHeight,
|
|
3328
|
-
},
|
|
3329
|
-
screenTop: navigationBarHeight,
|
|
3330
|
-
};
|
|
3331
|
-
}
|
|
3332
|
-
function getMiniProgramRuntimeViewportRect(platformAdapter) {
|
|
3333
|
-
const metrics = platformAdapter.viewport.getViewportMetrics();
|
|
3334
|
-
const width = getPositiveNumber(metrics.innerWidth, getPositiveNumber(metrics.documentElementClientWidth, 0));
|
|
3335
|
-
const height = getPositiveNumber(metrics.innerHeight, getPositiveNumber(metrics.documentElementClientHeight, 0));
|
|
3336
|
-
return {
|
|
3337
|
-
left: 0,
|
|
3338
|
-
top: 0,
|
|
3339
|
-
width,
|
|
3340
|
-
height,
|
|
3341
|
-
};
|
|
3342
|
-
}
|
|
3343
|
-
function getNavigationBarHeight(platformAdapter) {
|
|
3344
|
-
try {
|
|
3345
|
-
return platformAdapter.viewport.getNavigationBarHeight();
|
|
3346
|
-
}
|
|
3347
|
-
catch {
|
|
3348
|
-
return 0;
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3351
|
-
function getViewportWidth(metrics) {
|
|
3352
|
-
return getPositiveNumber(metrics.innerWidth, getPositiveNumber(metrics.documentElementClientWidth, 0));
|
|
3353
|
-
}
|
|
3354
|
-
function getViewportHeight(metrics) {
|
|
3355
|
-
return getPositiveNumber(metrics.innerHeight, getPositiveNumber(metrics.documentElementClientHeight, 0));
|
|
3356
|
-
}
|
|
3357
|
-
function getPositiveNumber(value, fallback) {
|
|
3358
|
-
const numberValue = Number(value);
|
|
3359
|
-
if (!Number.isFinite(numberValue) || numberValue <= 0) {
|
|
3360
|
-
return fallback;
|
|
3361
|
-
}
|
|
3362
|
-
return numberValue;
|
|
3363
|
-
}
|
|
3364
|
-
|
|
3365
3306
|
const DEFAULT_STORAGE_KEY_MAX_LENGTH = 128;
|
|
3366
3307
|
const STORAGE_KEY_CHAR_RE = /^[A-Za-z0-9_-]+$/;
|
|
3367
3308
|
function createMiniProgramRuntimeBridgeError(code, message, data) {
|
|
@@ -3447,187 +3388,6 @@ function stringifyMiniProgramRuntimeJsonData(data, options) {
|
|
|
3447
3388
|
return value;
|
|
3448
3389
|
}
|
|
3449
3390
|
|
|
3450
|
-
/** 设置导航栏关闭按钮与状态栏图标/文字的前景样式。 */
|
|
3451
|
-
function setMiniProgramRuntimeNavigationBarStyle(payload, platformAdapter) {
|
|
3452
|
-
return platformAdapter.viewport.setNavigationBarStyle(readMiniProgramNavigationBarStyleOptions(payload));
|
|
3453
|
-
}
|
|
3454
|
-
function readMiniProgramNavigationBarStyleOptions(payload) {
|
|
3455
|
-
assertMiniProgramRuntimeRecord(payload, 'viewport.setNavigationBarStyle 参数必须是对象');
|
|
3456
|
-
const foregroundStyle = payload.foregroundStyle;
|
|
3457
|
-
if (!isNavigationBarForegroundStyle(foregroundStyle)) {
|
|
3458
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'viewport.setNavigationBarStyle foregroundStyle 必须是 light 或 dark');
|
|
3459
|
-
}
|
|
3460
|
-
return {
|
|
3461
|
-
foregroundStyle,
|
|
3462
|
-
};
|
|
3463
|
-
}
|
|
3464
|
-
function isNavigationBarForegroundStyle(value) {
|
|
3465
|
-
return value === 'light' || value === 'dark';
|
|
3466
|
-
}
|
|
3467
|
-
|
|
3468
|
-
/** 展示基础分享面板。 */
|
|
3469
|
-
function showMiniProgramRuntimeShareMenu(payload, platformAdapter) {
|
|
3470
|
-
return platformAdapter.share.showShareMenu(readMiniProgramShareMenuOptions(payload));
|
|
3471
|
-
}
|
|
3472
|
-
function readMiniProgramShareMenuOptions(payload) {
|
|
3473
|
-
assertMiniProgramRuntimeRecord(payload, 'share.showShareMenu 参数必须是对象');
|
|
3474
|
-
const title = readMiniProgramRuntimeRequiredString(payload.title, 'share.showShareMenu title 必须是非空字符串');
|
|
3475
|
-
const desc = readMiniProgramRuntimeRequiredString(payload.desc, 'share.showShareMenu desc 必须是非空字符串');
|
|
3476
|
-
const url = readMiniProgramRuntimeHttpUrl(payload.url, 'share.showShareMenu url 必须是 HTTP(S) URL');
|
|
3477
|
-
const imageUrl = payload.imageUrl === undefined
|
|
3478
|
-
? undefined
|
|
3479
|
-
: readMiniProgramRuntimeHttpUrl(payload.imageUrl, 'share.showShareMenu imageUrl 必须是 HTTP(S) URL');
|
|
3480
|
-
const channel = payload.channel;
|
|
3481
|
-
if (channel !== undefined && !isShareChannel(channel)) {
|
|
3482
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'share.showShareMenu channel 不合法');
|
|
3483
|
-
}
|
|
3484
|
-
return {
|
|
3485
|
-
title,
|
|
3486
|
-
desc,
|
|
3487
|
-
url,
|
|
3488
|
-
imageUrl,
|
|
3489
|
-
channel,
|
|
3490
|
-
};
|
|
3491
|
-
}
|
|
3492
|
-
function isShareChannel(value) {
|
|
3493
|
-
return (value === 'wechatSession' ||
|
|
3494
|
-
value === 'wechatTimeline' ||
|
|
3495
|
-
value === 'qqFriend' ||
|
|
3496
|
-
value === 'qzone' ||
|
|
3497
|
-
value === 'weibo');
|
|
3498
|
-
}
|
|
3499
|
-
|
|
3500
|
-
/** 截图并唤起分享。 */
|
|
3501
|
-
function shareMiniProgramRuntimeScreenshot(payload, platformAdapter) {
|
|
3502
|
-
const options = readMiniProgramScreenshotOptions(payload);
|
|
3503
|
-
const rect = options.rect || getMiniProgramRuntimeViewportRect(platformAdapter);
|
|
3504
|
-
return platformAdapter.share.shareScreenshot({
|
|
3505
|
-
rect,
|
|
3506
|
-
delay: options.delay,
|
|
3507
|
-
saveToAlbum: options.saveToAlbum,
|
|
3508
|
-
});
|
|
3509
|
-
}
|
|
3510
|
-
function readMiniProgramScreenshotOptions(payload) {
|
|
3511
|
-
if (payload === undefined || payload === null) {
|
|
3512
|
-
return {};
|
|
3513
|
-
}
|
|
3514
|
-
assertMiniProgramRuntimeRecord(payload, 'share.screenshot 参数必须是对象');
|
|
3515
|
-
const options = {};
|
|
3516
|
-
if (payload.rect !== undefined) {
|
|
3517
|
-
options.rect = readScreenshotRect(payload.rect);
|
|
3518
|
-
}
|
|
3519
|
-
if (payload.delay !== undefined) {
|
|
3520
|
-
options.delay = readMiniProgramRuntimeNonNegativeNumber(payload.delay, 'share.screenshot delay 必须是非负数字');
|
|
3521
|
-
}
|
|
3522
|
-
if (payload.saveToAlbum !== undefined) {
|
|
3523
|
-
options.saveToAlbum = readMiniProgramRuntimeBoolean(payload.saveToAlbum, 'share.screenshot saveToAlbum 必须是布尔值');
|
|
3524
|
-
}
|
|
3525
|
-
return options;
|
|
3526
|
-
}
|
|
3527
|
-
function readScreenshotRect(value) {
|
|
3528
|
-
assertMiniProgramRuntimeRecord(value, 'share.screenshot rect 必须是对象');
|
|
3529
|
-
const left = readMiniProgramRuntimeNonNegativeNumber(value.left, 'share.screenshot rect.left 必须是非负数字');
|
|
3530
|
-
const top = readMiniProgramRuntimeNonNegativeNumber(value.top, 'share.screenshot rect.top 必须是非负数字');
|
|
3531
|
-
const width = readMiniProgramRuntimePositiveNumber(value.width, 'share.screenshot rect.width 必须是正数');
|
|
3532
|
-
const height = readMiniProgramRuntimePositiveNumber(value.height, 'share.screenshot rect.height 必须是正数');
|
|
3533
|
-
return {
|
|
3534
|
-
left,
|
|
3535
|
-
top,
|
|
3536
|
-
width,
|
|
3537
|
-
height,
|
|
3538
|
-
};
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
/** 获取小程序隔离 storage。 */
|
|
3542
|
-
function getMiniProgramRuntimeStorage(payload, options, platformAdapter) {
|
|
3543
|
-
const { key } = readMiniProgramGetStoragePayload(payload, options.maxKeyLength);
|
|
3544
|
-
const storageValue = platformAdapter.storage.getStorage({
|
|
3545
|
-
key: createMiniProgramRuntimeStorageKey(key, options.scope || getMiniProgramRuntimeStorageScope(undefined, platformAdapter), options.maxKeyLength),
|
|
3546
|
-
});
|
|
3547
|
-
return {
|
|
3548
|
-
data: parseStorageData(storageValue),
|
|
3549
|
-
};
|
|
3550
|
-
}
|
|
3551
|
-
/** 写入小程序隔离 storage。 */
|
|
3552
|
-
async function setMiniProgramRuntimeStorage(payload, options, platformAdapter) {
|
|
3553
|
-
const { key, data } = readMiniProgramSetStoragePayload(payload, options.maxKeyLength);
|
|
3554
|
-
await platformAdapter.storage.setStorage({
|
|
3555
|
-
key: createMiniProgramRuntimeStorageKey(key, options.scope || getMiniProgramRuntimeStorageScope(undefined, platformAdapter), options.maxKeyLength),
|
|
3556
|
-
value: stringifyMiniProgramRuntimeJsonData(data, {
|
|
3557
|
-
invalidMessage: 'storage.setStorage data 必须可 JSON 序列化',
|
|
3558
|
-
maxValueBytes: options.maxValueBytes,
|
|
3559
|
-
}),
|
|
3560
|
-
});
|
|
3561
|
-
}
|
|
3562
|
-
/** 根据容器入口生成小程序 storage 隔离 scope。 */
|
|
3563
|
-
function getMiniProgramRuntimeStorageScope(href, platformAdapter) {
|
|
3564
|
-
const currentHref = platformAdapter?.app.getCurrentHref() ?? '';
|
|
3565
|
-
try {
|
|
3566
|
-
const url = new URL(currentHref);
|
|
3567
|
-
const miniProgramId = url.searchParams.get('mini_program_id')?.trim();
|
|
3568
|
-
if (miniProgramId) {
|
|
3569
|
-
return `id_${toStorageScopeToken(miniProgramId)}`;
|
|
3570
|
-
}
|
|
3571
|
-
const miniUrl = url.searchParams.get('mini_url')?.trim();
|
|
3572
|
-
if (miniUrl) {
|
|
3573
|
-
return `url_${hashString(miniUrl)}`;
|
|
3574
|
-
}
|
|
3575
|
-
return `url_${hashString(`${url.origin}${url.pathname}`)}`;
|
|
3576
|
-
}
|
|
3577
|
-
catch {
|
|
3578
|
-
return `url_${hashString(currentHref)}`;
|
|
3579
|
-
}
|
|
3580
|
-
}
|
|
3581
|
-
/** 生成真实写入黑盒客户端的 storage key。 */
|
|
3582
|
-
function createMiniProgramRuntimeStorageKey(key, storageScope, maxKeyLength) {
|
|
3583
|
-
readMiniProgramRuntimeStorageKey(key, 'storage.setStorage', maxKeyLength);
|
|
3584
|
-
return `hb_miniprogram_${storageScope}_${key}`;
|
|
3585
|
-
}
|
|
3586
|
-
function readMiniProgramGetStoragePayload(payload, maxKeyLength) {
|
|
3587
|
-
if (!isMiniProgramRuntimeRecord(payload)) {
|
|
3588
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'storage.getStorage 参数必须是对象');
|
|
3589
|
-
}
|
|
3590
|
-
const key = readMiniProgramRuntimeStorageKey(payload.key, 'storage.getStorage', maxKeyLength);
|
|
3591
|
-
return {
|
|
3592
|
-
key,
|
|
3593
|
-
};
|
|
3594
|
-
}
|
|
3595
|
-
function readMiniProgramSetStoragePayload(payload, maxKeyLength) {
|
|
3596
|
-
if (!isMiniProgramRuntimeRecord(payload)) {
|
|
3597
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'storage.setStorage 参数必须是对象');
|
|
3598
|
-
}
|
|
3599
|
-
const key = readMiniProgramRuntimeStorageKey(payload.key, 'storage.setStorage', maxKeyLength);
|
|
3600
|
-
return {
|
|
3601
|
-
key,
|
|
3602
|
-
data: payload.data,
|
|
3603
|
-
};
|
|
3604
|
-
}
|
|
3605
|
-
function parseStorageData(value) {
|
|
3606
|
-
if (value === undefined || value === null || value === '') {
|
|
3607
|
-
return undefined;
|
|
3608
|
-
}
|
|
3609
|
-
try {
|
|
3610
|
-
return JSON.parse(value);
|
|
3611
|
-
}
|
|
3612
|
-
catch {
|
|
3613
|
-
return value;
|
|
3614
|
-
}
|
|
3615
|
-
}
|
|
3616
|
-
function toStorageScopeToken(value) {
|
|
3617
|
-
if (/^[A-Za-z0-9_-]{1,64}$/.test(value)) {
|
|
3618
|
-
return value;
|
|
3619
|
-
}
|
|
3620
|
-
return hashString(value);
|
|
3621
|
-
}
|
|
3622
|
-
function hashString(value) {
|
|
3623
|
-
let hash = 2166136261;
|
|
3624
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
3625
|
-
hash ^= value.charCodeAt(index);
|
|
3626
|
-
hash = Math.imul(hash, 16777619);
|
|
3627
|
-
}
|
|
3628
|
-
return (hash >>> 0).toString(36);
|
|
3629
|
-
}
|
|
3630
|
-
|
|
3631
3391
|
const NETWORK_REQUEST_ALLOWED_KEYS = new Set([
|
|
3632
3392
|
'url',
|
|
3633
3393
|
'method',
|
|
@@ -3769,69 +3529,309 @@ function isDeniedNetworkRequestHeader(headerName) {
|
|
|
3769
3529
|
normalizedHeaderName.startsWith('x-heybox-') ||
|
|
3770
3530
|
normalizedHeaderName.startsWith('x-xhh-'));
|
|
3771
3531
|
}
|
|
3772
|
-
function assertNetworkRequestBody(data) {
|
|
3773
|
-
if (isUnsupportedNetworkRequestBody(data)) {
|
|
3774
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request data 不支持 File、Blob 或 FormData,请使用专用上传能力');
|
|
3532
|
+
function assertNetworkRequestBody(data) {
|
|
3533
|
+
if (isUnsupportedNetworkRequestBody(data)) {
|
|
3534
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request data 不支持 File、Blob 或 FormData,请使用专用上传能力');
|
|
3535
|
+
}
|
|
3536
|
+
const bodyBytes = estimateNetworkRequestBodyBytes(data);
|
|
3537
|
+
if (bodyBytes > NETWORK_REQUEST_MAX_BODY_BYTES) {
|
|
3538
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', `network.request data 不能超过 ${NETWORK_REQUEST_MAX_BODY_BYTES} 字节`);
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
function isUnsupportedNetworkRequestBody(data) {
|
|
3542
|
+
return ((typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
3543
|
+
(typeof FormData !== 'undefined' && data instanceof FormData));
|
|
3544
|
+
}
|
|
3545
|
+
function estimateNetworkRequestBodyBytes(data) {
|
|
3546
|
+
if (typeof data === 'string') {
|
|
3547
|
+
return getMiniProgramRuntimeUtf8ByteLength(data);
|
|
3548
|
+
}
|
|
3549
|
+
if (data instanceof ArrayBuffer) {
|
|
3550
|
+
return data.byteLength;
|
|
3551
|
+
}
|
|
3552
|
+
if (ArrayBuffer.isView(data)) {
|
|
3553
|
+
return data.byteLength;
|
|
3554
|
+
}
|
|
3555
|
+
if (typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams) {
|
|
3556
|
+
return getMiniProgramRuntimeUtf8ByteLength(data.toString());
|
|
3557
|
+
}
|
|
3558
|
+
try {
|
|
3559
|
+
const serialized = JSON.stringify(data);
|
|
3560
|
+
return serialized ? getMiniProgramRuntimeUtf8ByteLength(serialized) : 0;
|
|
3561
|
+
}
|
|
3562
|
+
catch {
|
|
3563
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request data 必须可序列化');
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
function readNetworkMethod(value) {
|
|
3567
|
+
const method = readMiniProgramRuntimeRequiredString(value, 'network.request method 必须是字符串').trim().toUpperCase();
|
|
3568
|
+
if (!NETWORK_HTTP_METHODS.has(method)) {
|
|
3569
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request method 不合法');
|
|
3570
|
+
}
|
|
3571
|
+
return method;
|
|
3572
|
+
}
|
|
3573
|
+
function readUnknownRecord(value, message) {
|
|
3574
|
+
assertMiniProgramRuntimeRecord(value, message);
|
|
3575
|
+
return { ...value };
|
|
3576
|
+
}
|
|
3577
|
+
function readStringRecord(value, message) {
|
|
3578
|
+
assertMiniProgramRuntimeRecord(value, message);
|
|
3579
|
+
return Object.entries(value).reduce((headers, [key, headerValue]) => {
|
|
3580
|
+
if (!key.trim() || typeof headerValue !== 'string') {
|
|
3581
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', message);
|
|
3582
|
+
}
|
|
3583
|
+
headers[key] = headerValue;
|
|
3584
|
+
return headers;
|
|
3585
|
+
}, {});
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3588
|
+
function getMiniProgramRuntimeWindowInfo(platformAdapter) {
|
|
3589
|
+
const metrics = platformAdapter.viewport.getViewportMetrics();
|
|
3590
|
+
const windowWidth = getViewportWidth(metrics);
|
|
3591
|
+
const windowHeight = getViewportHeight(metrics);
|
|
3592
|
+
const screenWidth = getPositiveNumber(metrics.screenWidth, windowWidth);
|
|
3593
|
+
const screenHeight = getPositiveNumber(metrics.screenHeight, windowHeight);
|
|
3594
|
+
const navigationBarHeight = getNavigationBarHeight(platformAdapter);
|
|
3595
|
+
const safeAreaHeight = Math.max(windowHeight - navigationBarHeight, 0);
|
|
3596
|
+
return {
|
|
3597
|
+
pixelRatio: getPositiveNumber(metrics.pixelRatio, 1),
|
|
3598
|
+
screenWidth,
|
|
3599
|
+
screenHeight,
|
|
3600
|
+
windowWidth,
|
|
3601
|
+
windowHeight,
|
|
3602
|
+
statusBarHeight: navigationBarHeight,
|
|
3603
|
+
safeArea: {
|
|
3604
|
+
left: 0,
|
|
3605
|
+
right: windowWidth,
|
|
3606
|
+
top: navigationBarHeight,
|
|
3607
|
+
bottom: windowHeight,
|
|
3608
|
+
width: windowWidth,
|
|
3609
|
+
height: safeAreaHeight,
|
|
3610
|
+
},
|
|
3611
|
+
screenTop: navigationBarHeight,
|
|
3612
|
+
};
|
|
3613
|
+
}
|
|
3614
|
+
function getMiniProgramRuntimeViewportRect(platformAdapter) {
|
|
3615
|
+
const metrics = platformAdapter.viewport.getViewportMetrics();
|
|
3616
|
+
const width = getPositiveNumber(metrics.innerWidth, getPositiveNumber(metrics.documentElementClientWidth, 0));
|
|
3617
|
+
const height = getPositiveNumber(metrics.innerHeight, getPositiveNumber(metrics.documentElementClientHeight, 0));
|
|
3618
|
+
return {
|
|
3619
|
+
left: 0,
|
|
3620
|
+
top: 0,
|
|
3621
|
+
width,
|
|
3622
|
+
height,
|
|
3623
|
+
};
|
|
3624
|
+
}
|
|
3625
|
+
function getNavigationBarHeight(platformAdapter) {
|
|
3626
|
+
try {
|
|
3627
|
+
return platformAdapter.viewport.getNavigationBarHeight();
|
|
3628
|
+
}
|
|
3629
|
+
catch {
|
|
3630
|
+
return 0;
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
function getViewportWidth(metrics) {
|
|
3634
|
+
return getPositiveNumber(metrics.innerWidth, getPositiveNumber(metrics.documentElementClientWidth, 0));
|
|
3635
|
+
}
|
|
3636
|
+
function getViewportHeight(metrics) {
|
|
3637
|
+
return getPositiveNumber(metrics.innerHeight, getPositiveNumber(metrics.documentElementClientHeight, 0));
|
|
3638
|
+
}
|
|
3639
|
+
function getPositiveNumber(value, fallback) {
|
|
3640
|
+
const numberValue = Number(value);
|
|
3641
|
+
if (!Number.isFinite(numberValue) || numberValue <= 0) {
|
|
3642
|
+
return fallback;
|
|
3643
|
+
}
|
|
3644
|
+
return numberValue;
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3647
|
+
/** 截图并唤起分享。 */
|
|
3648
|
+
function shareMiniProgramRuntimeScreenshot(payload, platformAdapter) {
|
|
3649
|
+
const options = readMiniProgramScreenshotOptions(payload);
|
|
3650
|
+
const rect = options.rect || getMiniProgramRuntimeViewportRect(platformAdapter);
|
|
3651
|
+
return platformAdapter.share.shareScreenshot({
|
|
3652
|
+
rect,
|
|
3653
|
+
delay: options.delay,
|
|
3654
|
+
saveToAlbum: options.saveToAlbum,
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
3657
|
+
function readMiniProgramScreenshotOptions(payload) {
|
|
3658
|
+
if (payload === undefined || payload === null) {
|
|
3659
|
+
return {};
|
|
3660
|
+
}
|
|
3661
|
+
assertMiniProgramRuntimeRecord(payload, 'share.screenshot 参数必须是对象');
|
|
3662
|
+
const options = {};
|
|
3663
|
+
if (payload.rect !== undefined) {
|
|
3664
|
+
options.rect = readScreenshotRect(payload.rect);
|
|
3665
|
+
}
|
|
3666
|
+
if (payload.delay !== undefined) {
|
|
3667
|
+
options.delay = readMiniProgramRuntimeNonNegativeNumber(payload.delay, 'share.screenshot delay 必须是非负数字');
|
|
3668
|
+
}
|
|
3669
|
+
if (payload.saveToAlbum !== undefined) {
|
|
3670
|
+
options.saveToAlbum = readMiniProgramRuntimeBoolean(payload.saveToAlbum, 'share.screenshot saveToAlbum 必须是布尔值');
|
|
3671
|
+
}
|
|
3672
|
+
return options;
|
|
3673
|
+
}
|
|
3674
|
+
function readScreenshotRect(value) {
|
|
3675
|
+
assertMiniProgramRuntimeRecord(value, 'share.screenshot rect 必须是对象');
|
|
3676
|
+
const left = readMiniProgramRuntimeNonNegativeNumber(value.left, 'share.screenshot rect.left 必须是非负数字');
|
|
3677
|
+
const top = readMiniProgramRuntimeNonNegativeNumber(value.top, 'share.screenshot rect.top 必须是非负数字');
|
|
3678
|
+
const width = readMiniProgramRuntimePositiveNumber(value.width, 'share.screenshot rect.width 必须是正数');
|
|
3679
|
+
const height = readMiniProgramRuntimePositiveNumber(value.height, 'share.screenshot rect.height 必须是正数');
|
|
3680
|
+
return {
|
|
3681
|
+
left,
|
|
3682
|
+
top,
|
|
3683
|
+
width,
|
|
3684
|
+
height,
|
|
3685
|
+
};
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
/** 展示基础分享面板。 */
|
|
3689
|
+
function showMiniProgramRuntimeShareMenu(payload, platformAdapter) {
|
|
3690
|
+
return platformAdapter.share.showShareMenu(readMiniProgramShareMenuOptions(payload));
|
|
3691
|
+
}
|
|
3692
|
+
function readMiniProgramShareMenuOptions(payload) {
|
|
3693
|
+
assertMiniProgramRuntimeRecord(payload, 'share.showShareMenu 参数必须是对象');
|
|
3694
|
+
const title = readMiniProgramRuntimeRequiredString(payload.title, 'share.showShareMenu title 必须是非空字符串');
|
|
3695
|
+
const desc = readMiniProgramRuntimeRequiredString(payload.desc, 'share.showShareMenu desc 必须是非空字符串');
|
|
3696
|
+
const url = readMiniProgramRuntimeHttpUrl(payload.url, 'share.showShareMenu url 必须是 HTTP(S) URL');
|
|
3697
|
+
const imageUrl = payload.imageUrl === undefined
|
|
3698
|
+
? undefined
|
|
3699
|
+
: readMiniProgramRuntimeHttpUrl(payload.imageUrl, 'share.showShareMenu imageUrl 必须是 HTTP(S) URL');
|
|
3700
|
+
const channel = payload.channel;
|
|
3701
|
+
if (channel !== undefined && !isShareChannel(channel)) {
|
|
3702
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'share.showShareMenu channel 不合法');
|
|
3703
|
+
}
|
|
3704
|
+
return {
|
|
3705
|
+
title,
|
|
3706
|
+
desc,
|
|
3707
|
+
url,
|
|
3708
|
+
imageUrl,
|
|
3709
|
+
channel,
|
|
3710
|
+
};
|
|
3711
|
+
}
|
|
3712
|
+
function isShareChannel(value) {
|
|
3713
|
+
return (value === 'wechatSession' ||
|
|
3714
|
+
value === 'wechatTimeline' ||
|
|
3715
|
+
value === 'qqFriend' ||
|
|
3716
|
+
value === 'qzone' ||
|
|
3717
|
+
value === 'weibo');
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
/** 获取小程序隔离 storage。 */
|
|
3721
|
+
function getMiniProgramRuntimeStorage(payload, options, platformAdapter) {
|
|
3722
|
+
const { key } = readMiniProgramGetStoragePayload(payload, options.maxKeyLength);
|
|
3723
|
+
const storageValue = platformAdapter.storage.getStorage({
|
|
3724
|
+
key: createMiniProgramRuntimeStorageKey(key, options.scope || getMiniProgramRuntimeStorageScope(undefined, platformAdapter), options.maxKeyLength),
|
|
3725
|
+
});
|
|
3726
|
+
return {
|
|
3727
|
+
data: parseStorageData(storageValue),
|
|
3728
|
+
};
|
|
3729
|
+
}
|
|
3730
|
+
/** 写入小程序隔离 storage。 */
|
|
3731
|
+
async function setMiniProgramRuntimeStorage(payload, options, platformAdapter) {
|
|
3732
|
+
const { key, data } = readMiniProgramSetStoragePayload(payload, options.maxKeyLength);
|
|
3733
|
+
await platformAdapter.storage.setStorage({
|
|
3734
|
+
key: createMiniProgramRuntimeStorageKey(key, options.scope || getMiniProgramRuntimeStorageScope(undefined, platformAdapter), options.maxKeyLength),
|
|
3735
|
+
value: stringifyMiniProgramRuntimeJsonData(data, {
|
|
3736
|
+
invalidMessage: 'storage.setStorage data 必须可 JSON 序列化',
|
|
3737
|
+
maxValueBytes: options.maxValueBytes,
|
|
3738
|
+
}),
|
|
3739
|
+
});
|
|
3740
|
+
}
|
|
3741
|
+
/** 根据容器入口生成小程序 storage 隔离 scope。 */
|
|
3742
|
+
function getMiniProgramRuntimeStorageScope(href, platformAdapter) {
|
|
3743
|
+
const currentHref = platformAdapter?.app.getCurrentHref() ?? '';
|
|
3744
|
+
try {
|
|
3745
|
+
const url = new URL(currentHref);
|
|
3746
|
+
const miniProgramId = url.searchParams.get('mini_program_id')?.trim();
|
|
3747
|
+
if (miniProgramId) {
|
|
3748
|
+
return `id_${toStorageScopeToken(miniProgramId)}`;
|
|
3749
|
+
}
|
|
3750
|
+
const miniUrl = url.searchParams.get('mini_url')?.trim();
|
|
3751
|
+
if (miniUrl) {
|
|
3752
|
+
return `url_${hashString(miniUrl)}`;
|
|
3753
|
+
}
|
|
3754
|
+
return `url_${hashString(`${url.origin}${url.pathname}`)}`;
|
|
3775
3755
|
}
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', `network.request data 不能超过 ${NETWORK_REQUEST_MAX_BODY_BYTES} 字节`);
|
|
3756
|
+
catch {
|
|
3757
|
+
return `url_${hashString(currentHref)}`;
|
|
3779
3758
|
}
|
|
3780
3759
|
}
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3760
|
+
/** 生成真实写入黑盒客户端的 storage key。 */
|
|
3761
|
+
function createMiniProgramRuntimeStorageKey(key, storageScope, maxKeyLength) {
|
|
3762
|
+
readMiniProgramRuntimeStorageKey(key, 'storage.setStorage', maxKeyLength);
|
|
3763
|
+
return `hb_miniprogram_${storageScope}_${key}`;
|
|
3784
3764
|
}
|
|
3785
|
-
function
|
|
3786
|
-
if (
|
|
3787
|
-
|
|
3788
|
-
}
|
|
3789
|
-
if (data instanceof ArrayBuffer) {
|
|
3790
|
-
return data.byteLength;
|
|
3765
|
+
function readMiniProgramGetStoragePayload(payload, maxKeyLength) {
|
|
3766
|
+
if (!isMiniProgramRuntimeRecord(payload)) {
|
|
3767
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'storage.getStorage 参数必须是对象');
|
|
3791
3768
|
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3769
|
+
const key = readMiniProgramRuntimeStorageKey(payload.key, 'storage.getStorage', maxKeyLength);
|
|
3770
|
+
return {
|
|
3771
|
+
key,
|
|
3772
|
+
};
|
|
3773
|
+
}
|
|
3774
|
+
function readMiniProgramSetStoragePayload(payload, maxKeyLength) {
|
|
3775
|
+
if (!isMiniProgramRuntimeRecord(payload)) {
|
|
3776
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'storage.setStorage 参数必须是对象');
|
|
3794
3777
|
}
|
|
3795
|
-
|
|
3796
|
-
|
|
3778
|
+
const key = readMiniProgramRuntimeStorageKey(payload.key, 'storage.setStorage', maxKeyLength);
|
|
3779
|
+
return {
|
|
3780
|
+
key,
|
|
3781
|
+
data: payload.data,
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
function parseStorageData(value) {
|
|
3785
|
+
if (value === undefined || value === null || value === '') {
|
|
3786
|
+
return undefined;
|
|
3797
3787
|
}
|
|
3798
3788
|
try {
|
|
3799
|
-
|
|
3800
|
-
return serialized ? getMiniProgramRuntimeUtf8ByteLength(serialized) : 0;
|
|
3789
|
+
return JSON.parse(value);
|
|
3801
3790
|
}
|
|
3802
3791
|
catch {
|
|
3803
|
-
|
|
3792
|
+
return value;
|
|
3804
3793
|
}
|
|
3805
3794
|
}
|
|
3806
|
-
function
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request method 不合法');
|
|
3795
|
+
function toStorageScopeToken(value) {
|
|
3796
|
+
if (/^[A-Za-z0-9_-]{1,64}$/.test(value)) {
|
|
3797
|
+
return value;
|
|
3810
3798
|
}
|
|
3811
|
-
return
|
|
3799
|
+
return hashString(value);
|
|
3812
3800
|
}
|
|
3813
|
-
function
|
|
3814
|
-
|
|
3815
|
-
|
|
3801
|
+
function hashString(value) {
|
|
3802
|
+
let hash = 2166136261;
|
|
3803
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
3804
|
+
hash ^= value.charCodeAt(index);
|
|
3805
|
+
hash = Math.imul(hash, 16777619);
|
|
3806
|
+
}
|
|
3807
|
+
return (hash >>> 0).toString(36);
|
|
3816
3808
|
}
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3809
|
+
|
|
3810
|
+
/** 设置导航栏关闭按钮与状态栏图标/文字的前景样式。 */
|
|
3811
|
+
function setMiniProgramRuntimeNavigationBarStyle(payload, platformAdapter) {
|
|
3812
|
+
return platformAdapter.viewport.setNavigationBarStyle(readMiniProgramNavigationBarStyleOptions(payload));
|
|
3813
|
+
}
|
|
3814
|
+
function readMiniProgramNavigationBarStyleOptions(payload) {
|
|
3815
|
+
assertMiniProgramRuntimeRecord(payload, 'viewport.setNavigationBarStyle 参数必须是对象');
|
|
3816
|
+
const foregroundStyle = payload.foregroundStyle;
|
|
3817
|
+
if (!isNavigationBarForegroundStyle(foregroundStyle)) {
|
|
3818
|
+
throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'viewport.setNavigationBarStyle foregroundStyle 必须是 light 或 dark');
|
|
3819
|
+
}
|
|
3820
|
+
return {
|
|
3821
|
+
foregroundStyle,
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
function isNavigationBarForegroundStyle(value) {
|
|
3825
|
+
return value === 'light' || value === 'dark';
|
|
3826
3826
|
}
|
|
3827
3827
|
|
|
3828
|
-
const MINI_PROGRAM_MOCK_RUNTIME_METHODS = MINI_PROGRAM_PROTOCOL_CAPABILITIES.map(capability => capability.method);
|
|
3828
|
+
const MINI_PROGRAM_MOCK_RUNTIME_METHODS = MINI_PROGRAM_PROTOCOL_CAPABILITIES.map((capability) => capability.method);
|
|
3829
3829
|
const MINI_PROGRAM_MOCK_RUNTIME_METHOD_HANDLERS = {
|
|
3830
|
-
[AUTH_LOGIN_METHOD]: runtime => runtime.login(),
|
|
3831
|
-
[USER_GET_INFO_METHOD]: runtime => runtime.getUserInfo(),
|
|
3830
|
+
[AUTH_LOGIN_METHOD]: (runtime) => runtime.login(),
|
|
3831
|
+
[USER_GET_INFO_METHOD]: (runtime) => runtime.getUserInfo(),
|
|
3832
3832
|
[SHARE_SHOW_SHARE_MENU_METHOD]: (runtime, payload) => runtime.showShareMenu(payload),
|
|
3833
3833
|
[SHARE_SCREENSHOT_METHOD]: (runtime, payload) => runtime.shareScreenshot(payload),
|
|
3834
|
-
[VIEWPORT_GET_WINDOW_INFO_METHOD]: runtime => runtime.getWindowInfo(),
|
|
3834
|
+
[VIEWPORT_GET_WINDOW_INFO_METHOD]: (runtime) => runtime.getWindowInfo(),
|
|
3835
3835
|
[VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD]: (runtime, payload) => runtime.setNavigationBarStyle(payload),
|
|
3836
3836
|
[STORAGE_GET_STORAGE_METHOD]: (runtime, payload) => runtime.getStorage(payload),
|
|
3837
3837
|
[STORAGE_SET_STORAGE_METHOD]: (runtime, payload) => runtime.setStorage(payload),
|
|
@@ -3844,6 +3844,118 @@ const MINI_PROGRAM_MOCK_RUNTIME_METHOD_HANDLERS = {
|
|
|
3844
3844
|
[NAVIGATION_CLOSE_METHOD]: (runtime, payload) => runtime.close(payload),
|
|
3845
3845
|
[NAVIGATION_RELOAD_METHOD]: (runtime, payload) => runtime.reload(payload),
|
|
3846
3846
|
};
|
|
3847
|
+
function createBrowserMockRuntimePlatformAdapter(options) {
|
|
3848
|
+
return {
|
|
3849
|
+
app: {
|
|
3850
|
+
getCurrentHref: options.getCurrentHref,
|
|
3851
|
+
},
|
|
3852
|
+
launch: {
|
|
3853
|
+
async getMiniProgramInfo() {
|
|
3854
|
+
return {
|
|
3855
|
+
pageUrl: options.getMiniProgramPageUrl(),
|
|
3856
|
+
};
|
|
3857
|
+
},
|
|
3858
|
+
},
|
|
3859
|
+
auth: {
|
|
3860
|
+
async getCurrentUserId() {
|
|
3861
|
+
return options.getCurrentUser()?.heybox_id;
|
|
3862
|
+
},
|
|
3863
|
+
async login() {
|
|
3864
|
+
await options.login();
|
|
3865
|
+
},
|
|
3866
|
+
},
|
|
3867
|
+
user: {
|
|
3868
|
+
async getUserBasicInfo(userId) {
|
|
3869
|
+
const currentUser = options.getCurrentUser();
|
|
3870
|
+
if (!currentUser || currentUser.heybox_id !== userId) {
|
|
3871
|
+
return undefined;
|
|
3872
|
+
}
|
|
3873
|
+
return {
|
|
3874
|
+
nickname: currentUser.nickname,
|
|
3875
|
+
avatar: currentUser.avatar,
|
|
3876
|
+
};
|
|
3877
|
+
},
|
|
3878
|
+
},
|
|
3879
|
+
share: {
|
|
3880
|
+
async showShareMenu(params) {
|
|
3881
|
+
return {
|
|
3882
|
+
ok: true,
|
|
3883
|
+
platform: 'hb-sdk-mock-host',
|
|
3884
|
+
type: 'showShareMenu',
|
|
3885
|
+
params,
|
|
3886
|
+
};
|
|
3887
|
+
},
|
|
3888
|
+
async shareScreenshot(params) {
|
|
3889
|
+
return {
|
|
3890
|
+
ok: true,
|
|
3891
|
+
platform: 'hb-sdk-mock-host',
|
|
3892
|
+
type: 'screenshot',
|
|
3893
|
+
params,
|
|
3894
|
+
};
|
|
3895
|
+
},
|
|
3896
|
+
},
|
|
3897
|
+
viewport: {
|
|
3898
|
+
setDocumentTitle(title) {
|
|
3899
|
+
options.setDocumentTitle?.(title);
|
|
3900
|
+
},
|
|
3901
|
+
setNavigationBarStyle(styleOptions) {
|
|
3902
|
+
return options.setNavigationBarStyle?.(styleOptions);
|
|
3903
|
+
},
|
|
3904
|
+
getViewportMetrics() {
|
|
3905
|
+
const rect = options.iframe.getBoundingClientRect();
|
|
3906
|
+
const width = Math.max(1, Math.round(rect.width));
|
|
3907
|
+
const height = Math.max(1, Math.round(rect.height));
|
|
3908
|
+
const currentWindow = options.iframe.ownerDocument.defaultView ?? readWindow();
|
|
3909
|
+
return {
|
|
3910
|
+
innerWidth: width,
|
|
3911
|
+
innerHeight: height,
|
|
3912
|
+
documentElementClientWidth: width,
|
|
3913
|
+
documentElementClientHeight: height,
|
|
3914
|
+
screenWidth: currentWindow?.screen.width || width,
|
|
3915
|
+
screenHeight: currentWindow?.screen.height || height,
|
|
3916
|
+
pixelRatio: currentWindow?.devicePixelRatio || 1,
|
|
3917
|
+
};
|
|
3918
|
+
},
|
|
3919
|
+
getNavigationBarHeight() {
|
|
3920
|
+
return 0;
|
|
3921
|
+
},
|
|
3922
|
+
},
|
|
3923
|
+
ui: {
|
|
3924
|
+
async showToast() {
|
|
3925
|
+
return undefined;
|
|
3926
|
+
},
|
|
3927
|
+
async showLoading() {
|
|
3928
|
+
return undefined;
|
|
3929
|
+
},
|
|
3930
|
+
async hideLoading() {
|
|
3931
|
+
return undefined;
|
|
3932
|
+
},
|
|
3933
|
+
},
|
|
3934
|
+
device: {
|
|
3935
|
+
async vibrate() {
|
|
3936
|
+
return undefined;
|
|
3937
|
+
},
|
|
3938
|
+
async setClipboard() {
|
|
3939
|
+
return undefined;
|
|
3940
|
+
},
|
|
3941
|
+
},
|
|
3942
|
+
navigation: {
|
|
3943
|
+
async close() {
|
|
3944
|
+
return undefined;
|
|
3945
|
+
},
|
|
3946
|
+
async reload() {
|
|
3947
|
+
return undefined;
|
|
3948
|
+
},
|
|
3949
|
+
},
|
|
3950
|
+
storage: {
|
|
3951
|
+
getStorage: options.getStorage,
|
|
3952
|
+
setStorage: options.setStorage,
|
|
3953
|
+
},
|
|
3954
|
+
network: {
|
|
3955
|
+
request: options.requestNetwork,
|
|
3956
|
+
},
|
|
3957
|
+
};
|
|
3958
|
+
}
|
|
3847
3959
|
class MiniProgramMockRuntime {
|
|
3848
3960
|
constructor(adapter, options = {}) {
|
|
3849
3961
|
this.adapter = adapter;
|
|
@@ -4064,10 +4176,11 @@ function readVibratePayload(payload) {
|
|
|
4064
4176
|
if (intensity !== 'light' && intensity !== 'medium' && intensity !== 'heavy') {
|
|
4065
4177
|
throw createMockBridgeError('INVALID_PARAMS', 'device.vibrate intensity 必须是 light、medium 或 heavy');
|
|
4066
4178
|
}
|
|
4067
|
-
const
|
|
4068
|
-
if (!Number.isInteger(
|
|
4179
|
+
const rawDelay = payload?.delay;
|
|
4180
|
+
if (rawDelay !== undefined && (typeof rawDelay !== 'number' || !Number.isInteger(rawDelay) || rawDelay < 0 || rawDelay > 5000)) {
|
|
4069
4181
|
throw createMockBridgeError('INVALID_PARAMS', 'device.vibrate delay 必须是 0..5000 的整数毫秒');
|
|
4070
4182
|
}
|
|
4183
|
+
const delay = rawDelay ?? 0;
|
|
4071
4184
|
return {
|
|
4072
4185
|
delay,
|
|
4073
4186
|
intensity,
|
|
@@ -4079,7 +4192,7 @@ function readSetClipboardPayload(payload) {
|
|
|
4079
4192
|
if (!isPlainRecord(payload)) {
|
|
4080
4193
|
throw createMockBridgeError('INVALID_PARAMS', 'device.setClipboard options 必须是对象');
|
|
4081
4194
|
}
|
|
4082
|
-
const extraKeys = Object.keys(payload).filter(key => key !== 'text');
|
|
4195
|
+
const extraKeys = Object.keys(payload).filter((key) => key !== 'text');
|
|
4083
4196
|
if (extraKeys.length > 0) {
|
|
4084
4197
|
throw createMockBridgeError('INVALID_PARAMS', `device.setClipboard 不支持字段: ${extraKeys.join(', ')}`);
|
|
4085
4198
|
}
|
|
@@ -4103,7 +4216,7 @@ function assertEmptyPayload(payload, methodName) {
|
|
|
4103
4216
|
}
|
|
4104
4217
|
}
|
|
4105
4218
|
function assertOnlyAllowedKeys(payload, allowedKeys, methodName) {
|
|
4106
|
-
const invalidKeys = Object.keys(payload).filter(key => !allowedKeys.has(key));
|
|
4219
|
+
const invalidKeys = Object.keys(payload).filter((key) => !allowedKeys.has(key));
|
|
4107
4220
|
if (invalidKeys.length > 0) {
|
|
4108
4221
|
throw createMockBridgeError('INVALID_PARAMS', `${methodName} 不支持字段: ${invalidKeys.join(', ')}`);
|
|
4109
4222
|
}
|
|
@@ -4216,6 +4329,9 @@ function findOrCreateMockElement(document, id) {
|
|
|
4216
4329
|
function readDocument() {
|
|
4217
4330
|
return typeof document === 'undefined' ? null : document;
|
|
4218
4331
|
}
|
|
4332
|
+
function readWindow() {
|
|
4333
|
+
return typeof window === 'undefined' ? undefined : window;
|
|
4334
|
+
}
|
|
4219
4335
|
function isPlainRecord(value) {
|
|
4220
4336
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
4221
4337
|
}
|
|
@@ -4267,8 +4383,30 @@ iframe.src = appendNonce(miniProgramUrl, nonce);
|
|
|
4267
4383
|
iframe.allow = 'clipboard-read; clipboard-write';
|
|
4268
4384
|
elements.device.appendChild(iframe);
|
|
4269
4385
|
elements.miniUrl.textContent = miniProgramUrl;
|
|
4270
|
-
const runtime = new MiniProgramMockRuntime(
|
|
4271
|
-
|
|
4386
|
+
const runtime = new MiniProgramMockRuntime(createBrowserMockRuntimePlatformAdapter({
|
|
4387
|
+
iframe,
|
|
4388
|
+
getCurrentHref: () => location.href,
|
|
4389
|
+
getCurrentUser: () => currentUser,
|
|
4390
|
+
getMiniProgramPageUrl: () => miniProgramUrl,
|
|
4391
|
+
getStorage: ({ key }) => storage.get(key),
|
|
4392
|
+
async login() {
|
|
4393
|
+
currentUser = createUserFromForm();
|
|
4394
|
+
updateUserStatus();
|
|
4395
|
+
},
|
|
4396
|
+
requestNetwork,
|
|
4397
|
+
setDocumentTitle(title) {
|
|
4398
|
+
document.title = title;
|
|
4399
|
+
},
|
|
4400
|
+
setNavigationBarStyle(options) {
|
|
4401
|
+
navigationBarStyle = options.foregroundStyle;
|
|
4402
|
+
document.documentElement.dataset.navigationBarStyle = navigationBarStyle;
|
|
4403
|
+
},
|
|
4404
|
+
async setStorage({ key, value }) {
|
|
4405
|
+
storage.set(key, value);
|
|
4406
|
+
updateStorageSnapshot();
|
|
4407
|
+
},
|
|
4408
|
+
}), {
|
|
4409
|
+
onAuthChange: (result) => postEvent('authChange', result),
|
|
4272
4410
|
});
|
|
4273
4411
|
updateUserStatus();
|
|
4274
4412
|
updateStorageSnapshot();
|
|
@@ -4300,98 +4438,6 @@ elements.mobileLanSelect.addEventListener('change', () => {
|
|
|
4300
4438
|
void updateMobileQrCode();
|
|
4301
4439
|
});
|
|
4302
4440
|
const mobileAppQrReady = setupMobileAppQr();
|
|
4303
|
-
function createBrowserMockRuntimeAdapter() {
|
|
4304
|
-
return {
|
|
4305
|
-
app: {
|
|
4306
|
-
getCurrentHref() {
|
|
4307
|
-
return location.href;
|
|
4308
|
-
},
|
|
4309
|
-
},
|
|
4310
|
-
launch: {
|
|
4311
|
-
async getMiniProgramInfo() {
|
|
4312
|
-
return {
|
|
4313
|
-
pageUrl: miniProgramUrl,
|
|
4314
|
-
};
|
|
4315
|
-
},
|
|
4316
|
-
},
|
|
4317
|
-
auth: {
|
|
4318
|
-
async getCurrentUserId() {
|
|
4319
|
-
return currentUser?.heybox_id;
|
|
4320
|
-
},
|
|
4321
|
-
async login() {
|
|
4322
|
-
currentUser = createUserFromForm();
|
|
4323
|
-
updateUserStatus();
|
|
4324
|
-
},
|
|
4325
|
-
},
|
|
4326
|
-
user: {
|
|
4327
|
-
async getUserBasicInfo(userId) {
|
|
4328
|
-
if (!currentUser || currentUser.heybox_id !== userId) {
|
|
4329
|
-
return undefined;
|
|
4330
|
-
}
|
|
4331
|
-
return {
|
|
4332
|
-
nickname: currentUser.nickname,
|
|
4333
|
-
avatar: currentUser.avatar,
|
|
4334
|
-
};
|
|
4335
|
-
},
|
|
4336
|
-
},
|
|
4337
|
-
share: {
|
|
4338
|
-
async showShareMenu(options) {
|
|
4339
|
-
return {
|
|
4340
|
-
ok: true,
|
|
4341
|
-
platform: 'hb-sdk-mock-host',
|
|
4342
|
-
type: 'showShareMenu',
|
|
4343
|
-
params: options,
|
|
4344
|
-
};
|
|
4345
|
-
},
|
|
4346
|
-
async shareScreenshot(options) {
|
|
4347
|
-
return {
|
|
4348
|
-
ok: true,
|
|
4349
|
-
platform: 'hb-sdk-mock-host',
|
|
4350
|
-
type: 'screenshot',
|
|
4351
|
-
params: options,
|
|
4352
|
-
};
|
|
4353
|
-
},
|
|
4354
|
-
},
|
|
4355
|
-
viewport: {
|
|
4356
|
-
setDocumentTitle(title) {
|
|
4357
|
-
document.title = title;
|
|
4358
|
-
},
|
|
4359
|
-
setNavigationBarStyle(options) {
|
|
4360
|
-
navigationBarStyle = options.foregroundStyle;
|
|
4361
|
-
document.documentElement.dataset.navigationBarStyle = navigationBarStyle;
|
|
4362
|
-
},
|
|
4363
|
-
getViewportMetrics() {
|
|
4364
|
-
const rect = iframe.getBoundingClientRect();
|
|
4365
|
-
const width = Math.max(1, Math.round(rect.width));
|
|
4366
|
-
const height = Math.max(1, Math.round(rect.height));
|
|
4367
|
-
return {
|
|
4368
|
-
innerWidth: width,
|
|
4369
|
-
innerHeight: height,
|
|
4370
|
-
documentElementClientWidth: width,
|
|
4371
|
-
documentElementClientHeight: height,
|
|
4372
|
-
screenWidth: window.screen.width || width,
|
|
4373
|
-
screenHeight: window.screen.height || height,
|
|
4374
|
-
pixelRatio: window.devicePixelRatio || 1,
|
|
4375
|
-
};
|
|
4376
|
-
},
|
|
4377
|
-
getNavigationBarHeight() {
|
|
4378
|
-
return 0;
|
|
4379
|
-
},
|
|
4380
|
-
},
|
|
4381
|
-
storage: {
|
|
4382
|
-
getStorage({ key }) {
|
|
4383
|
-
return storage.get(key);
|
|
4384
|
-
},
|
|
4385
|
-
async setStorage({ key, value }) {
|
|
4386
|
-
storage.set(key, value);
|
|
4387
|
-
updateStorageSnapshot();
|
|
4388
|
-
},
|
|
4389
|
-
},
|
|
4390
|
-
network: {
|
|
4391
|
-
request: requestNetwork,
|
|
4392
|
-
},
|
|
4393
|
-
};
|
|
4394
|
-
}
|
|
4395
4441
|
function handleMessage(event) {
|
|
4396
4442
|
if (event.source !== iframe.contentWindow || !isBridgeMessage(event.data)) {
|
|
4397
4443
|
return;
|
|
@@ -4461,9 +4507,7 @@ async function readNetworkProxyResponse(response) {
|
|
|
4461
4507
|
catch {
|
|
4462
4508
|
throw {
|
|
4463
4509
|
code: response.status === 404 ? 'MOCK_NETWORK_PROXY_NOT_FOUND' : 'MOCK_NETWORK_PROXY_ERROR',
|
|
4464
|
-
message: response.status === 404
|
|
4465
|
-
? 'mock network proxy 不可用,请重启 hb-sdk dev'
|
|
4466
|
-
: text,
|
|
4510
|
+
message: response.status === 404 ? 'mock network proxy 不可用,请重启 hb-sdk dev' : text,
|
|
4467
4511
|
};
|
|
4468
4512
|
}
|
|
4469
4513
|
}
|
|
@@ -4700,7 +4744,7 @@ function pushLog(method, detail) {
|
|
|
4700
4744
|
});
|
|
4701
4745
|
logs.splice(30);
|
|
4702
4746
|
elements.logs.innerHTML = logs
|
|
4703
|
-
.map(log => `<article class="log"><strong>${escapeHtml(log.method)} · ${escapeHtml(log.timestamp)}</strong><pre>${escapeHtml(JSON.stringify(log.detail, null, 2))}</pre></article>`)
|
|
4747
|
+
.map((log) => `<article class="log"><strong>${escapeHtml(log.method)} · ${escapeHtml(log.timestamp)}</strong><pre>${escapeHtml(JSON.stringify(log.detail, null, 2))}</pre></article>`)
|
|
4704
4748
|
.join('');
|
|
4705
4749
|
}
|
|
4706
4750
|
function appendNonce(input, value) {
|
|
@@ -4741,10 +4785,5 @@ function isRecord(value) {
|
|
|
4741
4785
|
return typeof value === 'object' && value !== null;
|
|
4742
4786
|
}
|
|
4743
4787
|
function escapeHtml(value) {
|
|
4744
|
-
return String(value)
|
|
4745
|
-
.replace(/&/g, '&')
|
|
4746
|
-
.replace(/</g, '<')
|
|
4747
|
-
.replace(/>/g, '>')
|
|
4748
|
-
.replace(/"/g, '"')
|
|
4749
|
-
.replace(/'/g, ''');
|
|
4788
|
+
return String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
4750
4789
|
}
|