@heybox/hb-sdk 0.1.3 → 0.2.0-alpha.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.
Files changed (49) hide show
  1. package/README.md +167 -37
  2. package/bin/hb-sdk.cjs +3 -0
  3. package/dist/cli.cjs +9639 -0
  4. package/dist/devtools/mock-host/index.html +626 -0
  5. package/dist/index.cjs.js +477 -75
  6. package/dist/index.esm.js +463 -70
  7. package/dist/protocol.cjs.js +104 -0
  8. package/dist/protocol.esm.js +90 -0
  9. package/dist/templates/vue3-vite-ts/.gitignore.ejs +5 -0
  10. package/dist/templates/vue3-vite-ts/README.md.ejs +46 -0
  11. package/dist/templates/vue3-vite-ts/index.html.ejs +12 -0
  12. package/dist/templates/vue3-vite-ts/package.json.ejs +29 -0
  13. package/dist/templates/vue3-vite-ts/src/App.vue +63 -0
  14. package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +67 -0
  15. package/dist/templates/vue3-vite-ts/src/main.ts +5 -0
  16. package/dist/templates/vue3-vite-ts/src/styles.css +60 -0
  17. package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +1 -0
  18. package/dist/templates/vue3-vite-ts/tsconfig.app.json +17 -0
  19. package/dist/templates/vue3-vite-ts/tsconfig.json +11 -0
  20. package/dist/templates/vue3-vite-ts/tsconfig.node.json +11 -0
  21. package/dist/templates/vue3-vite-ts/vite.config.ts +6 -0
  22. package/dist/templates/vue3-vite-ts/vitest.config.ts +10 -0
  23. package/package.json +28 -5
  24. package/types/core/client.d.ts +23 -3
  25. package/types/core/errors.d.ts +45 -2
  26. package/types/core/sdk.d.ts +78 -10
  27. package/types/core/singleton.d.ts +33 -7
  28. package/types/core/utils.d.ts +2 -0
  29. package/types/index.d.ts +10 -4
  30. package/types/modules/auth/index.d.ts +42 -0
  31. package/types/modules/network/index.d.ts +125 -0
  32. package/types/modules/share/index.d.ts +12 -2
  33. package/types/modules/share/screenshot.d.ts +14 -2
  34. package/types/modules/share/show-share-menu.d.ts +14 -2
  35. package/types/modules/share/types.d.ts +24 -4
  36. package/types/modules/storage/index.d.ts +70 -0
  37. package/types/modules/user/get-info.d.ts +11 -1
  38. package/types/modules/user/index.d.ts +13 -9
  39. package/types/modules/user/types.d.ts +1 -0
  40. package/types/modules/viewport/index.d.ts +78 -0
  41. package/types/protocol/guards.d.ts +6 -1
  42. package/types/protocol/types.d.ts +19 -4
  43. package/types/protocol.d.ts +18 -0
  44. package/types/modules/system/get-storage.d.ts +0 -15
  45. package/types/modules/system/get-window-info.d.ts +0 -16
  46. package/types/modules/system/index.d.ts +0 -23
  47. package/types/modules/system/set-storage.d.ts +0 -12
  48. package/types/modules/system/types.d.ts +0 -34
  49. package/types/modules/user/login.d.ts +0 -18
package/README.md CHANGED
@@ -1,24 +1,27 @@
1
1
  # @heybox/hb-sdk
2
2
 
3
- 面向黑盒外部小程序 iframe 沙盒的前端 SDK。它负责与父容器完成握手、收发 bridge 消息,并以受控模块的形式向外部小程序开放用户、分享、系统信息和隔离 storage 能力。
3
+ 面向黑盒外部小程序 iframe 沙盒的前端 SDK。它负责与父容器完成握手、收发 bridge 消息,并以受控模块的形式向外部小程序开放授权、用户、分享、视口、隔离 storage 与网络请求能力。
4
4
 
5
5
  ## 为什么需要它
6
6
 
7
7
  外部小程序运行在父容器创建的 iframe 沙盒中,业务页面不能直接读取主站登录态,也不应该关心底层 `postMessage` 协议、nonce 校验、请求响应关联、超时清理、客户端协议参数过滤等细节。
8
8
 
9
- `@heybox/hb-sdk` 将这些通信细节封装为稳定接口,让小程序只通过被允许的能力访问父容器。父容器仍负责调用黑盒客户端协议,并在运行时过滤不适合开放给外部小程序的内部参数。
9
+ `@heybox/hb-sdk` 将这些通信细节封装为稳定接口,让小程序只通过被允许的能力访问父容器。父容器仍负责调用黑盒客户端协议,并在运行时过滤不适合开放给外部小程序的内部参数。网络请求能力同样遵循这个边界:SDK 提供 axios-like 的窄接口,运行时负责协议映射。
10
10
 
11
11
  ## 当前对外导出
12
12
 
13
13
  > 以 `src/index.ts` 为准;历史目录、旧示例或构建产物若与当前入口不一致,以当前源码导出能力为准。
14
14
 
15
- - 默认导出 `hbSDK`:包含 `ready`、`on`、`off`、`user`、`share`、`system`。
16
- - 命名导出 `ready` / `on` / `off` / `user` / `share` / `system`:默认 SDK 单例能力。
15
+ - 默认导出 `hbSDK`:包含 `ready`、`on`、`off`、`auth`、`user`、`share`、`viewport`、`storage`、`network`。
16
+ - 命名导出 `ready` / `on` / `off` / `auth` / `user` / `share` / `viewport` / `storage` / `network`:默认 SDK 单例能力。
17
17
  - `createMiniProgramSDK` / `MiniProgramSDK`:创建独立 SDK 实例,适合测试、多实例或显式生命周期管理场景。
18
- - `HbMiniProgramSDKError`:SDK 对外抛出的标准错误类型。
18
+ - `HbMiniProgramSDKError`:bridge / 运行时 / 协议失败时的标准错误类型。
19
+ - `HbMiniProgramNetworkError`:HTTP 已完成但未通过 SDK `validateStatus` 校验时的网络错误类型。
19
20
  - `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 常量。
21
+ - bridge 协议常量、类型与守卫:根入口保留导出;运行时等宿主侧包应优先从 `@heybox/hb-sdk/protocol` 子入口导入,避免误依赖 SDK core / singleton。
22
+ - 模块类型与方法常量:`MiniProgramAuthModule`、`MiniProgramUserModule`、`MiniProgramShareModule`、`MiniProgramViewportModule`、`MiniProgramStorageModule`、`MiniProgramNetworkModule` 以及各模块 method 常量。
23
+
24
+ > 本版本为破坏性模块重排:登录归属 `auth`,窗口归属 `viewport`,存储归属 `storage`;旧的 `user.login()` 与 `system.*` 入口已移除。
22
25
 
23
26
  ## 快速开始
24
27
 
@@ -52,10 +55,18 @@ const currentUser = await user.getInfo();
52
55
  unsubscribe();
53
56
  ```
54
57
 
55
- 分享与 storage
58
+ 分享、storage 与 network
56
59
 
57
60
  ```ts
58
- import { share, system } from '@heybox/hb-sdk';
61
+ import { network, share, storage } from '@heybox/hb-sdk';
62
+
63
+ const response = await network.request<{ ok: boolean }>({
64
+ url: 'https://api.example.com/demo',
65
+ method: 'GET',
66
+ });
67
+
68
+ console.log(response.status, response.data.ok);
69
+
59
70
 
60
71
  await share.showShareMenu({
61
72
  title: '分享标题',
@@ -64,29 +75,31 @@ await share.showShareMenu({
64
75
  imageUrl: 'https://imgheybox.max-c.com/demo.png',
65
76
  });
66
77
 
67
- await system.setStorage({
78
+ await storage.setStorage({
68
79
  key: 'settings',
69
80
  data: {
70
81
  theme: 'dark',
71
82
  },
72
83
  });
73
84
 
74
- const { data } = await system.getStorage<{ theme: string }>({
85
+ const { data } = await storage.getStorage<{ theme: string }>({
75
86
  key: 'settings',
76
87
  });
77
88
  ```
78
89
 
90
+ 网络请求默认只把 `2xx` 视为成功;`4xx/5xx` 这类已完成 HTTP 响应会在 SDK 模块层抛出 `HbMiniProgramNetworkError`,而 bridge / 运行时 / 协议失败仍然抛出 `HbMiniProgramSDKError`。`validateStatus` 仅在 SDK 本地执行,不会把函数值透传给父容器。
91
+
79
92
  ## 核心概念
80
93
 
81
94
  ### 默认单例
82
95
 
83
- 普通小程序页面优先使用默认导出的 `hbSDK`,或直接按需导入 `ready`、`on`、`off`、`user`、`share`、`system`。默认单例会在首次调用时懒创建,业务不需要手动初始化。
96
+ 普通小程序页面优先使用默认导出的 `hbSDK`,或直接按需导入 `ready`、`on`、`off`、`auth`、`user`、`share`、`viewport`、`storage`。默认单例会在首次调用时懒创建,业务不需要手动初始化。
84
97
 
85
98
  ```ts
86
- import { ready, system } from '@heybox/hb-sdk';
99
+ import { ready, viewport } from '@heybox/hb-sdk';
87
100
 
88
101
  await ready();
89
- const windowInfo = await system.getWindowInfo();
102
+ const windowInfo = await viewport.getWindowInfo();
90
103
  ```
91
104
 
92
105
  ### 独立实例
@@ -102,7 +115,7 @@ const sdk = createMiniProgramSDK({
102
115
 
103
116
  await sdk.ready();
104
117
 
105
- const loginResult = await sdk.user.login();
118
+ const loginResult = await sdk.auth.login();
106
119
 
107
120
  sdk.destroy();
108
121
  ```
@@ -112,6 +125,7 @@ sdk.destroy();
112
125
  SDK 与父容器之间通过 `postMessage` 通信,消息会带上固定命名空间、协议版本与 iframe 实例 nonce。SDK 内部负责:
113
126
 
114
127
  - 从 URL query 读取 `hb_mini_bridge_nonce`,也支持通过 `MiniProgramSDKOptions.nonce` 显式传入。
128
+ - 支持通过 `MiniProgramSDKOptions.targetOrigin` 显式指定发往父容器的 `postMessage targetOrigin`;未传时会尝试推断父容器 origin,失败则兼容回退为 `*`。
115
129
  - 向父容器发送 `sdk.handshake` 握手消息;如果还没有收到 `ready` 事件,会在总超时窗口内短间隔重试。
116
130
  - 为每次能力调用生成请求 ID,匹配父容器返回的 response。
117
131
  - 过滤非小程序消息、非当前 nonce 消息以及非目标父窗口消息。
@@ -124,10 +138,10 @@ SDK 与父容器之间通过 `postMessage` 通信,消息会带上固定命名
124
138
  请求失败和 SDK 内部错误会统一包装为 `HbMiniProgramSDKError`,包含稳定的 `code`、面向开发者的 `message` 和可选 `data`。
125
139
 
126
140
  ```ts
127
- import { HbMiniProgramSDKError, user } from '@heybox/hb-sdk';
141
+ import { HbMiniProgramSDKError, auth } from '@heybox/hb-sdk';
128
142
 
129
143
  try {
130
- await user.login();
144
+ await auth.login();
131
145
  } catch (error) {
132
146
  if (error instanceof HbMiniProgramSDKError) {
133
147
  console.log(error.code, error.message, error.data);
@@ -144,18 +158,25 @@ try {
144
158
  | 模块 | 作用 | 代表导出 |
145
159
  | --- | --- | --- |
146
160
  | `core/sdk` | SDK 实例封装 | `MiniProgramSDK`、`createMiniProgramSDK` |
147
- | `core/singleton` | 默认单例入口 | `ready`、`on`、`off`、`user`、`share`、`system` |
161
+ | `core/singleton` | 默认单例入口 | `ready`、`on`、`off`、`auth`、`user`、`share`、`viewport`、`storage` |
148
162
  | `core/client` | bridge 握手、请求响应、事件分发 | `MiniProgramSDKOptions`、`MiniProgramRequester` |
149
163
  | `core/errors` | 标准错误类型 | `HbMiniProgramSDKError` |
150
164
 
165
+ ### Auth
166
+
167
+ 授权模块位于 `src/modules/auth`,承载登录授权类能力。
168
+
169
+ | API | 对应父容器能力 | 说明 |
170
+ | --- | --- | --- |
171
+ | `auth.login()` | `auth.login` | 唤起黑盒登录流程,并返回登录后的最新用户公开资料。 |
172
+
151
173
  ### User
152
174
 
153
- 用户模块位于 `src/modules/user`,只暴露允许小程序访问的公开用户能力。
175
+ 用户模块位于 `src/modules/user`,只暴露允许小程序访问的公开用户资料能力。
154
176
 
155
177
  | API | 说明 |
156
178
  | --- | --- |
157
179
  | `user.getInfo()` | 获取当前用户登录态与公开基础资料。未登录时不会触发登录流程。 |
158
- | `user.login()` | 唤起黑盒登录流程,并返回登录后的最新用户公开资料。 |
159
180
 
160
181
  用户信息只包含允许暴露给外部小程序的公开字段:
161
182
 
@@ -174,6 +195,42 @@ interface MiniProgramUserInfoResult {
174
195
 
175
196
  SDK 不会向小程序暴露 token、cookie、手机号或任何可用于直接调用主站私有接口的凭据。
176
197
 
198
+ ### Network
199
+
200
+ 网络模块位于 `src/modules/network`,提供一个窄化的 axios-like `network.request()` 接口。SDK 只暴露公共请求字段,父容器运行时负责把这些字段映射到实际协议。
201
+
202
+ | API | 对应父容器能力 | 说明 |
203
+ | --- | --- | --- |
204
+ | `network.request(config)` | `network.request` | 发起网络请求;默认仅 `2xx` 视为成功。 |
205
+
206
+ ```ts
207
+ interface MiniProgramNetworkRequestConfig {
208
+ url: string;
209
+ method?: string;
210
+ params?: Record<string, unknown>;
211
+ data?: unknown;
212
+ headers?: Record<string, string>;
213
+ timeout?: number;
214
+ withCredentials?: boolean;
215
+ validateStatus?: (status: number) => boolean;
216
+ }
217
+
218
+ interface MiniProgramNetworkResponse<T = unknown> {
219
+ data: T;
220
+ status: number;
221
+ statusText?: string;
222
+ headers: Record<string, string>;
223
+ config: MiniProgramNetworkRequestConfig;
224
+ }
225
+ ```
226
+
227
+ 约束说明:
228
+
229
+ - `validateStatus` 只在 SDK 本地执行,不会跨 bridge 传输函数。
230
+ - `config` 是 SDK 公共请求配置快照,不包含任何原始 `sendRequestV2` 字段。
231
+ - 公开响应头为 `Record<string, string>`;无法可靠解析时应视为 `{}`。
232
+ - v1 不提供原始协议字段、回调函数、拦截器或上传下载进度等高级能力。
233
+
177
234
  ### Share
178
235
 
179
236
  分享模块位于 `src/modules/share`,对外提供简洁配置,父容器侧再映射到黑盒客户端协议。
@@ -212,15 +269,13 @@ interface MiniProgramScreenshotOptions {
212
269
 
213
270
  为了保持外部 API 稳定,`share` 模块不开放 raw protocol、JS callback、活动上报、发帖、自定义按钮、upload-only 等内部能力。
214
271
 
215
- ### System
272
+ ### Viewport
216
273
 
217
- 系统模块位于 `src/modules/system`,当前提供窗口信息与隔离 storage 能力。
274
+ Viewport 模块位于 `src/modules/viewport`,承载窗口、视口和安全区域相关能力。
218
275
 
219
276
  | API | 对应父容器能力 | 说明 |
220
277
  | --- | --- | --- |
221
- | `system.getWindowInfo()` | `system.getWindowInfo` | 获取窗口、屏幕、安全区域等信息。 |
222
- | `system.getStorage(options)` | `system.getStorage` -> `getStorage` 协议 | 读取小程序隔离 storage。 |
223
- | `system.setStorage(options)` | `system.setStorage` -> `setStorage` 协议 | 写入小程序隔离 storage。 |
278
+ | `viewport.getWindowInfo()` | `viewport.getWindowInfo` | 获取窗口、屏幕、安全区域等信息。 |
224
279
 
225
280
  `getWindowInfo()` 返回字段对齐微信小程序 `wx.getWindowInfo` 的常用字段:
226
281
 
@@ -244,17 +299,26 @@ interface MiniProgramWindowInfoResult {
244
299
  }
245
300
  ```
246
301
 
302
+ ### Storage
303
+
304
+ Storage 模块位于 `src/modules/storage`,承载小程序隔离存储能力。
305
+
306
+ | API | 对应父容器能力 | 说明 |
307
+ | --- | --- | --- |
308
+ | `storage.getStorage(options)` | `storage.getStorage` -> `getStorage` 协议 | 读取小程序隔离 storage。 |
309
+ | `storage.setStorage(options)` | `storage.setStorage` -> `setStorage` 协议 | 写入小程序隔离 storage。 |
310
+
247
311
  storage API:
248
312
 
249
313
  ```ts
250
- await system.setStorage({
314
+ await storage.setStorage({
251
315
  key: 'settings',
252
316
  data: {
253
317
  enabled: true,
254
318
  },
255
319
  });
256
320
 
257
- const result = await system.getStorage<{ enabled: boolean }>({
321
+ const result = await storage.getStorage<{ enabled: boolean }>({
258
322
  key: 'settings',
259
323
  });
260
324
  ```
@@ -297,10 +361,10 @@ renderUser(result.userInfo);
297
361
  ### 场景 2:点击按钮唤起登录
298
362
 
299
363
  ```ts
300
- import { user } from '@heybox/hb-sdk';
364
+ import { auth } from '@heybox/hb-sdk';
301
365
 
302
366
  async function handleLoginClick() {
303
- const result = await user.login();
367
+ const result = await auth.login();
304
368
 
305
369
  if (result.isLogin) {
306
370
  renderUser(result.userInfo);
@@ -353,9 +417,9 @@ await share.screenshot({
353
417
  ### 场景 5:读取窗口信息
354
418
 
355
419
  ```ts
356
- import { system } from '@heybox/hb-sdk';
420
+ import { viewport } from '@heybox/hb-sdk';
357
421
 
358
- const windowInfo = await system.getWindowInfo();
422
+ const windowInfo = await viewport.getWindowInfo();
359
423
 
360
424
  console.log(windowInfo.windowWidth, windowInfo.windowHeight, windowInfo.safeArea.top);
361
425
  ```
@@ -363,16 +427,16 @@ console.log(windowInfo.windowWidth, windowInfo.windowHeight, windowInfo.safeArea
363
427
  ### 场景 6:使用隔离 storage
364
428
 
365
429
  ```ts
366
- import { system } from '@heybox/hb-sdk';
430
+ import { storage } from '@heybox/hb-sdk';
367
431
 
368
- await system.setStorage({
432
+ await storage.setStorage({
369
433
  key: 'card_mode',
370
434
  data: {
371
435
  enabled: true,
372
436
  },
373
437
  });
374
438
 
375
- const { data } = await system.getStorage<{ enabled: boolean }>({
439
+ const { data } = await storage.getStorage<{ enabled: boolean }>({
376
440
  key: 'card_mode',
377
441
  });
378
442
 
@@ -428,6 +492,38 @@ await sdk.ready();
428
492
  sdk.destroy();
429
493
  ```
430
494
 
495
+ ## 与 `@heybox/hb-sdk-runtime` 的关系与兼容矩阵
496
+
497
+ `@heybox/hb-sdk` 是 iframe 内部使用的客户端 SDK,`@heybox/hb-sdk-runtime` 是 iframe 外部宿主壳层使用的运行时实现。当前仓库选择将 **协议 / 契约相关内容继续维护在 `@heybox/hb-sdk` 内部**,而不是额外拆出一个 contract 包,以减少包数量、发布面和维护成本。
498
+
499
+ 约定如下:
500
+
501
+ - `@heybox/hb-sdk-runtime` 可以依赖 `@heybox/hb-sdk` 中的 **协议常量、类型、消息守卫** 等契约层内容。
502
+ - `@heybox/hb-sdk-runtime` **不应依赖** `@heybox/hb-sdk` 的 `core/*`、默认单例、客户端请求实现等客户端运行时逻辑。
503
+ - 协议变更时,`@heybox/hb-sdk` 与 `@heybox/hb-sdk-runtime` 应按一组联动能力来评审和发布,而不是分别独立演进。
504
+
505
+ ### 兼容矩阵(当前约定)
506
+
507
+ | `@heybox/hb-sdk` | `@heybox/hb-sdk-runtime` | 说明 |
508
+ | --- | --- | --- |
509
+ | 同一仓库主线版本 | 同一仓库主线版本 | 默认开发模式,按同一批次代码联动验证 |
510
+ | 仅补丁级变更 | 仅补丁级变更 | 允许,但必须保持协议常量、消息结构、事件名和 payload 兼容 |
511
+ | 协议字段 / 方法名 / 事件名变更 | 需要同步升级 | 不允许单边发布后假定另一侧自动兼容 |
512
+
513
+ ### 后续 CI 兼容性检查(待补)
514
+
515
+ 后续补 CI 时,至少应增加以下检查:
516
+
517
+ 1. **依赖边界检查**
518
+ - 禁止 `@heybox/hb-sdk-runtime` 引用 `@heybox/hb-sdk/core/*`、默认单例或客户端实现层。
519
+ - 只允许引用协议 / 契约层入口(例如 `@heybox/hb-sdk/protocol`)。
520
+ 2. **协议兼容性检查**
521
+ - 当 `MINI_PROGRAM_MESSAGE_*` 常量、事件名、方法名、payload 类型变更时,要求 `hb-sdk` 与 `hb-sdk-runtime` 相关测试同时通过。
522
+ 3. **联动验证检查**
523
+ - 至少跑一组 `hb-sdk` 单测 + `hb-sdk-runtime` 单测,确保客户端与宿主运行时没有单边漂移。
524
+ 4. **导出面检查**
525
+ - 若协议层导出发生调整,CI 需提醒评审同步检查 runtime 使用面,而不是默认为向后兼容。
526
+
431
527
  ## 能力边界与注意事项
432
528
 
433
529
  - SDK 只能在父容器创建的小程序 iframe 沙盒中正常完成握手;非 iframe 环境会抛出 `NOT_IN_IFRAME`。
@@ -435,14 +531,48 @@ sdk.destroy();
435
531
  - 父容器需要幂等响应 `sdk.handshake`;SDK 会在收到 `ready` 前自动重试握手,不引用 SDK 的普通页面不会触发握手。
436
532
  - 调用模块能力前会自动等待 `ready()`,但业务仍建议在页面启动阶段显式 `await ready()`,便于集中处理握手失败。
437
533
  - `user.getInfo()` 只查询登录态,不会主动唤起登录。
438
- - `user.login()` 只返回公开用户资料,不返回 token、cookie 或私有凭据。
534
+ - `auth.login()` 只返回公开用户资料,不返回 token、cookie 或私有凭据。
439
535
  - `share.showShareMenu()` 只开放基础分享字段,不开放活动任务上报、发帖、自定义按钮等内部协议参数。
440
536
  - `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}$/`。
537
+ - `viewport.getWindowInfo()` 的 `statusBarHeight`、`screenTop`、`safeArea.top` 在黑盒容器内按顶部可用偏移处理。
538
+ - `storage.getStorage()` / `storage.setStorage()` 只访问小程序隔离 storage;业务 key 必须符合 `/^[A-Za-z0-9_-]{1,128}$/`。
443
539
  - `on()` 会返回取消监听函数;页面卸载或组件销毁时应及时取消监听。
444
540
  - 独立实例不再使用时应调用 `destroy()`,以移除 message 监听并拒绝未完成请求。
445
541
 
542
+ ## CLI 创建外部小程序模板
543
+
544
+ `hb-sdk create <project-name>` 会生成一个外部独立小程序开发模板,默认使用 Vue 3、Vite、TypeScript 和 npm。
545
+
546
+ ```bash
547
+ hb-sdk create my-miniapp
548
+ cd my-miniapp
549
+ npm install
550
+ npm run dev:mock
551
+ ```
552
+
553
+ 生成规则:
554
+
555
+ - `project-name` 同时作为项目目录名和 `package.json` 的 `name`,必须是合法的非 scoped npm 包名,例如 `my-miniapp`。
556
+ - 目标目录不存在时会自动创建;目标目录已存在但非空时会拒绝覆盖。
557
+ - CLI 只生成文件,不会自动安装依赖、初始化 git 或打开编辑器。
558
+ - 模板内置轻量 SDK 能力演示页和 Vitest 单测配置;`npm run dev:mock` 会启动本地 Vite 服务和 hb-sdk mock runtime host。
559
+
560
+ ## CLI 登录态
561
+
562
+ `hb-sdk` CLI 内置 Heybox 浏览器登录流,登录态只保存在 `hb-sdk` 自己的本地缓存命名空间里,供 `hb-sdk` CLI 命令内部调用 Heybox 接口时复用。
563
+
564
+ ```bash
565
+ hb-sdk login
566
+ hb-sdk login status
567
+ hb-sdk login clear
568
+ ```
569
+
570
+ - `hb-sdk login` 会打开 `login.xiaoheihe.cn`,通过本地临时回调服务接收登录结果。
571
+ - `hb-sdk login status` 只展示脱敏状态、`heyboxId`、登录时间和 cache 路径,不输出 `pkey`、cookie 或完整请求头。
572
+ - `hb-sdk login clear` 只清理 `hb-sdk` 自己命名空间中的 Heybox 登录态。
573
+
574
+ 这份 CLI 登录态不会注入 iframe SDK,也不会改变 `hb-sdk dev --mock` 的 mock 用户、`auth.login()`、`user.getInfo()` 或 `network.request()` 行为。
575
+
446
576
  ## 开发命令
447
577
 
448
578
  优先使用仓库统一的 `hbexec` 入口:
package/bin/hb-sdk.cjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/cli.cjs');