@heybox/hb-sdk 0.1.3 → 0.2.0-alpha.1
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 +149 -345
- package/bin/hb-sdk.cjs +3 -0
- package/dist/cli.cjs +10117 -0
- package/dist/devtools/mock-host/index.html +252 -0
- package/dist/devtools/mock-host/main.js +975 -0
- package/dist/index.cjs.js +474 -85
- package/dist/index.esm.js +465 -71
- package/dist/protocol.cjs.js +163 -0
- package/dist/protocol.esm.js +148 -0
- package/dist/templates/vue3-vite-ts/.gitignore.ejs +5 -0
- package/dist/templates/vue3-vite-ts/README.md.ejs +42 -0
- package/dist/templates/vue3-vite-ts/index.html.ejs +12 -0
- package/dist/templates/vue3-vite-ts/package.json.ejs +28 -0
- package/dist/templates/vue3-vite-ts/src/App.vue +63 -0
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +67 -0
- package/dist/templates/vue3-vite-ts/src/main.ts +5 -0
- package/dist/templates/vue3-vite-ts/src/styles.css +60 -0
- package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +1 -0
- package/dist/templates/vue3-vite-ts/tsconfig.app.json +17 -0
- package/dist/templates/vue3-vite-ts/tsconfig.json +11 -0
- package/dist/templates/vue3-vite-ts/tsconfig.node.json +11 -0
- package/dist/templates/vue3-vite-ts/vite.config.ts +6 -0
- package/dist/templates/vue3-vite-ts/vitest.config.ts +10 -0
- package/package.json +30 -5
- package/skill/SKILL.md +95 -0
- package/skill/references/api-protocol.md +135 -0
- package/skill/references/api-root.md +346 -0
- package/skill/references/cli.md +360 -0
- package/skill/references/examples.md +107 -0
- package/skill/references/llms-index.md +44 -0
- package/skill/references/recipes.md +374 -0
- package/skill/references/safety-boundaries.md +28 -0
- package/skill/references/smoke-evaluation.md +24 -0
- package/skill/scripts/check-references.mjs +14 -0
- package/skill/scripts/package-skill.mjs +60 -0
- package/skill/scripts/package-skill.sh +6 -0
- package/skill/scripts/skill-metadata.mjs +74 -0
- package/skill/scripts/sync-references.mjs +541 -0
- package/skill/scripts/validate-skill.mjs +233 -0
- package/skill/skill.json +11 -0
- package/types/core/client.d.ts +23 -3
- package/types/core/errors.d.ts +45 -2
- package/types/core/sdk.d.ts +78 -10
- package/types/core/singleton.d.ts +33 -7
- package/types/core/utils.d.ts +2 -0
- package/types/index.d.ts +14 -6
- package/types/modules/auth/index.d.ts +35 -0
- package/types/modules/network/index.d.ts +120 -0
- package/types/modules/share/index.d.ts +9 -5
- package/types/modules/share/screenshot.d.ts +9 -3
- package/types/modules/share/show-share-menu.d.ts +9 -3
- package/types/modules/share/types.d.ts +24 -4
- package/types/modules/storage/index.d.ts +56 -0
- package/types/modules/user/get-info.d.ts +6 -2
- package/types/modules/user/index.d.ts +8 -10
- package/types/modules/user/types.d.ts +1 -0
- package/types/modules/viewport/index.d.ts +71 -0
- package/types/protocol/capabilities.d.ts +180 -0
- package/types/protocol/guards.d.ts +6 -1
- package/types/protocol/types.d.ts +19 -4
- package/types/protocol.d.ts +13 -0
- package/types/modules/system/get-storage.d.ts +0 -15
- package/types/modules/system/get-window-info.d.ts +0 -16
- package/types/modules/system/index.d.ts +0 -23
- package/types/modules/system/set-storage.d.ts +0 -12
- package/types/modules/system/types.d.ts +0 -34
- package/types/modules/user/login.d.ts +0 -18
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** 小程序沙盒通信命名空间,父容器与 iframe 内 SDK 必须保持一致。 */
|
|
4
|
+
const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
|
|
5
|
+
/** 小程序沙盒通信协议版本。 */
|
|
6
|
+
const MINI_PROGRAM_MESSAGE_VERSION = 1;
|
|
7
|
+
/** 父容器注入到小程序 URL 上的通信 nonce 参数名。 */
|
|
8
|
+
const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
|
|
9
|
+
/** SDK 初始化时发给父容器的握手方法名。 */
|
|
10
|
+
const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 判断未知数据是否符合小程序 bridge 消息信封。
|
|
14
|
+
*
|
|
15
|
+
* @param value 待判断的未知数据。
|
|
16
|
+
* @returns 当数据满足小程序 bridge 消息基础结构时返回 `true`。
|
|
17
|
+
*/
|
|
18
|
+
function isMiniProgramBridgeMessage(value) {
|
|
19
|
+
if (!value || typeof value !== 'object') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const message = value;
|
|
23
|
+
return (message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
|
|
24
|
+
message.version === MINI_PROGRAM_MESSAGE_VERSION &&
|
|
25
|
+
typeof message.nonce === 'string' &&
|
|
26
|
+
typeof message.type === 'string');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 登录授权能力方法名。
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
34
|
+
*/
|
|
35
|
+
const AUTH_LOGIN_METHOD = 'auth.login';
|
|
36
|
+
/**
|
|
37
|
+
* 用户信息能力方法名。
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
41
|
+
*/
|
|
42
|
+
const USER_GET_INFO_METHOD = 'user.getInfo';
|
|
43
|
+
/**
|
|
44
|
+
* 展示分享面板能力方法名。
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
48
|
+
*/
|
|
49
|
+
const SHARE_SHOW_SHARE_MENU_METHOD = 'share.showShareMenu';
|
|
50
|
+
/**
|
|
51
|
+
* 截图分享能力方法名。
|
|
52
|
+
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
55
|
+
*/
|
|
56
|
+
const SHARE_SCREENSHOT_METHOD = 'share.screenshot';
|
|
57
|
+
/**
|
|
58
|
+
* 视口窗口信息能力方法名。
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
62
|
+
*/
|
|
63
|
+
const VIEWPORT_GET_WINDOW_INFO_METHOD = 'viewport.getWindowInfo';
|
|
64
|
+
/**
|
|
65
|
+
* 读取小程序隔离 storage 能力方法名。
|
|
66
|
+
*
|
|
67
|
+
* @remarks
|
|
68
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
69
|
+
*/
|
|
70
|
+
const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage';
|
|
71
|
+
/**
|
|
72
|
+
* 写入小程序隔离 storage 能力方法名。
|
|
73
|
+
*
|
|
74
|
+
* @remarks
|
|
75
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
76
|
+
*/
|
|
77
|
+
const STORAGE_SET_STORAGE_METHOD = 'storage.setStorage';
|
|
78
|
+
/**
|
|
79
|
+
* 发起网络请求能力方法名。
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
83
|
+
*/
|
|
84
|
+
const NETWORK_REQUEST_METHOD = 'network.request';
|
|
85
|
+
/**
|
|
86
|
+
* 小程序开放能力目录。
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* 新增 bridge method 时应先更新这里,再分别补齐 SDK 模块、runtime handler 与测试。
|
|
90
|
+
*/
|
|
91
|
+
const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
|
|
92
|
+
{
|
|
93
|
+
method: AUTH_LOGIN_METHOD,
|
|
94
|
+
module: 'auth',
|
|
95
|
+
capability: AUTH_LOGIN_METHOD,
|
|
96
|
+
permission: 'auth.login',
|
|
97
|
+
risk: 'medium',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
method: USER_GET_INFO_METHOD,
|
|
101
|
+
module: 'user',
|
|
102
|
+
capability: USER_GET_INFO_METHOD,
|
|
103
|
+
permission: 'user.getInfo',
|
|
104
|
+
risk: 'medium',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
method: SHARE_SHOW_SHARE_MENU_METHOD,
|
|
108
|
+
module: 'share',
|
|
109
|
+
capability: SHARE_SHOW_SHARE_MENU_METHOD,
|
|
110
|
+
permission: 'share.basic',
|
|
111
|
+
risk: 'low',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
method: SHARE_SCREENSHOT_METHOD,
|
|
115
|
+
module: 'share',
|
|
116
|
+
capability: SHARE_SCREENSHOT_METHOD,
|
|
117
|
+
permission: 'share.screenshot',
|
|
118
|
+
risk: 'medium',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
method: VIEWPORT_GET_WINDOW_INFO_METHOD,
|
|
122
|
+
module: 'viewport',
|
|
123
|
+
capability: VIEWPORT_GET_WINDOW_INFO_METHOD,
|
|
124
|
+
permission: 'viewport.windowInfo',
|
|
125
|
+
risk: 'low',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
method: STORAGE_GET_STORAGE_METHOD,
|
|
129
|
+
module: 'storage',
|
|
130
|
+
capability: STORAGE_GET_STORAGE_METHOD,
|
|
131
|
+
permission: 'storage.read',
|
|
132
|
+
risk: 'low',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
method: STORAGE_SET_STORAGE_METHOD,
|
|
136
|
+
module: 'storage',
|
|
137
|
+
capability: STORAGE_SET_STORAGE_METHOD,
|
|
138
|
+
permission: 'storage.write',
|
|
139
|
+
risk: 'medium',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
method: NETWORK_REQUEST_METHOD,
|
|
143
|
+
module: 'network',
|
|
144
|
+
capability: NETWORK_REQUEST_METHOD,
|
|
145
|
+
permission: 'network.request',
|
|
146
|
+
risk: 'high',
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
exports.AUTH_LOGIN_METHOD = AUTH_LOGIN_METHOD;
|
|
151
|
+
exports.MINI_PROGRAM_BRIDGE_NONCE_PARAM = MINI_PROGRAM_BRIDGE_NONCE_PARAM;
|
|
152
|
+
exports.MINI_PROGRAM_MESSAGE_NAMESPACE = MINI_PROGRAM_MESSAGE_NAMESPACE;
|
|
153
|
+
exports.MINI_PROGRAM_MESSAGE_VERSION = MINI_PROGRAM_MESSAGE_VERSION;
|
|
154
|
+
exports.MINI_PROGRAM_PROTOCOL_CAPABILITIES = MINI_PROGRAM_PROTOCOL_CAPABILITIES;
|
|
155
|
+
exports.NETWORK_REQUEST_METHOD = NETWORK_REQUEST_METHOD;
|
|
156
|
+
exports.SDK_HANDSHAKE_METHOD = SDK_HANDSHAKE_METHOD;
|
|
157
|
+
exports.SHARE_SCREENSHOT_METHOD = SHARE_SCREENSHOT_METHOD;
|
|
158
|
+
exports.SHARE_SHOW_SHARE_MENU_METHOD = SHARE_SHOW_SHARE_MENU_METHOD;
|
|
159
|
+
exports.STORAGE_GET_STORAGE_METHOD = STORAGE_GET_STORAGE_METHOD;
|
|
160
|
+
exports.STORAGE_SET_STORAGE_METHOD = STORAGE_SET_STORAGE_METHOD;
|
|
161
|
+
exports.USER_GET_INFO_METHOD = USER_GET_INFO_METHOD;
|
|
162
|
+
exports.VIEWPORT_GET_WINDOW_INFO_METHOD = VIEWPORT_GET_WINDOW_INFO_METHOD;
|
|
163
|
+
exports.isMiniProgramBridgeMessage = isMiniProgramBridgeMessage;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/** 小程序沙盒通信命名空间,父容器与 iframe 内 SDK 必须保持一致。 */
|
|
2
|
+
const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
|
|
3
|
+
/** 小程序沙盒通信协议版本。 */
|
|
4
|
+
const MINI_PROGRAM_MESSAGE_VERSION = 1;
|
|
5
|
+
/** 父容器注入到小程序 URL 上的通信 nonce 参数名。 */
|
|
6
|
+
const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
|
|
7
|
+
/** SDK 初始化时发给父容器的握手方法名。 */
|
|
8
|
+
const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 判断未知数据是否符合小程序 bridge 消息信封。
|
|
12
|
+
*
|
|
13
|
+
* @param value 待判断的未知数据。
|
|
14
|
+
* @returns 当数据满足小程序 bridge 消息基础结构时返回 `true`。
|
|
15
|
+
*/
|
|
16
|
+
function isMiniProgramBridgeMessage(value) {
|
|
17
|
+
if (!value || typeof value !== 'object') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const message = value;
|
|
21
|
+
return (message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
|
|
22
|
+
message.version === MINI_PROGRAM_MESSAGE_VERSION &&
|
|
23
|
+
typeof message.nonce === 'string' &&
|
|
24
|
+
typeof message.type === 'string');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 登录授权能力方法名。
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
32
|
+
*/
|
|
33
|
+
const AUTH_LOGIN_METHOD = 'auth.login';
|
|
34
|
+
/**
|
|
35
|
+
* 用户信息能力方法名。
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
39
|
+
*/
|
|
40
|
+
const USER_GET_INFO_METHOD = 'user.getInfo';
|
|
41
|
+
/**
|
|
42
|
+
* 展示分享面板能力方法名。
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
46
|
+
*/
|
|
47
|
+
const SHARE_SHOW_SHARE_MENU_METHOD = 'share.showShareMenu';
|
|
48
|
+
/**
|
|
49
|
+
* 截图分享能力方法名。
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
53
|
+
*/
|
|
54
|
+
const SHARE_SCREENSHOT_METHOD = 'share.screenshot';
|
|
55
|
+
/**
|
|
56
|
+
* 视口窗口信息能力方法名。
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
60
|
+
*/
|
|
61
|
+
const VIEWPORT_GET_WINDOW_INFO_METHOD = 'viewport.getWindowInfo';
|
|
62
|
+
/**
|
|
63
|
+
* 读取小程序隔离 storage 能力方法名。
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
67
|
+
*/
|
|
68
|
+
const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage';
|
|
69
|
+
/**
|
|
70
|
+
* 写入小程序隔离 storage 能力方法名。
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
74
|
+
*/
|
|
75
|
+
const STORAGE_SET_STORAGE_METHOD = 'storage.setStorage';
|
|
76
|
+
/**
|
|
77
|
+
* 发起网络请求能力方法名。
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
|
|
81
|
+
*/
|
|
82
|
+
const NETWORK_REQUEST_METHOD = 'network.request';
|
|
83
|
+
/**
|
|
84
|
+
* 小程序开放能力目录。
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* 新增 bridge method 时应先更新这里,再分别补齐 SDK 模块、runtime handler 与测试。
|
|
88
|
+
*/
|
|
89
|
+
const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
|
|
90
|
+
{
|
|
91
|
+
method: AUTH_LOGIN_METHOD,
|
|
92
|
+
module: 'auth',
|
|
93
|
+
capability: AUTH_LOGIN_METHOD,
|
|
94
|
+
permission: 'auth.login',
|
|
95
|
+
risk: 'medium',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
method: USER_GET_INFO_METHOD,
|
|
99
|
+
module: 'user',
|
|
100
|
+
capability: USER_GET_INFO_METHOD,
|
|
101
|
+
permission: 'user.getInfo',
|
|
102
|
+
risk: 'medium',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
method: SHARE_SHOW_SHARE_MENU_METHOD,
|
|
106
|
+
module: 'share',
|
|
107
|
+
capability: SHARE_SHOW_SHARE_MENU_METHOD,
|
|
108
|
+
permission: 'share.basic',
|
|
109
|
+
risk: 'low',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
method: SHARE_SCREENSHOT_METHOD,
|
|
113
|
+
module: 'share',
|
|
114
|
+
capability: SHARE_SCREENSHOT_METHOD,
|
|
115
|
+
permission: 'share.screenshot',
|
|
116
|
+
risk: 'medium',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
method: VIEWPORT_GET_WINDOW_INFO_METHOD,
|
|
120
|
+
module: 'viewport',
|
|
121
|
+
capability: VIEWPORT_GET_WINDOW_INFO_METHOD,
|
|
122
|
+
permission: 'viewport.windowInfo',
|
|
123
|
+
risk: 'low',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
method: STORAGE_GET_STORAGE_METHOD,
|
|
127
|
+
module: 'storage',
|
|
128
|
+
capability: STORAGE_GET_STORAGE_METHOD,
|
|
129
|
+
permission: 'storage.read',
|
|
130
|
+
risk: 'low',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
method: STORAGE_SET_STORAGE_METHOD,
|
|
134
|
+
module: 'storage',
|
|
135
|
+
capability: STORAGE_SET_STORAGE_METHOD,
|
|
136
|
+
permission: 'storage.write',
|
|
137
|
+
risk: 'medium',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
method: NETWORK_REQUEST_METHOD,
|
|
141
|
+
module: 'network',
|
|
142
|
+
capability: NETWORK_REQUEST_METHOD,
|
|
143
|
+
permission: 'network.request',
|
|
144
|
+
risk: 'high',
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
export { AUTH_LOGIN_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NETWORK_REQUEST_METHOD, SDK_HANDSHAKE_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, USER_GET_INFO_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, isMiniProgramBridgeMessage };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# <%= projectName %>
|
|
2
|
+
|
|
3
|
+
这是通过 `hb-sdk create` 生成的黑盒外部小程序开发模板。项目使用 Vue 3、Vite、TypeScript 和 `@heybox/hb-sdk`。
|
|
4
|
+
|
|
5
|
+
## 使用命令
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev
|
|
10
|
+
npm run typecheck
|
|
11
|
+
npm run test:unit
|
|
12
|
+
npm run build
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 开发模式
|
|
16
|
+
|
|
17
|
+
- `npm run dev`:启动本地 Vite 服务和 `hb-sdk` 内置 mock runtime host,适合本地调试 SDK 能力;调试页内可点击按钮在 Mac 版 APP 中启动同一页面。
|
|
18
|
+
- `npm run build`:先执行 TypeScript 检查,再构建生产产物。
|
|
19
|
+
|
|
20
|
+
## 更多能力
|
|
21
|
+
|
|
22
|
+
模板页面只保留最小接入示例。其他常用能力可以直接从 `@heybox/hb-sdk` 调用:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import hbSDK from '@heybox/hb-sdk';
|
|
26
|
+
|
|
27
|
+
await hbSDK.share.showShareMenu({
|
|
28
|
+
title: '<%= projectName %>',
|
|
29
|
+
desc: '分享描述',
|
|
30
|
+
url: window.location.href,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await hbSDK.storage.setStorage({
|
|
34
|
+
key: 'settings',
|
|
35
|
+
data: { theme: 'dark' },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const response = await hbSDK.network.request({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
url: 'https://jsonplaceholder.typicode.com/todos/1',
|
|
41
|
+
});
|
|
42
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title><%= projectName %></title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.ts"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= packageName %>",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "hb-sdk dev",
|
|
8
|
+
"build": "vue-tsc --noEmit && vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"typecheck": "vue-tsc --noEmit",
|
|
11
|
+
"test:unit": "vitest run",
|
|
12
|
+
"test:unit:watch": "vitest"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@heybox/hb-sdk": "^<%= sdkVersion %>",
|
|
16
|
+
"vue": "^3.5.34"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^25.7.0",
|
|
20
|
+
"@vitejs/plugin-vue": "^6.0.6",
|
|
21
|
+
"@vue/test-utils": "^2.4.10",
|
|
22
|
+
"happy-dom": "^20.9.0",
|
|
23
|
+
"typescript": "^6.0.3",
|
|
24
|
+
"vite": "^8.0.12",
|
|
25
|
+
"vitest": "^4.1.6",
|
|
26
|
+
"vue-tsc": "^3.2.9"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<main class="page">
|
|
3
|
+
<section class="card">
|
|
4
|
+
<p class="eyebrow">Heybox Mini Program</p>
|
|
5
|
+
<h1><%= projectName %></h1>
|
|
6
|
+
<p class="intro">
|
|
7
|
+
这个模板只保留最小接入示例:等待 SDK ready、读取用户信息,并在需要时唤起登录。
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p class="status" data-testid="status">{{ status }}</p>
|
|
11
|
+
|
|
12
|
+
<button type="button" :disabled="loading" data-testid="login" @click="login">
|
|
13
|
+
登录并刷新用户信息
|
|
14
|
+
</button>
|
|
15
|
+
|
|
16
|
+
<pre data-testid="output">{{ output }}</pre>
|
|
17
|
+
</section>
|
|
18
|
+
</main>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import hbSDK from '@heybox/hb-sdk';
|
|
23
|
+
import { onMounted, ref } from 'vue';
|
|
24
|
+
|
|
25
|
+
const loading = ref(false);
|
|
26
|
+
const status = ref('正在连接 SDK...');
|
|
27
|
+
const output = ref('等待 user.getInfo 返回结果。');
|
|
28
|
+
|
|
29
|
+
onMounted(() => {
|
|
30
|
+
void loadUserInfo();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
async function loadUserInfo() {
|
|
34
|
+
await runSdkAction('user.getInfo', async () => {
|
|
35
|
+
await hbSDK.ready();
|
|
36
|
+
return hbSDK.user.getInfo();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function login() {
|
|
41
|
+
await runSdkAction('auth.login', () => hbSDK.auth.login());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function runSdkAction(label: string, action: () => Promise<unknown>) {
|
|
45
|
+
loading.value = true;
|
|
46
|
+
status.value = `${label} 调用中...`;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const result = await action();
|
|
50
|
+
status.value = `${label} 调用成功`;
|
|
51
|
+
output.value = JSON.stringify(result, null, 2);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
status.value = `${label} 调用失败`;
|
|
54
|
+
output.value = readErrorMessage(error);
|
|
55
|
+
} finally {
|
|
56
|
+
loading.value = false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function readErrorMessage(error: unknown) {
|
|
61
|
+
return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { flushPromises, mount } from '@vue/test-utils';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import App from '../App.vue';
|
|
4
|
+
|
|
5
|
+
const sdkMock = vi.hoisted(() => ({
|
|
6
|
+
authLogin: vi.fn(),
|
|
7
|
+
ready: vi.fn(),
|
|
8
|
+
userGetInfo: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
vi.mock('@heybox/hb-sdk', () => ({
|
|
12
|
+
default: {
|
|
13
|
+
auth: {
|
|
14
|
+
login: sdkMock.authLogin,
|
|
15
|
+
},
|
|
16
|
+
ready: sdkMock.ready,
|
|
17
|
+
user: {
|
|
18
|
+
getInfo: sdkMock.userGetInfo,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
describe('App', () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
vi.resetAllMocks();
|
|
26
|
+
|
|
27
|
+
sdkMock.ready.mockResolvedValue(undefined);
|
|
28
|
+
sdkMock.userGetInfo.mockResolvedValue({
|
|
29
|
+
isLogin: true,
|
|
30
|
+
userInfo: {
|
|
31
|
+
avatar: '',
|
|
32
|
+
heybox_id: '10001',
|
|
33
|
+
nickname: '模板用户',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
sdkMock.authLogin.mockResolvedValue({
|
|
37
|
+
isLogin: true,
|
|
38
|
+
userInfo: {
|
|
39
|
+
avatar: '',
|
|
40
|
+
heybox_id: '10002',
|
|
41
|
+
nickname: '登录用户',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('connects to hb-sdk and renders user info', async () => {
|
|
47
|
+
const wrapper = mount(App);
|
|
48
|
+
await flushPromises();
|
|
49
|
+
|
|
50
|
+
expect(sdkMock.ready).toHaveBeenCalledTimes(1);
|
|
51
|
+
expect(sdkMock.userGetInfo).toHaveBeenCalledTimes(1);
|
|
52
|
+
expect(wrapper.get('[data-testid="status"]').text()).toBe('user.getInfo 调用成功');
|
|
53
|
+
expect(wrapper.get('[data-testid="output"]').text()).toContain('模板用户');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('logs in and refreshes the output', async () => {
|
|
57
|
+
const wrapper = mount(App);
|
|
58
|
+
await flushPromises();
|
|
59
|
+
|
|
60
|
+
await wrapper.get('[data-testid="login"]').trigger('click');
|
|
61
|
+
await flushPromises();
|
|
62
|
+
|
|
63
|
+
expect(sdkMock.authLogin).toHaveBeenCalledTimes(1);
|
|
64
|
+
expect(wrapper.get('[data-testid="status"]').text()).toBe('auth.login 调用成功');
|
|
65
|
+
expect(wrapper.get('[data-testid="output"]').text()).toContain('登录用户');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color: #1f2933;
|
|
3
|
+
background: #f4f6f8;
|
|
4
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
5
|
+
line-height: 1.5;
|
|
6
|
+
}
|
|
7
|
+
* {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
body {
|
|
11
|
+
margin: 0; min-width: 320px;
|
|
12
|
+
}
|
|
13
|
+
.page {
|
|
14
|
+
width: min(100%, 720px);
|
|
15
|
+
margin: 0 auto;
|
|
16
|
+
padding: 40px 20px;
|
|
17
|
+
}
|
|
18
|
+
.card {
|
|
19
|
+
border: 1px solid #d8dee6;
|
|
20
|
+
border-radius: 8px;
|
|
21
|
+
background: #fff;
|
|
22
|
+
padding: 24px;
|
|
23
|
+
}
|
|
24
|
+
.eyebrow {
|
|
25
|
+
margin: 0 0 8px;
|
|
26
|
+
color: #287a4b;
|
|
27
|
+
font-size: 13px;
|
|
28
|
+
font-weight: 800;
|
|
29
|
+
}
|
|
30
|
+
h1 {
|
|
31
|
+
margin: 0; font-size: 36px; line-height: 1.1;
|
|
32
|
+
}
|
|
33
|
+
.intro,
|
|
34
|
+
.status {
|
|
35
|
+
color: #52616f;
|
|
36
|
+
}
|
|
37
|
+
button {
|
|
38
|
+
width: 100%;
|
|
39
|
+
min-height: 42px;
|
|
40
|
+
border: 0;
|
|
41
|
+
border-radius: 6px;
|
|
42
|
+
background: #1f2933;
|
|
43
|
+
color: #fff;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
font: inherit;
|
|
46
|
+
font-weight: 700;
|
|
47
|
+
}
|
|
48
|
+
button:disabled {
|
|
49
|
+
cursor: not-allowed; opacity: 0.6;
|
|
50
|
+
}
|
|
51
|
+
pre {
|
|
52
|
+
margin: 16px 0 0;
|
|
53
|
+
overflow: auto;
|
|
54
|
+
border-radius: 6px;
|
|
55
|
+
background: #101820;
|
|
56
|
+
color: #f7fbff;
|
|
57
|
+
padding: 14px;
|
|
58
|
+
white-space: pre-wrap;
|
|
59
|
+
word-break: break-word;
|
|
60
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"jsx": "preserve",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
14
|
+
"types": ["vite/client"]
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
|
17
|
+
}
|