@heybox/hb-sdk 0.4.5 → 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 CHANGED
@@ -280,13 +280,16 @@ try {
280
280
  | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
281
281
  | `hb-sdk create <project-name>` | 创建外部小程序模板。 |
282
282
  | `hb-sdk dev [--runtime-url <url>]` | 启动当前项目的 Vite dev server 和浏览器 mock 宿主环境,并默认打开调试页;`--runtime-url` 会传给真实客户端 dev shell。 |
283
- | `hb-sdk login [--login-base-url <url>]` | 登录 Heybox,并把 CLI 自己需要的登录态和登录入口环境保存在本地缓存中。 |
283
+ | `hb-sdk login [--login-base-url <url>] [--no-select-entity]` | 登录 Heybox,并把 CLI 自己需要的登录态和登录入口环境保存在本地缓存中;默认会引导多主体用户选择服务端 current entity。 |
284
284
  | `hb-sdk login status` | 查看脱敏后的 CLI 登录态。 |
285
285
  | `hb-sdk login clear` | 清理 CLI 登录态。 |
286
286
  | `hb-sdk doctor` | 检查本机 `hb-sdk` Agent Skill 是否匹配当前 SDK,并输出手动安装/刷新命令。 |
287
287
  | `hb-sdk remote access` | 查看当前 CLI 用户是否具备开发者用户小程序创建和管理资格。 |
288
+ | `hb-sdk remote entity list` | 列出当前 CLI 用户可切换的开发者主体,并标记服务端 current entity。 |
289
+ | `hb-sdk remote entity current` | 查看服务端 current entity,以及该主体的用户小程序权限状态。 |
290
+ | `hb-sdk remote entity switch <entity-id>` | 切换开发者平台服务端 current entity;不会修改项目绑定的小程序 ID。 |
288
291
  | `hb-sdk remote list [--status <status>] [--keyword <text>]` | 列出当前 CLI 用户可管理的远端用户小程序,用于发现并绑定当前项目。 |
289
- | `hb-sdk remote create --name <name> [--preview-image-url <url>] [--force-bind]` | 创建远端用户小程序并写入当前项目的 `package.json.heybox.miniProgramId`。 |
292
+ | `hb-sdk remote create --name <name> [--preview-image-url <url>] [--yes] [--force-bind]` | 在服务端 current entity 下创建远端用户小程序并写入当前项目的 `package.json.heybox.miniProgramId`。 |
290
293
  | `hb-sdk remote bind <mini-program-id> [--force]` | 校验当前 CLI 用户可管理目标小程序后,再把它绑定到当前项目。 |
291
294
  | `hb-sdk remote info` | 查看当前项目绑定的小程序详情。 |
292
295
  | `hb-sdk remote update [--name <name>] [--preview-image-url <url>]` | 更新绑定小程序的名称或远程预览图 URL。 |
@@ -299,7 +302,7 @@ try {
299
302
  | `hb-sdk remote take-down [--yes]` | 下架当前线上小程序;非 TTY 环境必须传 `--yes`。 |
300
303
  | `hb-sdk remote reopen [--yes]` | 重新上架已下架的小程序;非 TTY 环境必须传 `--yes`。 |
301
304
 
302
- 远端平台操作统一放在 `hb-sdk remote` 命令组下;顶层 `hb-sdk deploy` 已硬切删除,不再作为兼容别名保留。`hb-sdk login` 仍是顶层命令,因为它管理 CLI 登录态,不绑定到某个具体小程序。
305
+ 远端平台操作统一放在 `hb-sdk remote` 命令组下;顶层 `hb-sdk deploy` 已硬切删除,不再作为兼容别名保留。`hb-sdk login` 仍是顶层命令,因为它管理 CLI 登录态,不绑定到某个具体小程序。开发者主体的事实源是服务端 current entity;CLI 登录缓存中的 `selectedEntity` 只是上次选择时的提示快照,用于 `login status` 展示和漂移排障,不能作为权限或归属判断依据。
303
306
 
304
307
  `hb-sdk remote ...` 支持通用参数 `--json`、`--api-base-url <url>`、`--login-base-url <url>`、`--allow-unsafe-api-base-url` 和 `--verbose`。其中 `--json` 会让 stdout 只输出一个 JSON 对象,进度、警告和诊断信息不应污染 stdout。
305
308
 
@@ -317,23 +320,25 @@ try {
317
320
  }
318
321
  }
319
322
  ```
320
- 2. 已运行过 `hb-sdk login` 登录 Heybox
321
- 3. 如果需要以公司的名义发布小程序,需先找 @秦浩东 申请小程序开发权限。
322
- 4. 每次部署都要准备发布日志:`hb-sdk remote deploy --release-note "..."`。发布日志 trim 后不能为空,最多 500 个字符,允许换行;CI / 非 TTY 环境缺失时会直接失败,TTY 环境会提示输入。
323
- 5. 项目根有 `scripts.build`,会被 CLI 通过 lockfile 自动选用的 `pnpm`、`yarn` `npm` 触发;无 lockfile 时回退 `npm`。
324
- 6. 构建产物落在 `dist/`,包含 `index.html` `manifest.json`。
323
+ 2. 已运行过 `hb-sdk login` 登录 Heybox;多主体用户应确认 `hb-sdk remote entity current` 指向要发布的主体。
324
+ 3. 当前项目绑定的小程序必须属于服务端 current entity;如不一致,先运行 `hb-sdk remote entity switch <entity-id>` 切换主体。
325
+ 4. 如果需要以公司的名义发布小程序,需先找 @秦浩东 申请小程序开发权限。
326
+ 5. 每次部署都要准备发布日志:`hb-sdk remote deploy --release-note "..."`。发布日志 trim 后不能为空,最多 500 个字符,允许换行;CI / TTY 环境缺失时会直接失败,TTY 环境会提示输入。
327
+ 6. 项目根有 `scripts.build`,会被 CLI 通过 lockfile 自动选用的 `pnpm`、`yarn` `npm` 触发;无 lockfile 时回退 `npm`。
328
+ 7. 构建产物落在 `dist/`,包含 `index.html` 和 `manifest.json`。
325
329
 
326
330
  执行流程:
327
331
 
328
332
  1. 校验 `heybox.miniProgramId`、发布日志和登录态。
329
- 2. 普通 remote deploy 读取 `package.json.version`,登录后、build 前调用 `/mall/developer/user_miniprogram/version/precheck`,入参为 `mini_program_id`、`version`、`release_note`、`auto_publish`。
330
- 3. 触发 `<pm> run build`,除非使用 `--skip-build`。
331
- 4. 解析 `dist/manifest.json`,校验 `version` `x.y.z`,自动剥离 BOM;普通 remote deploy 要求该版本与 precheck 使用的 `package.json.version` 一致。
332
- 5. `--skip-build` 会先读取已有 `dist/manifest.json.version`,再调用 precheck。
333
- 6. 遍历 `dist/` 文件,跳过 `manifest.json`、`.DS_Store`、`.map`;遇到 symlink 或 `node_modules` 直接报错。
334
- 7. 校验所有上传路径长度不超过 64。
335
- 8. 4 并发上传到 COS。默认只展示上传阶段和文件总数;`--verbose` 会展示并发数、bucket / region 和逐文件结果,但不会输出 keys、签名、cookie 或 token。任一文件失败立刻 abort,不提交审核。
336
- 9. 全部上传成功后调用 `/mall/developer/user_miniprogram/version/submit_audit`,输出提交审核成功、发布策略和可用的 preview URL;后端原始失败细节只在 `--verbose` 下展示。
333
+ 2. 读取服务端 current entity 和绑定小程序详情,确认 `detail.entity_id` current entity 一致;主体不一致时直接失败,不触发 precheck、build、upload 或 submit audit。
334
+ 3. 普通 remote deploy 读取 `package.json.version`,主体校验通过后、build 前调用 `/mall/developer/user_miniprogram/version/precheck`,入参为 `mini_program_id`、`version`、`release_note`、`auto_publish`。
335
+ 4. 触发 `<pm> run build`,除非使用 `--skip-build`。
336
+ 5. 解析 `dist/manifest.json`,校验 `version` 为 `x.y.z`,自动剥离 BOM;普通 remote deploy 要求该版本与 precheck 使用的 `package.json.version` 一致。
337
+ 6. `--skip-build` 会先读取已有 `dist/manifest.json.version`,再调用 precheck。
338
+ 7. 遍历 `dist/` 文件,跳过 `manifest.json`、`.DS_Store`、`.map`;遇到 symlink 或 `node_modules` 直接报错。
339
+ 8. 校验所有上传路径长度不超过 64。
340
+ 9. 4 并发上传到 COS。默认只展示上传阶段和文件总数;`--verbose` 会展示并发数、bucket / region 和逐文件结果,但不会输出 keys、签名、cookie 或 token。任一文件失败立刻 abort,不提交审核。
341
+ 10. 全部上传成功后调用 `/mall/developer/user_miniprogram/version/submit_audit`,输出提交审核成功、发布策略和可用的 preview URL;后端原始失败细节只在 `--verbose` 下展示。
337
342
 
338
343
  默认 `auto_publish=false`,审核通过后使用 `hb-sdk remote versions` 查看版本状态,再用 `hb-sdk remote release <version>` 发布;使用 `--auto-publish` 时提交 `auto_publish=true`,审核通过后自动发布。未发布候选版本可通过 `hb-sdk remote allowlist add <heybox_id>` 加入预览白名单,让指定用户在广场看到;正式入口使用 `mini_program_id`,`mini_url` 仅用于本地调试。
339
344
 
@@ -359,14 +364,17 @@ HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1 hb-sdk remote deploy --api-base-url http://12
359
364
 
360
365
  ## hb-sdk remote 命令参考
361
366
 
362
- `hb-sdk remote` 默认作用于当前项目绑定的小程序,即 `package.json.heybox.miniProgramId`。`remote list` 只用于发现可管理的小程序;会改变远端状态的命令仍然只操作当前绑定的小程序,不接受临时 `mini_program_id` 参数。
367
+ `hb-sdk remote` 默认作用于当前项目绑定的小程序,即 `package.json.heybox.miniProgramId`。`remote list` 只展示服务端 current entity 下可管理的小程序,用于发现和绑定;会改变远端状态的命令仍然只操作当前绑定的小程序,不接受临时 `mini_program_id` 参数。需要查看或切换开发者主体时,使用 `hb-sdk remote entity ...`;CLI 不会根据本地绑定自动切换主体。
363
368
 
364
369
  | 命令 | 说明 |
365
370
  | ---- | ---- |
366
371
  | `hb-sdk remote access` | 查询当前 CLI 用户是否具备开发者用户小程序管理资格。 |
367
- | `hb-sdk remote list [--status <status>] [--keyword <text>]` | 列出当前 CLI 用户可管理的小程序,并标出当前绑定项。 |
368
- | `hb-sdk remote create --name <name> [--preview-image-url <url>] [--force-bind]` | 创建远端小程序并绑定当前项目;已有绑定时必须显式传 `--force-bind` 才能覆盖。 |
369
- | `hb-sdk remote bind <mini-program-id> [--force]` | 先校验当前 CLI 用户可管理目标小程序,再写入当前项目绑定;`--force` 只允许覆盖本地绑定,不跳过远端校验。 |
372
+ | `hb-sdk remote entity list` | 列出可切换开发者主体,并标记服务端 current entity。 |
373
+ | `hb-sdk remote entity current` | 查看服务端 current entity 和该主体的用户小程序权限状态。 |
374
+ | `hb-sdk remote entity switch <entity-id>` | 切换服务端 current entity;只允许切到 `entity list` 返回的主体。 |
375
+ | `hb-sdk remote list [--status <status>] [--keyword <text>]` | 列出 current entity 下当前 CLI 用户可管理的小程序,并标出当前绑定项。 |
376
+ | `hb-sdk remote create --name <name> [--preview-image-url <url>] [--yes] [--force-bind]` | 在 current entity 下创建远端小程序并绑定当前项目;多主体非 TTY 环境必须传 `--yes` 确认使用当前主体;已有绑定时必须显式传 `--force-bind` 才能覆盖。 |
377
+ | `hb-sdk remote bind <mini-program-id> [--force]` | 先校验 current entity 可管理目标小程序,再写入当前项目绑定;`--force` 只允许覆盖本地绑定,不跳过远端校验或主体一致性校验。 |
370
378
  | `hb-sdk remote info` | 查看当前绑定小程序的远端详情。 |
371
379
  | `hb-sdk remote update [--name <name>] [--preview-image-url <url>]` | 更新名称或远程预览图 URL,至少传一个变更字段。 |
372
380
  | `hb-sdk remote allowlist list` | 查看预览白名单。 |
@@ -381,7 +389,7 @@ HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1 hb-sdk remote deploy --api-base-url http://12
381
389
  | `hb-sdk remote take-down [--yes]` | 下架当前线上小程序;交互式终端会确认,非 TTY 必须传 `--yes`。 |
382
390
  | `hb-sdk remote reopen [--yes]` | 重新上架已下架的小程序;交互式终端会确认,非 TTY 必须传 `--yes`。 |
383
391
 
384
- CLI 登录态只供 CLI 命令访问黑盒接口时复用,不会注入 iframe SDK,也不会改变 `auth.login()`、`user.getInfo()`、`network.request()` 或 mock 宿主中的用户状态。`hb-sdk login status` 默认展示脱敏状态、`heyboxId`、`loginBaseUrl` 和登录时间;`--verbose` 额外展示 cache 路径。不输出 `pkey`、cookie 或完整请求头。
392
+ CLI 登录态只供 CLI 命令访问黑盒接口时复用,不会注入 iframe SDK,也不会改变 `auth.login()`、`user.getInfo()`、`network.request()` 或 mock 宿主中的用户状态。`hb-sdk login` 成功后会尝试读取开发者主体列表:单主体自动确认或切换为 current entity,多主体交互式环境要求选择主体,多主体非 TTY 环境只提示后续运行 `hb-sdk remote entity switch <entity-id>`;显式传 `--no-select-entity` 时只写登录态,不修改服务端 current entity。`hb-sdk login status` 默认展示脱敏状态、`heyboxId`、`loginBaseUrl`、登录时间和本地 `selectedEntity` 提示快照;`--verbose` 额外展示 cache 路径。不输出 `pkey`、cookie 或完整请求头。`selectedEntity` 不是权限事实源,每次 remote 命令仍以服务端 current entity 为准。
385
393
 
386
394
  `create`、`dev`、`remote ...`、`login`、`login status`、`login clear`、`doctor` 这些 CLI 命令会在成功执行后检查 npm registry 上的 `@heybox/hb-sdk@latest`。普通命令的检查结果会缓存 24 小时;如果发现新版本,会在 stderr 打印升级提醒;检查失败会静默跳过,不影响当前命令。`doctor` 已经诊断出 `SDK_MISMATCH` 时不会再追加统一提醒,避免同一次输出里重复提示升级 SDK。`hb-sdk --version` / `hb-sdk -V` 会直接请求 npm registry 获取 latest,不读取本地缓存;stdout 只输出版本号,升级提醒继续按 warn 级别写到 stderr。可通过 `HB_SDK_NO_UPDATE_CHECK=1` 禁用版本提醒;`CI=true` 时也会自动跳过检查。
387
395
 
@@ -5,7 +5,7 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var require$$0 = require('fs');
7
7
  var require$$1 = require('path');
8
- var index = require('./index-BYMTp2I6.cjs');
8
+ var index = require('./index-DuwxUSkq.cjs');
9
9
  require('node:module');
10
10
  require('os');
11
11
  require('readline');
@@ -9,7 +9,7 @@ var node_url = require('node:url');
9
9
  var net = require('node:net');
10
10
  var node_http = require('node:http');
11
11
  var browser = require('./browser-RAy8e8cV.cjs');
12
- var index = require('./index-BYMTp2I6.cjs');
12
+ var index = require('./index-DuwxUSkq.cjs');
13
13
  require('node:process');
14
14
  require('node:buffer');
15
15
  require('node:util');
@@ -4,7 +4,7 @@ var fs$1 = require('node:fs');
4
4
  var fs = require('node:fs/promises');
5
5
  var os = require('node:os');
6
6
  var path = require('node:path');
7
- var index = require('./index-BYMTp2I6.cjs');
7
+ var index = require('./index-DuwxUSkq.cjs');
8
8
  require('node:module');
9
9
  require('path');
10
10
  require('os');
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var index$2 = require('./index-BYMTp2I6.cjs');
3
+ var index$2 = require('./index-DuwxUSkq.cjs');
4
4
  var require$$0$2 = require('fs');
5
5
  var require$$2$1 = require('crypto');
6
6
  var require$$1$2 = require('path');
7
7
  var require$$0$3 = require('assert');
8
8
  var require$$4$2 = require('events');
9
9
  var require$$1$1 = require('util');
10
- var remote = require('./remote-DjaOc1VS.cjs');
10
+ var remote = require('./remote-zX17hOT4.cjs');
11
11
  var require$$0$5 = require('net');
12
12
  var require$$0$4 = require('url');
13
13
  var require$$2$2 = require('http');
@@ -234,19 +234,19 @@ function requireArgument () {
234
234
 
235
235
  var command = {};
236
236
 
237
- const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-BYMTp2I6.cjs', document.baseURI).href)));
237
+ const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DuwxUSkq.cjs', document.baseURI).href)));
238
238
  function __require$4() { return require$5("node:events"); }
239
239
 
240
- const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-BYMTp2I6.cjs', document.baseURI).href)));
240
+ const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DuwxUSkq.cjs', document.baseURI).href)));
241
241
  function __require$3() { return require$4("node:child_process"); }
242
242
 
243
- const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-BYMTp2I6.cjs', document.baseURI).href)));
243
+ const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DuwxUSkq.cjs', document.baseURI).href)));
244
244
  function __require$2() { return require$3("node:path"); }
245
245
 
246
- const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-BYMTp2I6.cjs', document.baseURI).href)));
246
+ const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DuwxUSkq.cjs', document.baseURI).href)));
247
247
  function __require$1() { return require$2("node:fs"); }
248
248
 
249
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-BYMTp2I6.cjs', document.baseURI).href)));
249
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DuwxUSkq.cjs', document.baseURI).href)));
250
250
  function __require() { return require$1("node:process"); }
251
251
 
252
252
  var help = {};
@@ -13094,7 +13094,7 @@ function readErrorMessage(error, options = {}) {
13094
13094
  }
13095
13095
 
13096
13096
  const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
13097
- const BUILT_CLI_VERSION = '0.4.5';
13097
+ const BUILT_CLI_VERSION = '0.4.6';
13098
13098
  const PACKAGE_JSON_CANDIDATES = [
13099
13099
  path.resolve(__dirname, '..', '..', 'package.json'),
13100
13100
  path.resolve(__dirname, '..', 'package.json'),
@@ -13193,11 +13193,13 @@ function createCliProgram(overrides = {}) {
13193
13193
  const login = addVerboseOption(program
13194
13194
  .command('login')
13195
13195
  .description('登录 Heybox 并缓存 CLI 登录态')
13196
- .option('--login-base-url <url>', 'Heybox 登录入口 origin,默认读取 HB_SDK_LOGIN_BASE_URL 或生产地址')).action(withUpdateReminder(async (options, command) => {
13196
+ .option('--login-base-url <url>', 'Heybox 登录入口 origin,默认读取 HB_SDK_LOGIN_BASE_URL 或生产地址')
13197
+ .option('--no-select-entity', '登录后不选择或切换开发者主体')).action(withUpdateReminder(async (options, command) => {
13197
13198
  const logger = resolveLogger(command);
13198
13199
  await handlers.loginToHeybox({
13199
13200
  logger,
13200
13201
  loginBaseUrl: options.loginBaseUrl,
13202
+ noSelectEntity: options.selectEntity === false,
13201
13203
  });
13202
13204
  }, handlers.printUpdateReminder, resolveLogger));
13203
13205
  addVerboseOption(login.command('status').description('查看脱敏后的 Heybox 登录态')).action(withUpdateReminder(async (...args) => {
@@ -13223,6 +13225,12 @@ function addRemotePublicOptions(command) {
13223
13225
  function installRemoteCommands(program, handlers, resolveLogger) {
13224
13226
  const remote = addRemotePublicOptions(program.command('remote').description('管理当前项目绑定的远程 Heybox 用户小程序'));
13225
13227
  addRemotePublicOptions(remote.command('access').description('查看当前账号的用户小程序访问权限')).action(createRemoteAction(handlers, resolveLogger, 'access'));
13228
+ const entity = addRemotePublicOptions(remote.command('entity').description('查看和切换当前开发者主体'));
13229
+ addRemotePublicOptions(entity.command('list').description('列出当前账号可切换的开发者主体')).action(createRemoteAction(handlers, resolveLogger, 'entity:list'));
13230
+ addRemotePublicOptions(entity.command('current').description('查看当前开发者主体和用户小程序权限状态')).action(createRemoteAction(handlers, resolveLogger, 'entity:current'));
13231
+ addRemotePublicOptions(entity.command('switch').description('切换当前开发者主体').argument('<entity-id>', '开发者主体 ID')).action(createRemoteAction(handlers, resolveLogger, 'entity:switch', (_command, entityId) => ({
13232
+ entityId: readStringArgument(entityId, 'entity-id'),
13233
+ })));
13226
13234
  addRemotePublicOptions(remote
13227
13235
  .command('list')
13228
13236
  .description('列出当前账号可管理的用户小程序')
@@ -13233,9 +13241,10 @@ function installRemoteCommands(program, handlers, resolveLogger) {
13233
13241
  .description('创建远程用户小程序并绑定当前项目')
13234
13242
  .requiredOption('--name <name>', '小程序名称')
13235
13243
  .option('--preview-image-url <url>', '远程预览图 HTTPS URL')
13236
- .option('--force-bind', '允许覆盖当前 package.json 中已有绑定')).action(createRemoteAction(handlers, resolveLogger, 'create', (command) => ({
13244
+ .option('--force-bind', '允许覆盖当前 package.json 中已有绑定')).option('--yes', '多开发者主体时确认使用服务端 current 主体创建').action(createRemoteAction(handlers, resolveLogger, 'create', (command) => ({
13237
13245
  ...pickOptions(command, ['name', 'previewImageUrl']),
13238
13246
  forceBind: Boolean(readCommandOptionsWithAncestors(command).forceBind),
13247
+ ...readYesOption(command),
13239
13248
  })));
13240
13249
  addRemotePublicOptions(remote.command('bind').description('绑定当前项目到已存在的远程用户小程序').argument('<mini-program-id>', '远程小程序 ID').option('--force', '允许覆盖当前 package.json 中已有绑定')).action(createRemoteAction(handlers, resolveLogger, 'bind', (command, miniProgramId) => ({
13241
13250
  force: Boolean(readCommandOptionsWithAncestors(command).force),
@@ -13368,31 +13377,31 @@ function createCommandLoggerResolver(options) {
13368
13377
  };
13369
13378
  }
13370
13379
  const defaultClearLoginStatus = async (...args) => {
13371
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-DIgcT1gv.cjs'); });
13380
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-OqaEx-Wd.cjs'); });
13372
13381
  return clearLoginStatus(...args);
13373
13382
  };
13374
13383
  const defaultLoginToHeybox = async (...args) => {
13375
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-DIgcT1gv.cjs'); });
13384
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-OqaEx-Wd.cjs'); });
13376
13385
  return loginToHeybox(...args);
13377
13386
  };
13378
13387
  const defaultPrintLoginStatus = async (...args) => {
13379
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-DIgcT1gv.cjs'); });
13388
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-OqaEx-Wd.cjs'); });
13380
13389
  return printLoginStatus(...args);
13381
13390
  };
13382
13391
  const defaultRunCreateCommand = async (...args) => {
13383
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-DpyZCNdo.cjs'); });
13392
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-BahMMgJH.cjs'); });
13384
13393
  return runCreateCommand(...args);
13385
13394
  };
13386
13395
  const defaultRunDevCommand = async (...args) => {
13387
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-DWIpgJnn.cjs'); });
13396
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-CTuXVPpU.cjs'); });
13388
13397
  return runDevCommand(...args);
13389
13398
  };
13390
13399
  const defaultRunDoctorCommand = async (...args) => {
13391
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DBotVUQI.cjs'); });
13400
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-9gg3ZIvt.cjs'); });
13392
13401
  return runDoctorCommand(...args);
13393
13402
  };
13394
13403
  const defaultRunRemoteCommand = async (...args) => {
13395
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-DjaOc1VS.cjs'); }).then(function (n) { return n.remote; });
13404
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-zX17hOT4.cjs'); }).then(function (n) { return n.remote; });
13396
13405
  return runRemoteCommand(...args);
13397
13406
  };
13398
13407
  function resolveStandaloneLogger(options, verbose) {
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ var promises = require('node:readline/promises');
3
4
  var node_crypto = require('node:crypto');
4
5
  var node_http = require('node:http');
5
- var session = require('./session-BAgaqpNL.cjs');
6
+ var session = require('./session-D7lF9mpd.cjs');
6
7
  var browser = require('./browser-RAy8e8cV.cjs');
7
- var index = require('./index-BYMTp2I6.cjs');
8
+ var index = require('./index-DuwxUSkq.cjs');
8
9
  require('node:path');
9
10
  require('fs');
10
11
  require('constants');
@@ -134,6 +135,8 @@ function closeServer(server) {
134
135
  });
135
136
  }
136
137
 
138
+ const DEVELOPER_ENTITY_LIST_API_PATH = '/mall/developer/entity/list';
139
+ const DEVELOPER_ENTITY_SWITCH_API_PATH = '/mall/developer/entity/switch';
137
140
  async function loginToHeybox(options = {}) {
138
141
  const logger = options.logger ?? index.createCliLogger();
139
142
  const waitForBrowserCallback = options.waitForBrowserCallback ?? waitForHeyboxBrowserCallback;
@@ -162,6 +165,7 @@ async function loginToHeybox(options = {}) {
162
165
  const session$1 = session.createHeyboxAuthSession(payload, { ...options, loginBaseUrl });
163
166
  await session.writeHeyboxAuthSession(session$1, options);
164
167
  logger.success(`Heybox 登录成功:${session$1.heyboxId}`);
168
+ await selectDeveloperEntityAfterLogin(session$1, options, logger);
165
169
  logger.debug(`cache: ${session.getAuthCacheFilePath(options)}`);
166
170
  logger.info('验证命令: hb-sdk login status');
167
171
  }
@@ -179,6 +183,9 @@ async function printLoginStatus(options = {}) {
179
183
  logger.info(`heyboxId: ${status.heyboxId}`);
180
184
  logger.info(`loginBaseUrl: ${status.loginBaseUrl}`);
181
185
  logger.info(`loggedInAt: ${status.loggedInAt}`);
186
+ if (status.selectedEntity) {
187
+ logger.info(`selectedEntity: ${formatDeveloperEntity(status.selectedEntity)}`);
188
+ }
182
189
  logger.debug(`cache: ${status.cacheFile}`);
183
190
  }
184
191
  async function clearLoginStatus(options = {}) {
@@ -187,6 +194,150 @@ async function clearLoginStatus(options = {}) {
187
194
  logger.success('已清理 Heybox 登录态');
188
195
  logger.debug(`cache: ${session.getAuthCacheFilePath(options)}`);
189
196
  }
197
+ async function selectDeveloperEntityAfterLogin(session$1, options, logger) {
198
+ if (options.noSelectEntity) {
199
+ logger.info('已跳过开发者主体选择。后续可运行: hb-sdk remote entity switch <entity-id>');
200
+ return;
201
+ }
202
+ const entities = await logger.task('读取开发者主体列表', () => listDeveloperEntities(session$1, options), {
203
+ successText: '已读取开发者主体列表',
204
+ });
205
+ if (entities.length === 0) {
206
+ logger.warn('当前账号未绑定开发者平台主体。');
207
+ logger.info('请先在开发者平台完成主体绑定,再运行 remote 命令。');
208
+ return;
209
+ }
210
+ if (entities.length === 1) {
211
+ const [entity] = entities;
212
+ if (!entity.isCurrent) {
213
+ await switchDeveloperEntity(session$1, entity, options);
214
+ await session.setSelectedDeveloperEntitySnapshot(entity, options);
215
+ logger.success(`已切换开发者主体:${formatDeveloperEntity(entity)}`);
216
+ return;
217
+ }
218
+ await session.setSelectedDeveloperEntitySnapshot(entity, options);
219
+ logger.info(`当前开发者主体:${formatDeveloperEntity(entity)}`);
220
+ return;
221
+ }
222
+ printDeveloperEntityChoices(logger, entities);
223
+ const isTTY = options.isTTY ?? logger.isInteractive;
224
+ if (!isTTY) {
225
+ logger.warn('检测到多个开发者主体,非交互环境不会自动切换。');
226
+ logger.info('请运行: hb-sdk remote entity switch <entity-id>');
227
+ return;
228
+ }
229
+ const selected = options.promptSelectEntity
230
+ ? await options.promptSelectEntity(entities)
231
+ : await promptSelectDeveloperEntity(entities, options);
232
+ if (!selected) {
233
+ throw new Error('必须选择一个开发者主体;如需跳过,请显式传 --no-select-entity');
234
+ }
235
+ await switchDeveloperEntity(session$1, selected, options);
236
+ await session.setSelectedDeveloperEntitySnapshot(selected, options);
237
+ logger.success(`已切换开发者主体:${formatDeveloperEntity(selected)}`);
238
+ }
239
+ async function listDeveloperEntities(session, options) {
240
+ const result = await requestDeveloperEntityApi(DEVELOPER_ENTITY_LIST_API_PATH, 'GET', session, options);
241
+ const rawItems = readDeveloperEntityItems(result);
242
+ return rawItems.map(normalizeDeveloperEntity).filter((item) => Boolean(item));
243
+ }
244
+ async function switchDeveloperEntity(session, entity, options) {
245
+ await requestDeveloperEntityApi(DEVELOPER_ENTITY_SWITCH_API_PATH, 'POST', session, options, {
246
+ entity_id: entity.entityId,
247
+ });
248
+ }
249
+ async function requestDeveloperEntityApi(path, method, session$1, options, fields = {}) {
250
+ const apiBaseUrl = session.resolveHeyboxApiBaseUrl(options);
251
+ const context = session.createHeyboxOpenPlatformRequestContext(session$1, path, {
252
+ ...(method === 'POST' ? { contentType: 'application/x-www-form-urlencoded' } : {}),
253
+ });
254
+ const fetchImpl = options.fetchImpl ?? fetch;
255
+ const response = await fetchImpl(session.createHeyboxApiUrl(apiBaseUrl, path, context.platformParams), {
256
+ method,
257
+ headers: context.headers,
258
+ ...(method === 'POST' ? { body: new URLSearchParams(stringifyFormFields(fields)).toString() } : {}),
259
+ });
260
+ return session.readHeyboxApiEnvelope(response, { pathWithQuery: path, requireResult: method === 'GET' });
261
+ }
262
+ function stringifyFormFields(fields) {
263
+ return Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, String(value)]));
264
+ }
265
+ function readDeveloperEntityItems(result) {
266
+ if (Array.isArray(result)) {
267
+ return result;
268
+ }
269
+ if (!isRecord(result)) {
270
+ return [];
271
+ }
272
+ if (Array.isArray(result.items)) {
273
+ return result.items;
274
+ }
275
+ if (Array.isArray(result.list)) {
276
+ return result.list;
277
+ }
278
+ return [];
279
+ }
280
+ function normalizeDeveloperEntity(value) {
281
+ if (!isRecord(value)) {
282
+ return undefined;
283
+ }
284
+ const entityId = readPositiveInteger(value.entity_id ?? value.entityId);
285
+ if (entityId === undefined) {
286
+ return undefined;
287
+ }
288
+ const ownerHeyboxId = readPositiveInteger(value.owner_heybox_id ?? value.ownerHeyboxId);
289
+ return {
290
+ entityId,
291
+ entityName: readNonEmptyString(value.entity_name ?? value.entityName) ?? `主体 ${entityId}`,
292
+ ...(ownerHeyboxId === undefined ? {} : { ownerHeyboxId }),
293
+ isCurrent: value.is_current === true || value.isCurrent === true,
294
+ };
295
+ }
296
+ function readPositiveInteger(value) {
297
+ const parsed = typeof value === 'number' ? value : typeof value === 'string' && /^\d+$/.test(value.trim()) ? Number(value.trim()) : NaN;
298
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
299
+ }
300
+ function readNonEmptyString(value) {
301
+ const normalized = typeof value === 'string' ? value.trim() : '';
302
+ return normalized || undefined;
303
+ }
304
+ function printDeveloperEntityChoices(logger, entities) {
305
+ logger.info('可用开发者主体:');
306
+ entities.forEach((entity, index) => {
307
+ logger.info(`${index + 1}. ${formatDeveloperEntity(entity)}${entity.isCurrent ? ' (current)' : ''}`);
308
+ });
309
+ }
310
+ async function promptSelectDeveloperEntity(entities, options) {
311
+ const input = options.stdin ?? process.stdin;
312
+ const output = options.stderr ?? process.stderr;
313
+ const rl = promises.createInterface({ input, output: output });
314
+ try {
315
+ for (;;) {
316
+ const answer = (await rl.question('请选择开发者主体序号或 entity_id: ')).trim();
317
+ const selected = findDeveloperEntityChoice(entities, answer);
318
+ if (selected) {
319
+ return selected;
320
+ }
321
+ output.write('输入无效,请重新选择。\n');
322
+ }
323
+ }
324
+ finally {
325
+ rl.close();
326
+ }
327
+ }
328
+ function findDeveloperEntityChoice(entities, answer) {
329
+ const index = readPositiveInteger(answer);
330
+ if (index !== undefined && index <= entities.length) {
331
+ return entities[index - 1];
332
+ }
333
+ return entities.find((entity) => String(entity.entityId) === answer);
334
+ }
335
+ function formatDeveloperEntity(entity) {
336
+ return `${entity.entityName} (ID: ${entity.entityId}${entity.ownerHeyboxId === undefined ? '' : `, owner: ${entity.ownerHeyboxId}`})`;
337
+ }
338
+ function isRecord(value) {
339
+ return Object.prototype.toString.call(value) === '[object Object]';
340
+ }
190
341
 
191
342
  exports.clearLoginStatus = clearLoginStatus;
192
343
  exports.loginToHeybox = loginToHeybox;