@heybox/hb-sdk 0.7.0-alpha.5 → 0.7.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/CHANGELOG.md +14 -0
- package/README.md +17 -16
- package/dist/cli-chunks/{build-35mI_IwM.cjs → build-CsXk21Yi.cjs} +2 -2
- package/dist/cli-chunks/{context-DysC5qrh.cjs → context-ClUhQYbA.cjs} +1 -1
- package/dist/cli-chunks/{create-BJSQzUeZ.cjs → create-vadbYtVj.cjs} +1 -1
- package/dist/cli-chunks/{dev-DiGtxt4q.cjs → dev-Dkk4qHsv.cjs} +5 -5
- package/dist/cli-chunks/{doctor-DWWVwcd7.cjs → doctor-DzgWYWKU.cjs} +1 -1
- package/dist/cli-chunks/{index-k5wJ6TMJ.cjs → index-BMddcNGi.cjs} +1 -1
- package/dist/cli-chunks/{index-CgCp6jGG.cjs → index-EYRMHb10.cjs} +14 -14
- package/dist/cli-chunks/{login-CzkMdcXM.cjs → login-5TM5_o8q.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-TBMlJw8y.cjs → project-vite-eJ89lO8_.cjs} +1 -1
- package/dist/cli-chunks/{remote-DE9DIxqw.cjs → remote-DxiHjrI9.cjs} +4 -4
- package/dist/cli-chunks/{session--DdaUkcq.cjs → session-DYEm6ALx.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/main.js +43 -23
- package/dist/index.cjs.js +108 -68
- package/dist/index.esm.js +107 -68
- package/dist/protocol.cjs.js +19 -0
- package/dist/protocol.esm.js +19 -1
- package/dist/templates/vue3-vite-ts/src/App.vue +29 -19
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +82 -9
- package/dist/vite.cjs.js +1 -1
- package/dist/vite.esm.js +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +8 -7
- package/skill/references/api-protocol.md +6 -2
- package/skill/references/api-root.md +65 -19
- package/skill/references/examples.md +30 -9
- package/skill/references/recipes.md +48 -26
- package/skill/references/safety-boundaries.md +3 -1
- package/skill/references/smoke-evaluation.md +3 -1
- package/skill/scripts/sync-references.mjs +31 -9
- package/skill/skill.json +4 -4
- package/types/core/client.d.ts +15 -9
- package/types/core/handshake-state.d.ts +24 -0
- package/types/core/sdk.d.ts +6 -17
- package/types/core/singleton.d.ts +5 -7
- package/types/index.d.ts +5 -3
- package/types/protocol/trusted-user-gesture.d.ts +6 -0
- package/types/protocol/types.d.ts +1 -1
- package/types/protocol.d.ts +1 -0
package/dist/index.cjs.js
CHANGED
|
@@ -433,6 +433,43 @@ class MiniProgramEventBus {
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
/** 保存握手终态,并向订阅者同步派发唯一一次状态迁移。 */
|
|
437
|
+
class MiniProgramSDKHandshakeStateStore {
|
|
438
|
+
state = Object.freeze({ status: 'connecting' });
|
|
439
|
+
handlers = new Set();
|
|
440
|
+
getState() {
|
|
441
|
+
return this.state;
|
|
442
|
+
}
|
|
443
|
+
subscribe(handler) {
|
|
444
|
+
this.handlers.add(handler);
|
|
445
|
+
this.notify(handler, this.state);
|
|
446
|
+
return () => {
|
|
447
|
+
this.handlers.delete(handler);
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
clear() {
|
|
451
|
+
this.handlers.clear();
|
|
452
|
+
}
|
|
453
|
+
settle(state) {
|
|
454
|
+
if (this.state.status !== 'connecting') {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
const immutableState = Object.freeze(state.status === 'ready'
|
|
458
|
+
? { status: 'ready' }
|
|
459
|
+
: { status: 'failed', error: state.error });
|
|
460
|
+
this.state = immutableState;
|
|
461
|
+
[...this.handlers].forEach((handler) => this.notify(handler, immutableState));
|
|
462
|
+
}
|
|
463
|
+
notify(handler, state) {
|
|
464
|
+
try {
|
|
465
|
+
handler(state);
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
// 订阅者异常不能阻断握手状态落定或其他订阅者。
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
436
473
|
const historyObservers = new WeakMap();
|
|
437
474
|
/** 共享同一个 History patch,并在最后一个订阅者退出时精确恢复原属性。 */
|
|
438
475
|
function subscribeHistoryChanges(history, listener) {
|
|
@@ -603,7 +640,7 @@ function createMessageId() {
|
|
|
603
640
|
/** 构建时替换为当前发布包的实际版本。 */
|
|
604
641
|
const HB_SDK_VERSION = typeof undefined === 'string'
|
|
605
642
|
? undefined
|
|
606
|
-
: '0.7.0
|
|
643
|
+
: '0.7.0';
|
|
607
644
|
|
|
608
645
|
/**
|
|
609
646
|
* 判断未知数据是否符合小程序 bridge 消息信封。
|
|
@@ -642,11 +679,12 @@ class MiniProgramBridgeClient {
|
|
|
642
679
|
};
|
|
643
680
|
unsubscribeHistoryChanges;
|
|
644
681
|
started = false;
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
682
|
+
handshakeState = new MiniProgramSDKHandshakeStateStore();
|
|
683
|
+
handshakeSettled = false;
|
|
684
|
+
handshakePromise;
|
|
685
|
+
resolveHandshake;
|
|
686
|
+
rejectHandshake;
|
|
687
|
+
handshakeTimer;
|
|
650
688
|
handshakeRetryTimer;
|
|
651
689
|
destroyed = false;
|
|
652
690
|
runtimeUnavailable = false;
|
|
@@ -659,16 +697,24 @@ class MiniProgramBridgeClient {
|
|
|
659
697
|
this.targetOrigin = options.targetOrigin || readParentOrigin(this.selfWindow) || '*';
|
|
660
698
|
this.nonce = options.nonce || readBridgeNonce(this.selfWindow);
|
|
661
699
|
this.handleMessage = this.onMessage.bind(this);
|
|
662
|
-
this.
|
|
663
|
-
this.
|
|
664
|
-
this.
|
|
700
|
+
this.handshakePromise = new Promise((resolve, reject) => {
|
|
701
|
+
this.resolveHandshake = resolve;
|
|
702
|
+
this.rejectHandshake = reject;
|
|
665
703
|
});
|
|
666
|
-
this.
|
|
704
|
+
this.handshakePromise.catch(() => undefined);
|
|
667
705
|
this.ensureStarted();
|
|
668
706
|
}
|
|
669
707
|
/** 等待父容器握手完成。 */
|
|
670
|
-
|
|
671
|
-
return this.
|
|
708
|
+
waitForHandshake() {
|
|
709
|
+
return this.handshakePromise;
|
|
710
|
+
}
|
|
711
|
+
/** 获取当前握手状态。 */
|
|
712
|
+
getHandshakeState() {
|
|
713
|
+
return this.handshakeState.getState();
|
|
714
|
+
}
|
|
715
|
+
/** 订阅握手状态,并立即接收当前状态。 */
|
|
716
|
+
onHandshakeStateChange(handler) {
|
|
717
|
+
return this.handshakeState.subscribe(handler);
|
|
672
718
|
}
|
|
673
719
|
/** 注册小程序事件监听。 */
|
|
674
720
|
on(eventName, handler) {
|
|
@@ -686,7 +732,7 @@ class MiniProgramBridgeClient {
|
|
|
686
732
|
if (this.runtimeUnavailable) {
|
|
687
733
|
throw this.getRuntimeUnavailableError();
|
|
688
734
|
}
|
|
689
|
-
await this.
|
|
735
|
+
await this.waitForHandshake();
|
|
690
736
|
if (this.destroyed) {
|
|
691
737
|
throw createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁');
|
|
692
738
|
}
|
|
@@ -735,16 +781,17 @@ class MiniProgramBridgeClient {
|
|
|
735
781
|
this.unsubscribeHistoryChanges?.();
|
|
736
782
|
this.unsubscribeHistoryChanges = undefined;
|
|
737
783
|
const error = createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁');
|
|
738
|
-
this.
|
|
784
|
+
this.failHandshake(error);
|
|
785
|
+
this.handshakeState.clear();
|
|
739
786
|
this.rejectAllPending(error);
|
|
740
787
|
}
|
|
741
788
|
ensureStarted() {
|
|
742
789
|
if (this.destroyed) {
|
|
743
|
-
this.
|
|
790
|
+
this.failHandshake(createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁'));
|
|
744
791
|
return;
|
|
745
792
|
}
|
|
746
793
|
if (this.runtimeUnavailable) {
|
|
747
|
-
this.
|
|
794
|
+
this.failHandshake(this.getRuntimeUnavailableError());
|
|
748
795
|
return;
|
|
749
796
|
}
|
|
750
797
|
if (this.started) {
|
|
@@ -752,11 +799,11 @@ class MiniProgramBridgeClient {
|
|
|
752
799
|
}
|
|
753
800
|
this.started = true;
|
|
754
801
|
if (!this.selfWindow || !this.targetWindow) {
|
|
755
|
-
this.
|
|
802
|
+
this.failHandshake(createSDKError('NOT_IN_IFRAME', '当前页面不在小程序沙盒 iframe 中'));
|
|
756
803
|
return;
|
|
757
804
|
}
|
|
758
805
|
if (!this.nonce) {
|
|
759
|
-
this.
|
|
806
|
+
this.failHandshake(createSDKError('MISSING_NONCE', '缺少小程序沙盒通信标识'));
|
|
760
807
|
return;
|
|
761
808
|
}
|
|
762
809
|
this.selfWindow.addEventListener('message', this.handleMessage);
|
|
@@ -767,8 +814,8 @@ class MiniProgramBridgeClient {
|
|
|
767
814
|
this.unsubscribeHistoryChanges = subscribeHistoryChanges(this.selfWindow.history, () => {
|
|
768
815
|
this.postLocationReport('history');
|
|
769
816
|
});
|
|
770
|
-
this.
|
|
771
|
-
this.
|
|
817
|
+
this.handshakeTimer = setTimeout(() => {
|
|
818
|
+
this.failHandshake(createSDKError('READY_TIMEOUT', '小程序沙盒握手超时'));
|
|
772
819
|
}, this.timeout);
|
|
773
820
|
try {
|
|
774
821
|
this.postHandshake();
|
|
@@ -777,14 +824,14 @@ class MiniProgramBridgeClient {
|
|
|
777
824
|
this.postHandshake();
|
|
778
825
|
}
|
|
779
826
|
catch (error) {
|
|
780
|
-
this.
|
|
827
|
+
this.failHandshake(error instanceof HbMiniProgramSDKError
|
|
781
828
|
? error
|
|
782
829
|
: createSDKError('HANDSHAKE_FAILED', '小程序沙盒握手发送失败', error));
|
|
783
830
|
}
|
|
784
831
|
}, HANDSHAKE_RETRY_INTERVAL);
|
|
785
832
|
}
|
|
786
833
|
catch (error) {
|
|
787
|
-
this.
|
|
834
|
+
this.failHandshake(error instanceof HbMiniProgramSDKError
|
|
788
835
|
? error
|
|
789
836
|
: createSDKError('HANDSHAKE_FAILED', '小程序沙盒握手发送失败', error));
|
|
790
837
|
}
|
|
@@ -881,7 +928,7 @@ class MiniProgramBridgeClient {
|
|
|
881
928
|
this.markRuntimeUnavailable();
|
|
882
929
|
}
|
|
883
930
|
else if (eventName === 'ready' && !this.runtimeUnavailable) {
|
|
884
|
-
this.
|
|
931
|
+
this.resolveHandshakeOnce();
|
|
885
932
|
}
|
|
886
933
|
else if (eventName === 'show' && !this.runtimeUnavailable) {
|
|
887
934
|
this.postLocationReport('resume');
|
|
@@ -910,26 +957,28 @@ class MiniProgramBridgeClient {
|
|
|
910
957
|
}
|
|
911
958
|
this.targetWindow.postMessage(message, this.targetOrigin);
|
|
912
959
|
}
|
|
913
|
-
|
|
914
|
-
if (this.
|
|
960
|
+
resolveHandshakeOnce() {
|
|
961
|
+
if (this.handshakeSettled) {
|
|
915
962
|
return;
|
|
916
963
|
}
|
|
917
|
-
this.
|
|
918
|
-
this.
|
|
919
|
-
this.
|
|
964
|
+
this.handshakeSettled = true;
|
|
965
|
+
this.clearHandshakeTimers();
|
|
966
|
+
this.handshakeState.settle({ status: 'ready' });
|
|
967
|
+
this.resolveHandshake();
|
|
920
968
|
}
|
|
921
|
-
|
|
922
|
-
if (this.
|
|
969
|
+
failHandshake(error) {
|
|
970
|
+
if (this.handshakeSettled) {
|
|
923
971
|
return;
|
|
924
972
|
}
|
|
925
|
-
this.
|
|
926
|
-
this.
|
|
927
|
-
this.
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
this.
|
|
973
|
+
this.handshakeSettled = true;
|
|
974
|
+
this.clearHandshakeTimers();
|
|
975
|
+
this.handshakeState.settle({ status: 'failed', error });
|
|
976
|
+
this.rejectHandshake(error);
|
|
977
|
+
}
|
|
978
|
+
clearHandshakeTimers() {
|
|
979
|
+
if (this.handshakeTimer) {
|
|
980
|
+
clearTimeout(this.handshakeTimer);
|
|
981
|
+
this.handshakeTimer = undefined;
|
|
933
982
|
}
|
|
934
983
|
if (this.handshakeRetryTimer) {
|
|
935
984
|
clearInterval(this.handshakeRetryTimer);
|
|
@@ -942,8 +991,8 @@ class MiniProgramBridgeClient {
|
|
|
942
991
|
}
|
|
943
992
|
const error = this.getRuntimeUnavailableError();
|
|
944
993
|
this.runtimeUnavailable = true;
|
|
945
|
-
this.
|
|
946
|
-
this.
|
|
994
|
+
this.clearHandshakeTimers();
|
|
995
|
+
this.failHandshake(error);
|
|
947
996
|
this.rejectAllPending(error);
|
|
948
997
|
}
|
|
949
998
|
getRuntimeUnavailableError() {
|
|
@@ -1597,16 +1646,7 @@ function createNavigationModule(requester) {
|
|
|
1597
1646
|
* 多数业务页直接使用默认单例即可;只有在测试、多实例或需要定制运行参数时,
|
|
1598
1647
|
* 才建议显式创建独立实例。
|
|
1599
1648
|
*
|
|
1600
|
-
*
|
|
1601
|
-
* ```ts
|
|
1602
|
-
* import { createMiniProgramSDK } from '@heybox/hb-sdk'
|
|
1603
|
-
*
|
|
1604
|
-
* const sdk = createMiniProgramSDK({
|
|
1605
|
-
* timeout: 15000,
|
|
1606
|
-
* })
|
|
1607
|
-
*
|
|
1608
|
-
* await sdk.ready()
|
|
1609
|
-
* ```
|
|
1649
|
+
* 能力调用会自动等待与父容器完成握手。
|
|
1610
1650
|
*/
|
|
1611
1651
|
class MiniProgramSDK {
|
|
1612
1652
|
client;
|
|
@@ -1643,14 +1683,13 @@ class MiniProgramSDK {
|
|
|
1643
1683
|
this.navigation = createNavigationModule(this.client);
|
|
1644
1684
|
this.cloud = createCloudModule(this.client);
|
|
1645
1685
|
}
|
|
1646
|
-
/**
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
return this.client.ready();
|
|
1686
|
+
/** 获取当前握手状态。 */
|
|
1687
|
+
getHandshakeState() {
|
|
1688
|
+
return this.client.getHandshakeState();
|
|
1689
|
+
}
|
|
1690
|
+
/** 订阅握手状态,并立即接收当前状态。 */
|
|
1691
|
+
onHandshakeStateChange(handler) {
|
|
1692
|
+
return this.client.onHandshakeStateChange(handler);
|
|
1654
1693
|
}
|
|
1655
1694
|
/**
|
|
1656
1695
|
* 注册小程序生命周期或业务事件。
|
|
@@ -1711,14 +1750,13 @@ function getDefaultSDK() {
|
|
|
1711
1750
|
}
|
|
1712
1751
|
return defaultSDK;
|
|
1713
1752
|
}
|
|
1714
|
-
/**
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
return getDefaultSDK().ready();
|
|
1753
|
+
/** 获取默认 SDK 实例的当前握手状态。 */
|
|
1754
|
+
function getHandshakeState() {
|
|
1755
|
+
return getDefaultSDK().getHandshakeState();
|
|
1756
|
+
}
|
|
1757
|
+
/** 订阅默认 SDK 实例的握手状态,并立即接收当前状态。 */
|
|
1758
|
+
function onHandshakeStateChange(handler) {
|
|
1759
|
+
return getDefaultSDK().onHandshakeStateChange(handler);
|
|
1722
1760
|
}
|
|
1723
1761
|
/**
|
|
1724
1762
|
* 注册默认 SDK 实例的事件监听。
|
|
@@ -1799,7 +1837,8 @@ const cloud = {
|
|
|
1799
1837
|
};
|
|
1800
1838
|
|
|
1801
1839
|
const hbSDK = {
|
|
1802
|
-
|
|
1840
|
+
getHandshakeState,
|
|
1841
|
+
onHandshakeStateChange,
|
|
1803
1842
|
on,
|
|
1804
1843
|
off,
|
|
1805
1844
|
auth,
|
|
@@ -1820,11 +1859,12 @@ exports.auth = auth;
|
|
|
1820
1859
|
exports.cloud = cloud;
|
|
1821
1860
|
exports.default = hbSDK;
|
|
1822
1861
|
exports.device = device;
|
|
1862
|
+
exports.getHandshakeState = getHandshakeState;
|
|
1823
1863
|
exports.navigation = navigation;
|
|
1824
1864
|
exports.network = network;
|
|
1825
1865
|
exports.off = off;
|
|
1826
1866
|
exports.on = on;
|
|
1827
|
-
exports.
|
|
1867
|
+
exports.onHandshakeStateChange = onHandshakeStateChange;
|
|
1828
1868
|
exports.share = share;
|
|
1829
1869
|
exports.storage = storage;
|
|
1830
1870
|
exports.ui = ui;
|
package/dist/index.esm.js
CHANGED
|
@@ -429,6 +429,43 @@ class MiniProgramEventBus {
|
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
+
/** 保存握手终态,并向订阅者同步派发唯一一次状态迁移。 */
|
|
433
|
+
class MiniProgramSDKHandshakeStateStore {
|
|
434
|
+
state = Object.freeze({ status: 'connecting' });
|
|
435
|
+
handlers = new Set();
|
|
436
|
+
getState() {
|
|
437
|
+
return this.state;
|
|
438
|
+
}
|
|
439
|
+
subscribe(handler) {
|
|
440
|
+
this.handlers.add(handler);
|
|
441
|
+
this.notify(handler, this.state);
|
|
442
|
+
return () => {
|
|
443
|
+
this.handlers.delete(handler);
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
clear() {
|
|
447
|
+
this.handlers.clear();
|
|
448
|
+
}
|
|
449
|
+
settle(state) {
|
|
450
|
+
if (this.state.status !== 'connecting') {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const immutableState = Object.freeze(state.status === 'ready'
|
|
454
|
+
? { status: 'ready' }
|
|
455
|
+
: { status: 'failed', error: state.error });
|
|
456
|
+
this.state = immutableState;
|
|
457
|
+
[...this.handlers].forEach((handler) => this.notify(handler, immutableState));
|
|
458
|
+
}
|
|
459
|
+
notify(handler, state) {
|
|
460
|
+
try {
|
|
461
|
+
handler(state);
|
|
462
|
+
}
|
|
463
|
+
catch {
|
|
464
|
+
// 订阅者异常不能阻断握手状态落定或其他订阅者。
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
432
469
|
const historyObservers = new WeakMap();
|
|
433
470
|
/** 共享同一个 History patch,并在最后一个订阅者退出时精确恢复原属性。 */
|
|
434
471
|
function subscribeHistoryChanges(history, listener) {
|
|
@@ -599,7 +636,7 @@ function createMessageId() {
|
|
|
599
636
|
/** 构建时替换为当前发布包的实际版本。 */
|
|
600
637
|
const HB_SDK_VERSION = typeof undefined === 'string'
|
|
601
638
|
? undefined
|
|
602
|
-
: '0.7.0
|
|
639
|
+
: '0.7.0';
|
|
603
640
|
|
|
604
641
|
/**
|
|
605
642
|
* 判断未知数据是否符合小程序 bridge 消息信封。
|
|
@@ -638,11 +675,12 @@ class MiniProgramBridgeClient {
|
|
|
638
675
|
};
|
|
639
676
|
unsubscribeHistoryChanges;
|
|
640
677
|
started = false;
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
678
|
+
handshakeState = new MiniProgramSDKHandshakeStateStore();
|
|
679
|
+
handshakeSettled = false;
|
|
680
|
+
handshakePromise;
|
|
681
|
+
resolveHandshake;
|
|
682
|
+
rejectHandshake;
|
|
683
|
+
handshakeTimer;
|
|
646
684
|
handshakeRetryTimer;
|
|
647
685
|
destroyed = false;
|
|
648
686
|
runtimeUnavailable = false;
|
|
@@ -655,16 +693,24 @@ class MiniProgramBridgeClient {
|
|
|
655
693
|
this.targetOrigin = options.targetOrigin || readParentOrigin(this.selfWindow) || '*';
|
|
656
694
|
this.nonce = options.nonce || readBridgeNonce(this.selfWindow);
|
|
657
695
|
this.handleMessage = this.onMessage.bind(this);
|
|
658
|
-
this.
|
|
659
|
-
this.
|
|
660
|
-
this.
|
|
696
|
+
this.handshakePromise = new Promise((resolve, reject) => {
|
|
697
|
+
this.resolveHandshake = resolve;
|
|
698
|
+
this.rejectHandshake = reject;
|
|
661
699
|
});
|
|
662
|
-
this.
|
|
700
|
+
this.handshakePromise.catch(() => undefined);
|
|
663
701
|
this.ensureStarted();
|
|
664
702
|
}
|
|
665
703
|
/** 等待父容器握手完成。 */
|
|
666
|
-
|
|
667
|
-
return this.
|
|
704
|
+
waitForHandshake() {
|
|
705
|
+
return this.handshakePromise;
|
|
706
|
+
}
|
|
707
|
+
/** 获取当前握手状态。 */
|
|
708
|
+
getHandshakeState() {
|
|
709
|
+
return this.handshakeState.getState();
|
|
710
|
+
}
|
|
711
|
+
/** 订阅握手状态,并立即接收当前状态。 */
|
|
712
|
+
onHandshakeStateChange(handler) {
|
|
713
|
+
return this.handshakeState.subscribe(handler);
|
|
668
714
|
}
|
|
669
715
|
/** 注册小程序事件监听。 */
|
|
670
716
|
on(eventName, handler) {
|
|
@@ -682,7 +728,7 @@ class MiniProgramBridgeClient {
|
|
|
682
728
|
if (this.runtimeUnavailable) {
|
|
683
729
|
throw this.getRuntimeUnavailableError();
|
|
684
730
|
}
|
|
685
|
-
await this.
|
|
731
|
+
await this.waitForHandshake();
|
|
686
732
|
if (this.destroyed) {
|
|
687
733
|
throw createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁');
|
|
688
734
|
}
|
|
@@ -731,16 +777,17 @@ class MiniProgramBridgeClient {
|
|
|
731
777
|
this.unsubscribeHistoryChanges?.();
|
|
732
778
|
this.unsubscribeHistoryChanges = undefined;
|
|
733
779
|
const error = createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁');
|
|
734
|
-
this.
|
|
780
|
+
this.failHandshake(error);
|
|
781
|
+
this.handshakeState.clear();
|
|
735
782
|
this.rejectAllPending(error);
|
|
736
783
|
}
|
|
737
784
|
ensureStarted() {
|
|
738
785
|
if (this.destroyed) {
|
|
739
|
-
this.
|
|
786
|
+
this.failHandshake(createSDKError('SDK_DESTROYED', '小程序 SDK 已销毁'));
|
|
740
787
|
return;
|
|
741
788
|
}
|
|
742
789
|
if (this.runtimeUnavailable) {
|
|
743
|
-
this.
|
|
790
|
+
this.failHandshake(this.getRuntimeUnavailableError());
|
|
744
791
|
return;
|
|
745
792
|
}
|
|
746
793
|
if (this.started) {
|
|
@@ -748,11 +795,11 @@ class MiniProgramBridgeClient {
|
|
|
748
795
|
}
|
|
749
796
|
this.started = true;
|
|
750
797
|
if (!this.selfWindow || !this.targetWindow) {
|
|
751
|
-
this.
|
|
798
|
+
this.failHandshake(createSDKError('NOT_IN_IFRAME', '当前页面不在小程序沙盒 iframe 中'));
|
|
752
799
|
return;
|
|
753
800
|
}
|
|
754
801
|
if (!this.nonce) {
|
|
755
|
-
this.
|
|
802
|
+
this.failHandshake(createSDKError('MISSING_NONCE', '缺少小程序沙盒通信标识'));
|
|
756
803
|
return;
|
|
757
804
|
}
|
|
758
805
|
this.selfWindow.addEventListener('message', this.handleMessage);
|
|
@@ -763,8 +810,8 @@ class MiniProgramBridgeClient {
|
|
|
763
810
|
this.unsubscribeHistoryChanges = subscribeHistoryChanges(this.selfWindow.history, () => {
|
|
764
811
|
this.postLocationReport('history');
|
|
765
812
|
});
|
|
766
|
-
this.
|
|
767
|
-
this.
|
|
813
|
+
this.handshakeTimer = setTimeout(() => {
|
|
814
|
+
this.failHandshake(createSDKError('READY_TIMEOUT', '小程序沙盒握手超时'));
|
|
768
815
|
}, this.timeout);
|
|
769
816
|
try {
|
|
770
817
|
this.postHandshake();
|
|
@@ -773,14 +820,14 @@ class MiniProgramBridgeClient {
|
|
|
773
820
|
this.postHandshake();
|
|
774
821
|
}
|
|
775
822
|
catch (error) {
|
|
776
|
-
this.
|
|
823
|
+
this.failHandshake(error instanceof HbMiniProgramSDKError
|
|
777
824
|
? error
|
|
778
825
|
: createSDKError('HANDSHAKE_FAILED', '小程序沙盒握手发送失败', error));
|
|
779
826
|
}
|
|
780
827
|
}, HANDSHAKE_RETRY_INTERVAL);
|
|
781
828
|
}
|
|
782
829
|
catch (error) {
|
|
783
|
-
this.
|
|
830
|
+
this.failHandshake(error instanceof HbMiniProgramSDKError
|
|
784
831
|
? error
|
|
785
832
|
: createSDKError('HANDSHAKE_FAILED', '小程序沙盒握手发送失败', error));
|
|
786
833
|
}
|
|
@@ -877,7 +924,7 @@ class MiniProgramBridgeClient {
|
|
|
877
924
|
this.markRuntimeUnavailable();
|
|
878
925
|
}
|
|
879
926
|
else if (eventName === 'ready' && !this.runtimeUnavailable) {
|
|
880
|
-
this.
|
|
927
|
+
this.resolveHandshakeOnce();
|
|
881
928
|
}
|
|
882
929
|
else if (eventName === 'show' && !this.runtimeUnavailable) {
|
|
883
930
|
this.postLocationReport('resume');
|
|
@@ -906,26 +953,28 @@ class MiniProgramBridgeClient {
|
|
|
906
953
|
}
|
|
907
954
|
this.targetWindow.postMessage(message, this.targetOrigin);
|
|
908
955
|
}
|
|
909
|
-
|
|
910
|
-
if (this.
|
|
956
|
+
resolveHandshakeOnce() {
|
|
957
|
+
if (this.handshakeSettled) {
|
|
911
958
|
return;
|
|
912
959
|
}
|
|
913
|
-
this.
|
|
914
|
-
this.
|
|
915
|
-
this.
|
|
960
|
+
this.handshakeSettled = true;
|
|
961
|
+
this.clearHandshakeTimers();
|
|
962
|
+
this.handshakeState.settle({ status: 'ready' });
|
|
963
|
+
this.resolveHandshake();
|
|
916
964
|
}
|
|
917
|
-
|
|
918
|
-
if (this.
|
|
965
|
+
failHandshake(error) {
|
|
966
|
+
if (this.handshakeSettled) {
|
|
919
967
|
return;
|
|
920
968
|
}
|
|
921
|
-
this.
|
|
922
|
-
this.
|
|
923
|
-
this.
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
this.
|
|
969
|
+
this.handshakeSettled = true;
|
|
970
|
+
this.clearHandshakeTimers();
|
|
971
|
+
this.handshakeState.settle({ status: 'failed', error });
|
|
972
|
+
this.rejectHandshake(error);
|
|
973
|
+
}
|
|
974
|
+
clearHandshakeTimers() {
|
|
975
|
+
if (this.handshakeTimer) {
|
|
976
|
+
clearTimeout(this.handshakeTimer);
|
|
977
|
+
this.handshakeTimer = undefined;
|
|
929
978
|
}
|
|
930
979
|
if (this.handshakeRetryTimer) {
|
|
931
980
|
clearInterval(this.handshakeRetryTimer);
|
|
@@ -938,8 +987,8 @@ class MiniProgramBridgeClient {
|
|
|
938
987
|
}
|
|
939
988
|
const error = this.getRuntimeUnavailableError();
|
|
940
989
|
this.runtimeUnavailable = true;
|
|
941
|
-
this.
|
|
942
|
-
this.
|
|
990
|
+
this.clearHandshakeTimers();
|
|
991
|
+
this.failHandshake(error);
|
|
943
992
|
this.rejectAllPending(error);
|
|
944
993
|
}
|
|
945
994
|
getRuntimeUnavailableError() {
|
|
@@ -1593,16 +1642,7 @@ function createNavigationModule(requester) {
|
|
|
1593
1642
|
* 多数业务页直接使用默认单例即可;只有在测试、多实例或需要定制运行参数时,
|
|
1594
1643
|
* 才建议显式创建独立实例。
|
|
1595
1644
|
*
|
|
1596
|
-
*
|
|
1597
|
-
* ```ts
|
|
1598
|
-
* import { createMiniProgramSDK } from '@heybox/hb-sdk'
|
|
1599
|
-
*
|
|
1600
|
-
* const sdk = createMiniProgramSDK({
|
|
1601
|
-
* timeout: 15000,
|
|
1602
|
-
* })
|
|
1603
|
-
*
|
|
1604
|
-
* await sdk.ready()
|
|
1605
|
-
* ```
|
|
1645
|
+
* 能力调用会自动等待与父容器完成握手。
|
|
1606
1646
|
*/
|
|
1607
1647
|
class MiniProgramSDK {
|
|
1608
1648
|
client;
|
|
@@ -1639,14 +1679,13 @@ class MiniProgramSDK {
|
|
|
1639
1679
|
this.navigation = createNavigationModule(this.client);
|
|
1640
1680
|
this.cloud = createCloudModule(this.client);
|
|
1641
1681
|
}
|
|
1642
|
-
/**
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
return this.client.ready();
|
|
1682
|
+
/** 获取当前握手状态。 */
|
|
1683
|
+
getHandshakeState() {
|
|
1684
|
+
return this.client.getHandshakeState();
|
|
1685
|
+
}
|
|
1686
|
+
/** 订阅握手状态,并立即接收当前状态。 */
|
|
1687
|
+
onHandshakeStateChange(handler) {
|
|
1688
|
+
return this.client.onHandshakeStateChange(handler);
|
|
1650
1689
|
}
|
|
1651
1690
|
/**
|
|
1652
1691
|
* 注册小程序生命周期或业务事件。
|
|
@@ -1707,14 +1746,13 @@ function getDefaultSDK() {
|
|
|
1707
1746
|
}
|
|
1708
1747
|
return defaultSDK;
|
|
1709
1748
|
}
|
|
1710
|
-
/**
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
return getDefaultSDK().ready();
|
|
1749
|
+
/** 获取默认 SDK 实例的当前握手状态。 */
|
|
1750
|
+
function getHandshakeState() {
|
|
1751
|
+
return getDefaultSDK().getHandshakeState();
|
|
1752
|
+
}
|
|
1753
|
+
/** 订阅默认 SDK 实例的握手状态,并立即接收当前状态。 */
|
|
1754
|
+
function onHandshakeStateChange(handler) {
|
|
1755
|
+
return getDefaultSDK().onHandshakeStateChange(handler);
|
|
1718
1756
|
}
|
|
1719
1757
|
/**
|
|
1720
1758
|
* 注册默认 SDK 实例的事件监听。
|
|
@@ -1795,7 +1833,8 @@ const cloud = {
|
|
|
1795
1833
|
};
|
|
1796
1834
|
|
|
1797
1835
|
const hbSDK = {
|
|
1798
|
-
|
|
1836
|
+
getHandshakeState,
|
|
1837
|
+
onHandshakeStateChange,
|
|
1799
1838
|
on,
|
|
1800
1839
|
off,
|
|
1801
1840
|
auth,
|
|
@@ -1810,4 +1849,4 @@ const hbSDK = {
|
|
|
1810
1849
|
cloud,
|
|
1811
1850
|
};
|
|
1812
1851
|
|
|
1813
|
-
export { HbMiniProgramNetworkError, HbMiniProgramSDKError, auth, cloud, hbSDK as default, device, navigation, network, off, on,
|
|
1852
|
+
export { HbMiniProgramNetworkError, HbMiniProgramSDKError, auth, cloud, hbSDK as default, device, getHandshakeState, navigation, network, off, on, onHandshakeStateChange, share, storage, ui, user, viewport };
|
package/dist/protocol.cjs.js
CHANGED
|
@@ -32,6 +32,24 @@ function isMiniProgramBridgeMessage(value) {
|
|
|
32
32
|
typeof message.type === 'string');
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function readBrowserEnvironment() {
|
|
36
|
+
try {
|
|
37
|
+
return {
|
|
38
|
+
activeElement: globalThis.document?.activeElement ?? null,
|
|
39
|
+
userActivation: globalThis.navigator?.userActivation,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { activeElement: null };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** 按当前浏览器消息、用户激活和目标 iframe 焦点生成请求级可信手势快照。 */
|
|
47
|
+
function computeTrustedIframeUserGesture(event, iframe, environment = readBrowserEnvironment()) {
|
|
48
|
+
return (event.isTrusted === true
|
|
49
|
+
&& environment.userActivation?.isActive === true
|
|
50
|
+
&& environment.activeElement === iframe);
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
|
|
36
54
|
/**
|
|
37
55
|
* 判断 permission key 是否由 Runtime 权限快照管理。
|
|
@@ -469,6 +487,7 @@ exports.USER_GET_STEAM_GAME_LIST_METHOD = USER_GET_STEAM_GAME_LIST_METHOD;
|
|
|
469
487
|
exports.USER_REVOKE_AUTHORIZATION_METHOD = USER_REVOKE_AUTHORIZATION_METHOD;
|
|
470
488
|
exports.VIEWPORT_GET_WINDOW_INFO_METHOD = VIEWPORT_GET_WINDOW_INFO_METHOD;
|
|
471
489
|
exports.VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD;
|
|
490
|
+
exports.computeTrustedIframeUserGesture = computeTrustedIframeUserGesture;
|
|
472
491
|
exports.isManagedMiniProgramRuntimePermissionKey = isManagedMiniProgramRuntimePermissionKey;
|
|
473
492
|
exports.isMiniProgramBridgeMessage = isMiniProgramBridgeMessage;
|
|
474
493
|
exports.isOfficialMiniProgramNetworkUrl = isOfficialMiniProgramNetworkUrl;
|