@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.
Files changed (67) hide show
  1. package/README.md +149 -345
  2. package/bin/hb-sdk.cjs +3 -0
  3. package/dist/cli.cjs +10117 -0
  4. package/dist/devtools/mock-host/index.html +252 -0
  5. package/dist/devtools/mock-host/main.js +975 -0
  6. package/dist/index.cjs.js +474 -85
  7. package/dist/index.esm.js +465 -71
  8. package/dist/protocol.cjs.js +163 -0
  9. package/dist/protocol.esm.js +148 -0
  10. package/dist/templates/vue3-vite-ts/.gitignore.ejs +5 -0
  11. package/dist/templates/vue3-vite-ts/README.md.ejs +42 -0
  12. package/dist/templates/vue3-vite-ts/index.html.ejs +12 -0
  13. package/dist/templates/vue3-vite-ts/package.json.ejs +28 -0
  14. package/dist/templates/vue3-vite-ts/src/App.vue +63 -0
  15. package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +67 -0
  16. package/dist/templates/vue3-vite-ts/src/main.ts +5 -0
  17. package/dist/templates/vue3-vite-ts/src/styles.css +60 -0
  18. package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +1 -0
  19. package/dist/templates/vue3-vite-ts/tsconfig.app.json +17 -0
  20. package/dist/templates/vue3-vite-ts/tsconfig.json +11 -0
  21. package/dist/templates/vue3-vite-ts/tsconfig.node.json +11 -0
  22. package/dist/templates/vue3-vite-ts/vite.config.ts +6 -0
  23. package/dist/templates/vue3-vite-ts/vitest.config.ts +10 -0
  24. package/package.json +30 -5
  25. package/skill/SKILL.md +95 -0
  26. package/skill/references/api-protocol.md +135 -0
  27. package/skill/references/api-root.md +346 -0
  28. package/skill/references/cli.md +360 -0
  29. package/skill/references/examples.md +107 -0
  30. package/skill/references/llms-index.md +44 -0
  31. package/skill/references/recipes.md +374 -0
  32. package/skill/references/safety-boundaries.md +28 -0
  33. package/skill/references/smoke-evaluation.md +24 -0
  34. package/skill/scripts/check-references.mjs +14 -0
  35. package/skill/scripts/package-skill.mjs +60 -0
  36. package/skill/scripts/package-skill.sh +6 -0
  37. package/skill/scripts/skill-metadata.mjs +74 -0
  38. package/skill/scripts/sync-references.mjs +541 -0
  39. package/skill/scripts/validate-skill.mjs +233 -0
  40. package/skill/skill.json +11 -0
  41. package/types/core/client.d.ts +23 -3
  42. package/types/core/errors.d.ts +45 -2
  43. package/types/core/sdk.d.ts +78 -10
  44. package/types/core/singleton.d.ts +33 -7
  45. package/types/core/utils.d.ts +2 -0
  46. package/types/index.d.ts +14 -6
  47. package/types/modules/auth/index.d.ts +35 -0
  48. package/types/modules/network/index.d.ts +120 -0
  49. package/types/modules/share/index.d.ts +9 -5
  50. package/types/modules/share/screenshot.d.ts +9 -3
  51. package/types/modules/share/show-share-menu.d.ts +9 -3
  52. package/types/modules/share/types.d.ts +24 -4
  53. package/types/modules/storage/index.d.ts +56 -0
  54. package/types/modules/user/get-info.d.ts +6 -2
  55. package/types/modules/user/index.d.ts +8 -10
  56. package/types/modules/user/types.d.ts +1 -0
  57. package/types/modules/viewport/index.d.ts +71 -0
  58. package/types/protocol/capabilities.d.ts +180 -0
  59. package/types/protocol/guards.d.ts +6 -1
  60. package/types/protocol/types.d.ts +19 -4
  61. package/types/protocol.d.ts +13 -0
  62. package/types/modules/system/get-storage.d.ts +0 -15
  63. package/types/modules/system/get-window-info.d.ts +0 -16
  64. package/types/modules/system/index.d.ts +0 -23
  65. package/types/modules/system/set-storage.d.ts +0 -12
  66. package/types/modules/system/types.d.ts +0 -34
  67. package/types/modules/user/login.d.ts +0 -18
package/README.md CHANGED
@@ -1,466 +1,270 @@
1
1
  # @heybox/hb-sdk
2
2
 
3
- 面向黑盒外部小程序 iframe 沙盒的前端 SDK。它负责与父容器完成握手、收发 bridge 消息,并以受控模块的形式向外部小程序开放用户、分享、系统信息和隔离 storage 能力。
3
+ 黑盒外部小程序前端 SDK。业务页面运行在黑盒父容器创建的 iframe 沙盒中,通过这个 SDK 等待容器 ready、获取登录态、唤起登录、分享、读取窗口信息、使用隔离 storage,以及发起受控网络请求。
4
4
 
5
- ## 为什么需要它
6
-
7
- 外部小程序运行在父容器创建的 iframe 沙盒中,业务页面不能直接读取主站登录态,也不应该关心底层 `postMessage` 协议、nonce 校验、请求响应关联、超时清理、客户端协议参数过滤等细节。
5
+ ## 快速开始
8
6
 
9
- `@heybox/hb-sdk` 将这些通信细节封装为稳定接口,让小程序只通过被允许的能力访问父容器。父容器仍负责调用黑盒客户端协议,并在运行时过滤不适合开放给外部小程序的内部参数。
7
+ 创建一个新的外部小程序项目:
10
8
 
11
- ## 当前对外导出
9
+ ```bash
10
+ npx @heybox/hb-sdk create my-miniapp
11
+ cd my-miniapp
12
+ npm install
13
+ npm run dev
14
+ ```
12
15
 
13
- > `src/index.ts` 为准;历史目录、旧示例或构建产物若与当前入口不一致,以当前源码导出能力为准。
16
+ 模板默认使用 Vue 3、Vite、TypeScript 和 npm。`npm run dev` 会启动小程序页面服务,并打开 `hb-sdk` 内置的浏览器 mock 宿主环境,适合在普通浏览器里调试 SDK 能力;调试页内可点击按钮在 Mac 版 APP 中启动同一页面。
14
17
 
15
- - 默认导出 `hbSDK`:包含 `ready`、`on`、`off`、`user`、`share`、`system`。
16
- - 命名导出 `ready` / `on` / `off` / `user` / `share` / `system`:默认 SDK 单例能力。
17
- - `createMiniProgramSDK` / `MiniProgramSDK`:创建独立 SDK 实例,适合测试、多实例或显式生命周期管理场景。
18
- - `HbMiniProgramSDKError`:SDK 对外抛出的标准错误类型。
19
- - `MiniProgramRequester` / `MiniProgramSDKOptions`:底层请求与 SDK 初始化配置类型。
20
- - bridge 协议常量、类型与守卫:`MINI_PROGRAM_MESSAGE_NAMESPACE`、`MINI_PROGRAM_MESSAGE_VERSION`、`MINI_PROGRAM_BRIDGE_NONCE_PARAM`、`SDK_HANDSHAKE_METHOD`、`isMiniProgramBridgeMessage` 等。
21
- - 模块类型与方法常量:`MiniProgramUserModule`、`MiniProgramShareModule`、`MiniProgramSystemModule` 以及各模块 method 常量。
18
+ 在已有项目中安装:
22
19
 
23
- ## 快速开始
20
+ ```bash
21
+ npm install @heybox/hb-sdk
22
+ ```
24
23
 
25
- 最小示例:
24
+ 然后在页面入口等待父容器 ready:
26
25
 
27
26
  ```ts
28
27
  import hbSDK from '@heybox/hb-sdk';
29
28
 
30
29
  await hbSDK.ready();
31
30
 
32
- const result = await hbSDK.user.getInfo();
31
+ const user = await hbSDK.user.getInfo();
33
32
 
34
- if (result.isLogin) {
35
- console.log(result.userInfo.nickname);
33
+ if (user.isLogin) {
34
+ console.log(user.userInfo.nickname);
36
35
  }
37
36
  ```
38
37
 
39
- 按需导入:
38
+ 也可以按需导入:
40
39
 
41
40
  ```ts
42
- import { on, ready, user } from '@heybox/hb-sdk';
43
-
44
- const unsubscribe = on('show', (payload) => {
45
- console.log('小程序展示', payload.timestamp, payload.source);
46
- });
41
+ import { auth, ready, user } from '@heybox/hb-sdk';
47
42
 
48
43
  await ready();
49
44
 
50
45
  const currentUser = await user.getInfo();
51
46
 
52
- unsubscribe();
53
- ```
54
-
55
- 分享与 storage:
56
-
57
- ```ts
58
- import { share, system } from '@heybox/hb-sdk';
59
-
60
- await share.showShareMenu({
61
- title: '分享标题',
62
- desc: '分享描述',
63
- url: 'https://web.xiaoheihe.cn/tools/demo',
64
- imageUrl: 'https://imgheybox.max-c.com/demo.png',
65
- });
66
-
67
- await system.setStorage({
68
- key: 'settings',
69
- data: {
70
- theme: 'dark',
71
- },
72
- });
73
-
74
- const { data } = await system.getStorage<{ theme: string }>({
75
- key: 'settings',
76
- });
77
- ```
78
-
79
- ## 核心概念
80
-
81
- ### 默认单例
82
-
83
- 普通小程序页面优先使用默认导出的 `hbSDK`,或直接按需导入 `ready`、`on`、`off`、`user`、`share`、`system`。默认单例会在首次调用时懒创建,业务不需要手动初始化。
84
-
85
- ```ts
86
- import { ready, system } from '@heybox/hb-sdk';
87
-
88
- await ready();
89
- const windowInfo = await system.getWindowInfo();
47
+ if (!currentUser.isLogin) {
48
+ await auth.login();
49
+ }
90
50
  ```
91
51
 
92
- ### 独立实例
93
-
94
- 需要显式控制生命周期、注入测试环境 window、调整超时时间,或同页存在多套沙盒通信上下文时,可以使用 `createMiniProgramSDK`。
95
-
96
- ```ts
97
- import { createMiniProgramSDK } from '@heybox/hb-sdk';
98
-
99
- const sdk = createMiniProgramSDK({
100
- timeout: 5000,
101
- });
102
-
103
- await sdk.ready();
52
+ ## 运行环境
104
53
 
105
- const loginResult = await sdk.user.login();
54
+ SDK 需要在黑盒小程序 iframe 容器内运行。父容器会为页面注入 bridge nonce,并通过 `postMessage` 与 SDK 通信。普通浏览器直接打开小程序页面时通常无法完成握手;本地开发请优先使用:
106
55
 
107
- sdk.destroy();
56
+ ```bash
57
+ npm run dev
108
58
  ```
109
59
 
110
- ### bridge 通信
111
-
112
- SDK 与父容器之间通过 `postMessage` 通信,消息会带上固定命名空间、协议版本与 iframe 实例 nonce。SDK 内部负责:
60
+ 调试页会通过 iframe 加载本地页面并补齐小程序 bridge 环境;如果需要真实黑盒小程序容器加载同一页面,点击调试页里的「在 Mac 版 APP 中启动」按钮。
113
61
 
114
- - URL query 读取 `hb_mini_bridge_nonce`,也支持通过 `MiniProgramSDKOptions.nonce` 显式传入。
115
- - 向父容器发送 `sdk.handshake` 握手消息;如果还没有收到 `ready` 事件,会在总超时窗口内短间隔重试。
116
- - 为每次能力调用生成请求 ID,匹配父容器返回的 response。
117
- - 过滤非小程序消息、非当前 nonce 消息以及非目标父窗口消息。
118
- - 处理请求超时、握手总超时和销毁后的未完成请求。
119
-
120
- 父容器应幂等响应握手:重复 `sdk.handshake` 只代表 SDK 在补偿早期消息丢失,父容器可以重复派发 `ready`,但不应重复执行一次性启动副作用。
121
-
122
- ### 标准错误
123
-
124
- 请求失败和 SDK 内部错误会统一包装为 `HbMiniProgramSDKError`,包含稳定的 `code`、面向开发者的 `message` 和可选 `data`。
125
-
126
- ```ts
127
- import { HbMiniProgramSDKError, user } from '@heybox/hb-sdk';
62
+ 在未使用脚手架的 Vite 项目中,可以把命令加到 `package.json`:
128
63
 
129
- try {
130
- await user.login();
131
- } catch (error) {
132
- if (error instanceof HbMiniProgramSDKError) {
133
- console.log(error.code, error.message, error.data);
64
+ ```json
65
+ {
66
+ "scripts": {
67
+ "dev": "hb-sdk dev"
134
68
  }
135
69
  }
136
70
  ```
137
71
 
138
- ## 模块说明
139
-
140
- ### Core
141
-
142
- 核心模块位于 `src/core`,负责 SDK 实例、默认单例、bridge client、事件总线、错误和工具函数。
143
-
144
- | 模块 | 作用 | 代表导出 |
145
- | --- | --- | --- |
146
- | `core/sdk` | SDK 实例封装 | `MiniProgramSDK`、`createMiniProgramSDK` |
147
- | `core/singleton` | 默认单例入口 | `ready`、`on`、`off`、`user`、`share`、`system` |
148
- | `core/client` | bridge 握手、请求响应、事件分发 | `MiniProgramSDKOptions`、`MiniProgramRequester` |
149
- | `core/errors` | 标准错误类型 | `HbMiniProgramSDKError` |
150
-
151
- ### User
152
-
153
- 用户模块位于 `src/modules/user`,只暴露允许小程序访问的公开用户能力。
72
+ ## 常用能力
154
73
 
155
- | API | 说明 |
156
- | --- | --- |
157
- | `user.getInfo()` | 获取当前用户登录态与公开基础资料。未登录时不会触发登录流程。 |
158
- | `user.login()` | 唤起黑盒登录流程,并返回登录后的最新用户公开资料。 |
74
+ ### 用户与登录
159
75
 
160
- 用户信息只包含允许暴露给外部小程序的公开字段:
76
+ `user.getInfo()` 只读取当前登录态,不会主动唤起登录。需要用户操作时再调用 `auth.login()`。
161
77
 
162
78
  ```ts
163
- interface MiniProgramUserInfo {
164
- heybox_id: string;
165
- nickname: string;
166
- avatar: string;
167
- }
79
+ import { auth, user } from '@heybox/hb-sdk';
168
80
 
169
- interface MiniProgramUserInfoResult {
170
- isLogin: boolean;
171
- userInfo: MiniProgramUserInfo | null;
81
+ const result = await user.getInfo();
82
+
83
+ if (!result.isLogin) {
84
+ const loginResult = await auth.login();
85
+ console.log(loginResult.userInfo);
172
86
  }
173
87
  ```
174
88
 
175
- SDK 不会向小程序暴露 token、cookie、手机号或任何可用于直接调用主站私有接口的凭据。
89
+ SDK 只返回允许暴露给外部小程序的公开资料,不会返回 token、cookie、手机号或其他私有凭据。
176
90
 
177
- ### Share
178
-
179
- 分享模块位于 `src/modules/share`,对外提供简洁配置,父容器侧再映射到黑盒客户端协议。
180
-
181
- | API | 对应父容器能力 | 说明 |
182
- | --- | --- | --- |
183
- | `share.showShareMenu(options)` | `share.showShareMenu` -> `share` 协议 | 展示基础分享面板。 |
184
- | `share.screenshot(options?)` | `share.screenshot` -> `screenShotShareV2` 协议 | 截图并唤起分享。 |
185
-
186
- 基础分享参数:
91
+ ### 分享
187
92
 
188
93
  ```ts
189
- interface MiniProgramShowShareMenuOptions {
190
- title: string;
191
- desc: string;
192
- url: string;
193
- imageUrl?: string;
194
- channel?: 'wechatSession' | 'wechatTimeline' | 'qqFriend' | 'qzone' | 'weibo';
195
- }
94
+ import { share } from '@heybox/hb-sdk';
95
+
96
+ await share.showShareMenu({
97
+ title: '我的小程序页面',
98
+ desc: '来自黑盒小程序的分享',
99
+ url: window.location.href,
100
+ imageUrl: 'https://imgheybox.max-c.com/demo.png',
101
+ });
196
102
  ```
197
103
 
198
- 截图分享参数:
104
+ 截图分享:
199
105
 
200
106
  ```ts
201
- interface MiniProgramScreenshotOptions {
202
- rect?: {
203
- left: number;
204
- top: number;
205
- width: number;
206
- height: number;
207
- };
208
- delay?: number;
209
- saveToAlbum?: boolean;
210
- }
107
+ await share.screenshot({
108
+ delay: 100,
109
+ saveToAlbum: true,
110
+ });
211
111
  ```
212
112
 
213
- 为了保持外部 API 稳定,`share` 模块不开放 raw protocol、JS callback、活动上报、发帖、自定义按钮、upload-only 等内部能力。
214
-
215
- ### System
216
-
217
- 系统模块位于 `src/modules/system`,当前提供窗口信息与隔离 storage 能力。
113
+ ### 窗口信息
218
114
 
219
- | API | 对应父容器能力 | 说明 |
220
- | --- | --- | --- |
221
- | `system.getWindowInfo()` | `system.getWindowInfo` | 获取窗口、屏幕、安全区域等信息。 |
222
- | `system.getStorage(options)` | `system.getStorage` -> `getStorage` 协议 | 读取小程序隔离 storage。 |
223
- | `system.setStorage(options)` | `system.setStorage` -> `setStorage` 协议 | 写入小程序隔离 storage。 |
115
+ ```ts
116
+ import { viewport } from '@heybox/hb-sdk';
224
117
 
225
- `getWindowInfo()` 返回字段对齐微信小程序 `wx.getWindowInfo` 的常用字段:
118
+ const windowInfo = await viewport.getWindowInfo();
226
119
 
227
- ```ts
228
- interface MiniProgramWindowInfoResult {
229
- pixelRatio: number;
230
- screenWidth: number;
231
- screenHeight: number;
232
- windowWidth: number;
233
- windowHeight: number;
234
- statusBarHeight: number;
235
- safeArea: {
236
- left: number;
237
- right: number;
238
- top: number;
239
- bottom: number;
240
- width: number;
241
- height: number;
242
- };
243
- screenTop: number;
244
- }
120
+ console.log(windowInfo.windowWidth, windowInfo.windowHeight, windowInfo.safeArea.top);
245
121
  ```
246
122
 
247
- storage API:
123
+ ### 隔离 Storage
248
124
 
249
125
  ```ts
250
- await system.setStorage({
126
+ import { storage } from '@heybox/hb-sdk';
127
+
128
+ await storage.setStorage({
251
129
  key: 'settings',
252
130
  data: {
253
- enabled: true,
131
+ theme: 'dark',
254
132
  },
255
133
  });
256
134
 
257
- const result = await system.getStorage<{ enabled: boolean }>({
135
+ const { data } = await storage.getStorage<{ theme: string }>({
258
136
  key: 'settings',
259
137
  });
260
138
  ```
261
139
 
262
- storage 只开放 `get` / `set`,不开放 `removeStorage`、`clearStorage`、`getStorageInfo`、`getStorageV2`。父容器会强制加小程序级命名空间,外部小程序不能读写黑盒客户端全局 storage key。用户传入的 `key` 只允许 1-128 位字母、数字、下划线和连字符。
263
-
264
- ### Protocol
265
-
266
- 协议模块位于 `src/protocol`,定义父容器与 iframe SDK 之间的消息格式、事件名、事件 payload 映射、协议常量和消息守卫。
267
-
268
- 当前支持的小程序事件:
269
-
270
- - `launch`:小程序首次完成握手并启动。
271
- - `ready`:SDK 已可安全调用开放能力。
272
- - `show`:小程序页面展示。
273
- - `hide`:小程序页面隐藏。
274
- - `unload`:小程序页面即将卸载。
275
- - `error`:父容器或开放能力运行异常。
276
- - `authChange`:登录状态发生变化后的最新用户信息。
277
-
278
- ## 常见场景示例
279
-
280
- ### 场景 1:进入页面后获取用户信息
281
-
282
- ```ts
283
- import { ready, user } from '@heybox/hb-sdk';
284
-
285
- await ready();
286
-
287
- const result = await user.getInfo();
288
-
289
- if (!result.isLogin) {
290
- // 可按业务需要展示登录按钮,不会在 getInfo 阶段自动唤起登录。
291
- return;
292
- }
293
-
294
- renderUser(result.userInfo);
295
- ```
296
-
297
- ### 场景 2:点击按钮唤起登录
140
+ storage key 只允许 1-128 位字母、数字、下划线和连字符。父容器会按小程序维度隔离 key,外部小程序不能读写黑盒客户端全局 storage。
298
141
 
299
- ```ts
300
- import { user } from '@heybox/hb-sdk';
301
-
302
- async function handleLoginClick() {
303
- const result = await user.login();
142
+ ### 网络请求
304
143
 
305
- if (result.isLogin) {
306
- renderUser(result.userInfo);
307
- }
308
- }
309
- ```
310
-
311
- ### 场景 3:展示分享面板
144
+ `network.request()` 提供窄化的 axios-like 接口。SDK 只接受公开请求字段,真实请求由父容器运行时映射到宿主网络能力。
312
145
 
313
146
  ```ts
314
- import { share } from '@heybox/hb-sdk';
147
+ import { HbMiniProgramNetworkError, network } from '@heybox/hb-sdk';
315
148
 
316
- async function handleShareClick() {
317
- await share.showShareMenu({
318
- title: '我的小程序页面',
319
- desc: '来自黑盒小程序的分享',
320
- url: location.href,
321
- imageUrl: 'https://imgheybox.max-c.com/demo.png',
322
- channel: 'wechatSession',
149
+ try {
150
+ const response = await network.request<{ ok: boolean }>({
151
+ url: 'https://api.example.com/demo',
152
+ method: 'GET',
153
+ headers: {
154
+ accept: 'application/json',
155
+ },
323
156
  });
324
- }
325
- ```
326
-
327
- ### 场景 4:截图分享当前页面
328
-
329
- ```ts
330
- import { share } from '@heybox/hb-sdk';
331
157
 
332
- async function handleScreenshotShare() {
333
- await share.screenshot({
334
- delay: 100,
335
- saveToAlbum: true,
336
- });
158
+ console.log(response.status, response.data.ok);
159
+ } catch (error) {
160
+ if (error instanceof HbMiniProgramNetworkError) {
161
+ console.log(error.response.status, error.response.data);
162
+ }
337
163
  }
338
164
  ```
339
165
 
340
- 也可以指定截图区域:
166
+ 默认只有 `2xx` 会 resolve;`4xx/5xx` 这类已完成 HTTP 响应会抛出 `HbMiniProgramNetworkError`。可以用 `validateStatus` 调整 SDK 本地判定逻辑,函数不会跨 bridge 传给父容器。
341
167
 
342
168
  ```ts
343
- await share.screenshot({
344
- rect: {
345
- left: 0,
346
- top: 0,
347
- width: 375,
348
- height: 667,
349
- },
169
+ await network.request({
170
+ url: 'https://api.example.com/demo',
171
+ validateStatus: status => status < 500,
350
172
  });
351
173
  ```
352
174
 
353
- ### 场景 5:读取窗口信息
175
+ 支持的 HTTP method 为 `GET`、`POST`、`PUT`、`PATCH`、`DELETE`、`HEAD`、`OPTIONS`。
354
176
 
355
- ```ts
356
- import { system } from '@heybox/hb-sdk';
357
-
358
- const windowInfo = await system.getWindowInfo();
359
-
360
- console.log(windowInfo.windowWidth, windowInfo.windowHeight, windowInfo.safeArea.top);
361
- ```
177
+ ## 生命周期事件
362
178
 
363
- ### 场景 6:使用隔离 storage
179
+ 使用 `on()` 监听父容器派发的小程序事件。`on()` 会返回取消监听函数,组件卸载或页面销毁时应及时调用。
364
180
 
365
181
  ```ts
366
- import { system } from '@heybox/hb-sdk';
182
+ import { on } from '@heybox/hb-sdk';
367
183
 
368
- await system.setStorage({
369
- key: 'card_mode',
370
- data: {
371
- enabled: true,
372
- },
184
+ const unsubscribeShow = on('show', payload => {
185
+ console.log('页面展示', payload.timestamp, payload.source);
373
186
  });
374
187
 
375
- const { data } = await system.getStorage<{ enabled: boolean }>({
376
- key: 'card_mode',
188
+ const unsubscribeAuth = on('authChange', payload => {
189
+ console.log('登录态变化', payload.isLogin, payload.userInfo);
377
190
  });
378
191
 
379
- if (data?.enabled) {
380
- enableCardMode();
381
- }
192
+ unsubscribeShow();
193
+ unsubscribeAuth();
382
194
  ```
383
195
 
384
- ### 场景 7:监听生命周期与登录态变化
196
+ 当前可监听事件包括 `launch`、`ready`、`show`、`hide`、`unload`、`error`、`authChange`。
385
197
 
386
- ```ts
387
- import { off, on } from '@heybox/hb-sdk';
198
+ ## 错误处理
388
199
 
389
- const handleShow = (payload) => {
390
- console.log('页面展示', payload.timestamp);
391
- };
200
+ bridge、父容器运行时、协议校验或能力调用失败时会抛出 `HbMiniProgramSDKError`,其中包含稳定的 `code`、开发者可读的 `message` 和可选 `data`。
392
201
 
393
- const handleAuthChange = (payload) => {
394
- console.log('登录态变化', payload.isLogin, payload.userInfo);
395
- };
396
-
397
- on('show', handleShow);
398
- on('authChange', handleAuthChange);
202
+ ```ts
203
+ import { HbMiniProgramSDKError, ready } from '@heybox/hb-sdk';
399
204
 
400
- // 页面销毁时移除监听
401
- off('show', handleShow);
402
- off('authChange', handleAuthChange);
205
+ try {
206
+ await ready();
207
+ } catch (error) {
208
+ if (error instanceof HbMiniProgramSDKError) {
209
+ console.log(error.code, error.message, error.data);
210
+ }
211
+ }
403
212
  ```
404
213
 
405
- 也可以使用 `on` 返回的取消函数:
214
+ 网络请求已完成但 HTTP 状态不满足 `validateStatus` 时会抛出 `HbMiniProgramNetworkError`,其 `response` 字段包含标准化后的 `status`、`headers`、`data` 和原始公共请求配置快照。
406
215
 
407
- ```ts
408
- const unsubscribe = on('hide', (payload) => {
409
- console.log('页面隐藏', payload.timestamp);
410
- });
216
+ ## CLI
411
217
 
412
- unsubscribe();
413
- ```
218
+ `@heybox/hb-sdk` 随包提供 `hb-sdk` CLI。脚手架项目已在 npm scripts 中接好常用命令;已有项目也可以自行添加 scripts。
414
219
 
415
- ### 场景 8:测试中注入通信环境
220
+ | 命令 | 作用 |
221
+ | --- | --- |
222
+ | `hb-sdk create <project-name>` | 创建外部小程序模板。 |
223
+ | `hb-sdk dev` | 启动当前项目的 Vite dev server 和浏览器 mock 宿主环境,并默认打开调试页。 |
224
+ | `hb-sdk login` | 登录 Heybox,并把 CLI 自己需要的登录态保存在本地缓存中。 |
225
+ | `hb-sdk login status` | 查看脱敏后的 CLI 登录态。 |
226
+ | `hb-sdk login clear` | 清理 CLI 登录态。 |
227
+ | `hb-sdk doctor` | 检查本机 `hb-sdk` Agent Skill 是否匹配当前 SDK,并输出手动安装/刷新命令。 |
416
228
 
417
- ```ts
418
- import { createMiniProgramSDK } from '@heybox/hb-sdk';
229
+ CLI 登录态只供 CLI 命令访问黑盒接口时复用,不会注入 iframe SDK,也不会改变 `auth.login()`、`user.getInfo()`、`network.request()` 或 mock 宿主中的用户状态。
419
230
 
420
- const sdk = createMiniProgramSDK({
421
- nonce: 'test_nonce',
422
- selfWindow: window,
423
- targetWindow: parentWindow,
424
- timeout: 100,
425
- });
231
+ CLI 会在成功执行命令后检查 npm registry 上的 `@heybox/hb-sdk@latest`。如果发现新版本,会在 stderr 打印升级提醒;检查失败会静默跳过,不影响当前命令。可通过 `HB_SDK_NO_UPDATE_CHECK=1` 禁用版本提醒。
426
232
 
427
- await sdk.ready();
428
- sdk.destroy();
429
- ```
233
+ ## SDK 与 Runtime
234
+
235
+ `@heybox/hb-sdk` 跑在 iframe 内部,由外部小程序业务页面使用。`@heybox/hb-sdk-runtime` 跑在 iframe 外部,由黑盒宿主壳层使用,负责启动 iframe、注入 nonce、维护 bridge server、注册能力 handler、转发宿主生命周期与登录态变化。
430
236
 
431
- ## 能力边界与注意事项
237
+ 两者共享同一套 bridge 协议。协议字段、事件名或能力 payload 发生变化时,应按同一批次联动升级 SDK 与 runtime;不要只升级其中一侧后假定另一侧自动兼容。
238
+
239
+ ## 能力边界
432
240
 
433
- - SDK 只能在父容器创建的小程序 iframe 沙盒中正常完成握手;非 iframe 环境会抛出 `NOT_IN_IFRAME`。
434
- - 父容器必须在小程序 URL 上注入 `hb_mini_bridge_nonce`,否则会抛出 `MISSING_NONCE`。
435
- - 父容器需要幂等响应 `sdk.handshake`;SDK 会在收到 `ready` 前自动重试握手,不引用 SDK 的普通页面不会触发握手。
436
241
  - 调用模块能力前会自动等待 `ready()`,但业务仍建议在页面启动阶段显式 `await ready()`,便于集中处理握手失败。
437
- - `user.getInfo()` 只查询登录态,不会主动唤起登录。
438
- - `user.login()` 只返回公开用户资料,不返回 token、cookie 或私有凭据。
439
- - `share.showShareMenu()` 只开放基础分享字段,不开放活动任务上报、发帖、自定义按钮等内部协议参数。
440
- - `share.screenshot()` 只做截图并分享,不开放 upload-only 和客户端 JS callback。
441
- - `system.getWindowInfo()` `statusBarHeight`、`screenTop`、`safeArea.top` 在黑盒容器内按顶部可用偏移处理。
442
- - `system.getStorage()` / `system.setStorage()` 只访问小程序隔离 storage;业务 key 必须符合 `/^[A-Za-z0-9_-]{1,128}$/`。
443
- - `on()` 会返回取消监听函数;页面卸载或组件销毁时应及时取消监听。
444
- - 独立实例不再使用时应调用 `destroy()`,以移除 message 监听并拒绝未完成请求。
242
+ - `user.getInfo()` 不会触发登录;登录必须由业务在用户操作后调用 `auth.login()`。
243
+ - 分享、截图、storage 和网络请求只开放稳定窄接口,不透传黑盒客户端内部协议参数。
244
+ - `network.request()` 的 `validateStatus` 只在 SDK 本地执行,不会被序列化给父容器。
245
+ - `on()` 返回取消监听函数;组件卸载或页面销毁时应主动取消监听。
246
+ - 使用 `createMiniProgramSDK()` 创建独立实例后,不再需要时应调用 `destroy()`。
445
247
 
446
- ## 开发命令
248
+ ## 导出
447
249
 
448
- 优先使用仓库统一的 `hbexec` 入口:
250
+ 默认导出 `hbSDK`,包含 `ready`、`on`、`off`、`auth`、`user`、`share`、`viewport`、`storage`、`network`。
449
251
 
450
- ```bash
451
- # 运行单元测试
452
- pnpm exec hbexec test unit @heybox/hb-sdk
252
+ 常用命名导出:
453
253
 
454
- # 构建产物与类型声明
455
- pnpm exec hbexec build package -d packages/hb-sdk
456
- ```
254
+ - `ready`、`on`、`off`
255
+ - `auth`、`user`、`share`、`viewport`、`storage`、`network`
256
+ - `createMiniProgramSDK`、`MiniProgramSDK`
257
+ - `HbMiniProgramSDKError`、`HbMiniProgramNetworkError`
258
+ - 各模块公开类型,例如 `MiniProgramNetworkRequestConfig`、`MiniProgramNetworkResponse`、`MiniProgramUserInfoResult`
259
+
260
+ 协议常量、消息类型和守卫仍通过根入口与 `@heybox/hb-sdk/protocol` 子入口导出。宿主运行时等非业务页面代码应优先使用 `@heybox/hb-sdk/protocol`。
457
261
 
458
- 也可以直接运行包内脚本:
262
+ ## 本仓库开发
459
263
 
460
264
  ```bash
461
- # 运行单元测试
462
265
  pnpm --filter @heybox/hb-sdk run test:unit
463
-
464
- # 运行单元测试并生成覆盖率
465
- pnpm --filter @heybox/hb-sdk run test:unit:coverage
266
+ pnpm --filter @heybox/hb-sdk run build:package
267
+ pnpm --filter @heybox/hb-sdk run check:boundary
466
268
  ```
269
+
270
+ `check:boundary` 用于保护 SDK、CLI、mock host 与 runtime 之间的依赖边界。调整 CLI、mock 或协议导出时应一起运行。
package/bin/hb-sdk.cjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/cli.cjs').runCli();