@heybox/hb-sdk 0.5.17 → 0.5.18
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 +19 -2
- package/dist/cli-chunks/{context-mav2gs13.cjs → context-CKJlNcSN.cjs} +1 -1
- package/dist/cli-chunks/{create-CPIjDM-n.cjs → create-OZOIdeBz.cjs} +1 -1
- package/dist/cli-chunks/{dev-Cr2u9ajy.cjs → dev-DXz8izSJ.cjs} +3 -3
- package/dist/cli-chunks/{doctor-mIgvLfLl.cjs → doctor-DjMSJoQ5.cjs} +1 -1
- package/dist/cli-chunks/{index-DHWEoki_.cjs → index-Cl5HFTBW.cjs} +2 -2
- package/dist/cli-chunks/{index-Dor8wa6R.cjs → index-CsOcGUzF.cjs} +262 -15
- package/dist/cli-chunks/{login-B63QgKed.cjs → login-Ct-46gLx.cjs} +2 -2
- package/dist/cli-chunks/{remote-Dksa9s5M.cjs → remote-C77axNSw.cjs} +12 -11
- package/dist/cli-chunks/{session-BMSThs93.cjs → session-dRGPpyS1.cjs} +3 -54
- package/dist/cli.cjs +1 -1
- package/package.json +1 -1
- package/skill/references/cli.md +18 -1
- package/skill/skill.json +2 -2
package/README.md
CHANGED
|
@@ -473,10 +473,27 @@ hb-sdk login --login-base-url https://login.test.xiaoheihe.cn
|
|
|
473
473
|
hb-sdk remote deploy --api-base-url https://api.test.xiaoheihe.cn --login-base-url https://login.test.xiaoheihe.cn --release-note "测试环境验证"
|
|
474
474
|
hb-sdk remote deploy --verbose --api-base-url https://api.test.xiaoheihe.cn --login-base-url https://login.test.xiaoheihe.cn --release-note "排查预检失败"
|
|
475
475
|
|
|
476
|
-
HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1 hb-sdk remote deploy --api-base-url http://127.0.
|
|
476
|
+
HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1 hb-sdk remote deploy --api-base-url http://127.0.1:8080 --release-note "本地后台联调"
|
|
477
477
|
```
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
切换测试环境时往往需要同时配置后台 host、登录 host 和 service tag。为避免每条命令都重复书写这些 env/flag,CLI 支持加载 `.env.<name>` 预设:
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
# 在项目根准备 .env.test(可提交当团队默认,或 gitignore 仅本地保留)
|
|
483
|
+
# HB_SDK_API_BASE_URL=https://api.test.xiaoheihe.cn
|
|
484
|
+
# HB_SDK_LOGIN_BASE_URL=https://login.test.xiaoheihe.cn
|
|
485
|
+
# HB_SDK_SERVICE_TAG=my-test-tag
|
|
486
|
+
|
|
487
|
+
hb-sdk remote deploy --env test --release-note "测试环境验证" # 一次加载三项配置
|
|
488
|
+
hb-sdk remote info --env test # 复用同一预设
|
|
489
|
+
HB_SDK_ENV=test hb-sdk remote versions # 环境变量形式,CI 友好
|
|
490
|
+
hb-sdk remote deploy --env-file .env.local --release-note "本地联调" # 显式指定文件路径
|
|
491
|
+
hb-sdk remote deploy --env test --service-tag other-tag --release-note "灰度" # 单项 flag 覆盖预设
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
`--env <name>` 会读取项目根下的 `.env.<name>`,`--env-file <path>` 显式指定路径且优先级高于 `--env`;两者也可通过 `HB_SDK_ENV=<name>` 触发。加载遵循 dotenv 惯例:不覆盖进程已有的同名变量,因此 CI 或命令行显式设置的值优先。文件仅支持 `KEY=VALUE`、空行和 `#` 注释,不做变量插值;文件不存在时静默跳过。`--verbose` 会打印生效的文件路径和被跳过的 key。
|
|
495
|
+
|
|
496
|
+
`--api-base-url` 优先于 `HB_SDK_API_BASE_URL`,影响 `hb-sdk remote` 里的远端平台后台 API,包括预检、CDN 上传凭证/回调、提交审核、版本、发布、撤回、下架、重新上架、详情和白名单等调用;`--login-base-url` 优先于 `HB_SDK_LOGIN_BASE_URL`,用于 `hb-sdk login` 的登录入口,以及 remote 命令前校验当前 CLI 登录态是否属于同一个登录环境。`--service-tag <tag>` 优先于 `HB_SDK_SERVICE_TAG`,给 Heybox 后台请求附加 `x-rylai-service-tag` header,并复用命中的 tag 追加 `special_tag` 请求参数,用于开发环境路由或灰度验证;仓库内开发也可继续在 `packages/hb-sdk/src/cli/config.ts` 里按 `@heybox/hb-types` 的 `RylaiServiceTagConfig` 配置 path-prefix 级 `special_tag`。自定义地址只接受 origin,不允许包含 path、query 或 hash;API origin 默认还必须是 Heybox 受信 HTTPS 域名,只有本地联调等场景可显式使用 `--allow-unsafe-api-base-url` 或 `HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1` 放开。日志只输出 origin,不输出带身份和签名参数的完整请求 URL。`hb-sdk doctor`、npm latest 检查、mock host 的 `network.request()` 不受这些配置影响。
|
|
480
497
|
|
|
481
498
|
## hb-sdk remote 命令参考
|
|
482
499
|
|
|
@@ -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-
|
|
8
|
+
var index = require('./index-CsOcGUzF.cjs');
|
|
9
9
|
require('node:module');
|
|
10
10
|
require('os');
|
|
11
11
|
require('readline');
|
|
@@ -9,8 +9,8 @@ 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-
|
|
13
|
-
var context = require('./context-
|
|
12
|
+
var index = require('./index-CsOcGUzF.cjs');
|
|
13
|
+
var context = require('./context-CKJlNcSN.cjs');
|
|
14
14
|
require('node:process');
|
|
15
15
|
require('node:buffer');
|
|
16
16
|
require('node:util');
|
|
@@ -24,7 +24,7 @@ require('events');
|
|
|
24
24
|
require('stream');
|
|
25
25
|
require('buffer');
|
|
26
26
|
require('util');
|
|
27
|
-
require('./session-
|
|
27
|
+
require('./session-dRGPpyS1.cjs');
|
|
28
28
|
require('node:crypto');
|
|
29
29
|
require('fs');
|
|
30
30
|
require('constants');
|
|
@@ -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-
|
|
7
|
+
var index = require('./index-CsOcGUzF.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-
|
|
3
|
+
var index$2 = require('./index-CsOcGUzF.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 context$1 = require('./context-
|
|
10
|
+
var context$1 = require('./context-CKJlNcSN.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-
|
|
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-CsOcGUzF.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-
|
|
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-CsOcGUzF.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-
|
|
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-CsOcGUzF.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-
|
|
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-CsOcGUzF.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-
|
|
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-CsOcGUzF.cjs', document.baseURI).href)));
|
|
250
250
|
function __require() { return require$1("node:process"); }
|
|
251
251
|
|
|
252
252
|
var help = {};
|
|
@@ -13095,8 +13095,228 @@ function readErrorMessage(error, options = {}) {
|
|
|
13095
13095
|
return String(error);
|
|
13096
13096
|
}
|
|
13097
13097
|
|
|
13098
|
+
/**
|
|
13099
|
+
* 极简 .env 文件解析器。
|
|
13100
|
+
*
|
|
13101
|
+
* 只支持 hb-sdk CLI 需要的最小语义:KEY=VALUE、空行、`#` 注释、单/双引号包裹值。
|
|
13102
|
+
* 不做变量插值,不展开 shell 转义,避免引入额外依赖。
|
|
13103
|
+
*/
|
|
13104
|
+
/**
|
|
13105
|
+
* 解析 .env 文件内容为 key/value 记录,保持原始出现顺序的 key 列表。
|
|
13106
|
+
*/
|
|
13107
|
+
function parseDotenvFile(content) {
|
|
13108
|
+
const entries = {};
|
|
13109
|
+
const keys = [];
|
|
13110
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
13111
|
+
const line = stripInlineComment(rawLine).trim();
|
|
13112
|
+
if (!line || line.startsWith('#')) {
|
|
13113
|
+
continue;
|
|
13114
|
+
}
|
|
13115
|
+
const equalsIndex = line.indexOf('=');
|
|
13116
|
+
if (equalsIndex <= 0) {
|
|
13117
|
+
continue;
|
|
13118
|
+
}
|
|
13119
|
+
const key = line.slice(0, equalsIndex).trim();
|
|
13120
|
+
if (!isValidEnvKey(key)) {
|
|
13121
|
+
continue;
|
|
13122
|
+
}
|
|
13123
|
+
const rawValue = line.slice(equalsIndex + 1).trim();
|
|
13124
|
+
const value = unquoteDotenvValue(rawValue);
|
|
13125
|
+
if (!Object.prototype.hasOwnProperty.call(entries, key)) {
|
|
13126
|
+
keys.push(key);
|
|
13127
|
+
}
|
|
13128
|
+
entries[key] = value;
|
|
13129
|
+
}
|
|
13130
|
+
return { entries, keys };
|
|
13131
|
+
}
|
|
13132
|
+
function stripInlineComment(line) {
|
|
13133
|
+
// 仅处理未被引号包裹的行内注释,避免误伤值里的 #。
|
|
13134
|
+
let inSingle = false;
|
|
13135
|
+
let inDouble = false;
|
|
13136
|
+
for (let i = 0; i < line.length; i += 1) {
|
|
13137
|
+
const char = line[i];
|
|
13138
|
+
if (char === "'" && !inDouble) {
|
|
13139
|
+
inSingle = !inSingle;
|
|
13140
|
+
}
|
|
13141
|
+
else if (char === '"' && !inSingle) {
|
|
13142
|
+
inDouble = !inDouble;
|
|
13143
|
+
}
|
|
13144
|
+
else if (char === '#' && !inSingle && !inDouble) {
|
|
13145
|
+
return line.slice(0, i);
|
|
13146
|
+
}
|
|
13147
|
+
}
|
|
13148
|
+
return line;
|
|
13149
|
+
}
|
|
13150
|
+
function unquoteDotenvValue(value) {
|
|
13151
|
+
if (value.length >= 2) {
|
|
13152
|
+
const first = value[0];
|
|
13153
|
+
const last = value[value.length - 1];
|
|
13154
|
+
if (first === '"' && last === '"') {
|
|
13155
|
+
return value.slice(1, -1).replace(/\\(["\\$])/g, '$1');
|
|
13156
|
+
}
|
|
13157
|
+
if (first === "'" && last === "'") {
|
|
13158
|
+
return value.slice(1, -1);
|
|
13159
|
+
}
|
|
13160
|
+
}
|
|
13161
|
+
return value;
|
|
13162
|
+
}
|
|
13163
|
+
function isValidEnvKey(key) {
|
|
13164
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
13165
|
+
}
|
|
13166
|
+
|
|
13167
|
+
const DEFAULT_READ_FILE = (path) => fs$1.readFileSync(path, 'utf8');
|
|
13168
|
+
function resolveEnvPresetFilePath(argv, env = process.env, cwd = process.cwd()) {
|
|
13169
|
+
const explicit = readEnvFileArgFromArgv(argv);
|
|
13170
|
+
if (explicit) {
|
|
13171
|
+
return path.resolve(cwd, explicit);
|
|
13172
|
+
}
|
|
13173
|
+
const name = readEnvNameArgFromArgv(argv) ?? env.HB_SDK_ENV;
|
|
13174
|
+
if (name) {
|
|
13175
|
+
return path.resolve(cwd, `.env.${name}`);
|
|
13176
|
+
}
|
|
13177
|
+
return undefined;
|
|
13178
|
+
}
|
|
13179
|
+
function loadEnvPreset(argv, options = {}) {
|
|
13180
|
+
const targetEnv = options.env ?? process.env;
|
|
13181
|
+
const cwd = options.cwd ?? process.cwd();
|
|
13182
|
+
const readFile = options.readFile ?? DEFAULT_READ_FILE;
|
|
13183
|
+
const filePath = resolveEnvPresetFilePath(argv, targetEnv, cwd);
|
|
13184
|
+
if (!filePath) {
|
|
13185
|
+
return { filePath: undefined, appliedKeys: [], skippedKeys: [] };
|
|
13186
|
+
}
|
|
13187
|
+
let content;
|
|
13188
|
+
try {
|
|
13189
|
+
content = readFile(filePath);
|
|
13190
|
+
}
|
|
13191
|
+
catch {
|
|
13192
|
+
// 文件不存在或不可读时静默跳过,与 dotenv 默认行为一致。
|
|
13193
|
+
return { filePath, appliedKeys: [], skippedKeys: [] };
|
|
13194
|
+
}
|
|
13195
|
+
const { entries } = parseDotenvFile(content);
|
|
13196
|
+
const appliedKeys = [];
|
|
13197
|
+
const skippedKeys = [];
|
|
13198
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
13199
|
+
if (targetEnv[key] !== undefined && targetEnv[key] !== '') {
|
|
13200
|
+
skippedKeys.push(key);
|
|
13201
|
+
continue;
|
|
13202
|
+
}
|
|
13203
|
+
targetEnv[key] = value;
|
|
13204
|
+
appliedKeys.push(key);
|
|
13205
|
+
}
|
|
13206
|
+
return { filePath, appliedKeys, skippedKeys };
|
|
13207
|
+
}
|
|
13208
|
+
/**
|
|
13209
|
+
* 从 argv 中提取 `--env-file <path>` 的值。
|
|
13210
|
+
* 支持 `--env-file path`、`--env-file=path` 两种写法。
|
|
13211
|
+
*/
|
|
13212
|
+
function readEnvFileArgFromArgv(argv) {
|
|
13213
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
13214
|
+
const arg = argv[i];
|
|
13215
|
+
if (arg === '--env-file') {
|
|
13216
|
+
return argv[i + 1];
|
|
13217
|
+
}
|
|
13218
|
+
if (arg?.startsWith('--env-file=')) {
|
|
13219
|
+
return arg.slice('--env-file='.length);
|
|
13220
|
+
}
|
|
13221
|
+
}
|
|
13222
|
+
return undefined;
|
|
13223
|
+
}
|
|
13224
|
+
/**
|
|
13225
|
+
* 从 argv 中提取 `--env <name>` 的值。
|
|
13226
|
+
* 支持 `--env name`、`--env=name` 两种写法。
|
|
13227
|
+
*/
|
|
13228
|
+
function readEnvNameArgFromArgv(argv) {
|
|
13229
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
13230
|
+
const arg = argv[i];
|
|
13231
|
+
if (arg === '--env') {
|
|
13232
|
+
return argv[i + 1];
|
|
13233
|
+
}
|
|
13234
|
+
if (arg?.startsWith('--env=')) {
|
|
13235
|
+
return arg.slice('--env='.length);
|
|
13236
|
+
}
|
|
13237
|
+
}
|
|
13238
|
+
return undefined;
|
|
13239
|
+
}
|
|
13240
|
+
|
|
13241
|
+
const globalHeyboxCliRequestConfig = {};
|
|
13242
|
+
function configureHeyboxCliRequestConfig(config) {
|
|
13243
|
+
const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
|
|
13244
|
+
if (normalized.default_tag) {
|
|
13245
|
+
globalHeyboxCliRequestConfig.default_tag = normalized.default_tag;
|
|
13246
|
+
}
|
|
13247
|
+
else {
|
|
13248
|
+
delete globalHeyboxCliRequestConfig.default_tag;
|
|
13249
|
+
}
|
|
13250
|
+
if (normalized.special_tag) {
|
|
13251
|
+
globalHeyboxCliRequestConfig.special_tag = normalized.special_tag;
|
|
13252
|
+
}
|
|
13253
|
+
else {
|
|
13254
|
+
delete globalHeyboxCliRequestConfig.special_tag;
|
|
13255
|
+
}
|
|
13256
|
+
}
|
|
13257
|
+
function readHeyboxCliRequestConfig() {
|
|
13258
|
+
return normalizeHeyboxRylaiServiceTagConfig(globalHeyboxCliRequestConfig);
|
|
13259
|
+
}
|
|
13260
|
+
/**
|
|
13261
|
+
* 当 tag 为非空字符串时,把它设为 CLI 全局 default_tag;为空时不改动现有配置,
|
|
13262
|
+
* 避免清掉 env 预设阶段已注入的值。
|
|
13263
|
+
*/
|
|
13264
|
+
function applyServiceTagIfNeeded(tag) {
|
|
13265
|
+
const normalized = normalizeHeyboxRylaiServiceTag(tag);
|
|
13266
|
+
if (!normalized) {
|
|
13267
|
+
return;
|
|
13268
|
+
}
|
|
13269
|
+
configureHeyboxCliRequestConfig({ default_tag: normalized });
|
|
13270
|
+
}
|
|
13271
|
+
function resolveHeyboxRylaiServiceTag(pathWithQuery, config = readHeyboxCliRequestConfig()) {
|
|
13272
|
+
const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
|
|
13273
|
+
const pathname = pathWithQuery ? getPathname(pathWithQuery) : '';
|
|
13274
|
+
const specialTag = normalized.special_tag;
|
|
13275
|
+
if (pathname && specialTag?.path_prefix_list.some((prefix) => pathname.startsWith(prefix))) {
|
|
13276
|
+
return specialTag.tag_name;
|
|
13277
|
+
}
|
|
13278
|
+
return normalized.default_tag;
|
|
13279
|
+
}
|
|
13280
|
+
function normalizeHeyboxRylaiServiceTagConfig(config) {
|
|
13281
|
+
const defaultTag = normalizeHeyboxRylaiServiceTag(config.default_tag);
|
|
13282
|
+
const specialTagName = normalizeHeyboxRylaiServiceTag(config.special_tag?.tag_name);
|
|
13283
|
+
const pathPrefixList = config.special_tag?.path_prefix_list?.filter(isValidPathPrefix) || [];
|
|
13284
|
+
return {
|
|
13285
|
+
...(defaultTag ? { default_tag: defaultTag } : {}),
|
|
13286
|
+
...(specialTagName && pathPrefixList.length
|
|
13287
|
+
? {
|
|
13288
|
+
special_tag: {
|
|
13289
|
+
tag_name: specialTagName,
|
|
13290
|
+
path_prefix_list: pathPrefixList,
|
|
13291
|
+
},
|
|
13292
|
+
}
|
|
13293
|
+
: {}),
|
|
13294
|
+
};
|
|
13295
|
+
}
|
|
13296
|
+
function normalizeHeyboxRylaiServiceTag(value) {
|
|
13297
|
+
const tag = String(value ?? '').trim();
|
|
13298
|
+
if (!tag) {
|
|
13299
|
+
return undefined;
|
|
13300
|
+
}
|
|
13301
|
+
if (/[\r\n]/.test(tag)) {
|
|
13302
|
+
throw new Error('x-rylai-service-tag 不允许包含换行符');
|
|
13303
|
+
}
|
|
13304
|
+
return tag;
|
|
13305
|
+
}
|
|
13306
|
+
function isValidPathPrefix(value) {
|
|
13307
|
+
return typeof value === 'string' && value.startsWith('/') && !/[\r\n]/.test(value);
|
|
13308
|
+
}
|
|
13309
|
+
function getPathname(pathWithQuery) {
|
|
13310
|
+
try {
|
|
13311
|
+
return new URL(pathWithQuery, 'https://api.xiaoheihe.cn').pathname;
|
|
13312
|
+
}
|
|
13313
|
+
catch {
|
|
13314
|
+
return '';
|
|
13315
|
+
}
|
|
13316
|
+
}
|
|
13317
|
+
|
|
13098
13318
|
const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
|
|
13099
|
-
const BUILT_CLI_VERSION = '0.5.
|
|
13319
|
+
const BUILT_CLI_VERSION = '0.5.18';
|
|
13100
13320
|
const PACKAGE_JSON_CANDIDATES = [
|
|
13101
13321
|
path.resolve(__dirname, '..', '..', 'package.json'),
|
|
13102
13322
|
path.resolve(__dirname, '..', 'package.json'),
|
|
@@ -13134,7 +13354,9 @@ async function runCli(options = {}) {
|
|
|
13134
13354
|
const processLike = options.process ?? process;
|
|
13135
13355
|
const argv = options.argv ?? process.argv;
|
|
13136
13356
|
const verbose = hasVerboseArg(argv);
|
|
13357
|
+
const logger = resolveStandaloneLogger(options, verbose);
|
|
13137
13358
|
try {
|
|
13359
|
+
preloadCliEnvPreset(argv, { logger });
|
|
13138
13360
|
await createCliProgram(options).parseAsync(argv);
|
|
13139
13361
|
}
|
|
13140
13362
|
catch (error) {
|
|
@@ -13143,7 +13365,7 @@ async function runCli(options = {}) {
|
|
|
13143
13365
|
return;
|
|
13144
13366
|
}
|
|
13145
13367
|
if (!(error instanceof CommanderError)) {
|
|
13146
|
-
(options.printError ?? printError)(error, { logger
|
|
13368
|
+
(options.printError ?? printError)(error, { logger, verbose });
|
|
13147
13369
|
}
|
|
13148
13370
|
processLike.exit(error instanceof CommanderError ? error.exitCode : 1);
|
|
13149
13371
|
}
|
|
@@ -13167,6 +13389,8 @@ function createCliProgram(overrides = {}) {
|
|
|
13167
13389
|
.description('hb-sdk developer tools')
|
|
13168
13390
|
.version(getCliVersion())
|
|
13169
13391
|
.option('-v, --verbose', '输出详细调试信息')
|
|
13392
|
+
.option('--env <name>', '加载项目根下 .env.<name> 预设,把其中的 HB_SDK_* 变量注入当前进程(不覆盖已有值)')
|
|
13393
|
+
.option('--env-file <path>', '显式指定 .env 文件路径,优先级高于 --env')
|
|
13170
13394
|
.showHelpAfterError()
|
|
13171
13395
|
.exitOverride();
|
|
13172
13396
|
installVersionUpdateReminder(program, handlers.printUpdateReminder, resolveLogger);
|
|
@@ -13222,7 +13446,8 @@ function addRemotePublicOptions(command) {
|
|
|
13222
13446
|
.option('--json', '以 JSON 格式输出 remote 命令结果')
|
|
13223
13447
|
.option('--api-base-url <url>', 'Heybox 后台 API origin,默认读取 HB_SDK_API_BASE_URL 或生产地址')
|
|
13224
13448
|
.option('--login-base-url <url>', '校验 CLI 登录态使用的登录 origin,默认读取 HB_SDK_LOGIN_BASE_URL 或生产地址')
|
|
13225
|
-
.option('--allow-unsafe-api-base-url', '允许向非 Heybox HTTPS API origin 发送登录态,仅限本地调试')
|
|
13449
|
+
.option('--allow-unsafe-api-base-url', '允许向非 Heybox HTTPS API origin 发送登录态,仅限本地调试')
|
|
13450
|
+
.option('--service-tag <tag>', '给 Heybox 后台请求附加 x-rylai-service-tag,默认读取 HB_SDK_SERVICE_TAG'));
|
|
13226
13451
|
}
|
|
13227
13452
|
function installRemoteCommands(program, handlers, resolveLogger) {
|
|
13228
13453
|
const remote = addRemotePublicOptions(program.command('remote').description('管理当前项目绑定的远程 Heybox 工坊小程序'));
|
|
@@ -13359,6 +13584,7 @@ function readRemoteCommonOptions(command) {
|
|
|
13359
13584
|
apiBaseUrl: readStringOption(options.apiBaseUrl),
|
|
13360
13585
|
json: Boolean(options.json),
|
|
13361
13586
|
loginBaseUrl: readStringOption(options.loginBaseUrl),
|
|
13587
|
+
serviceTag: readStringOption(options.serviceTag),
|
|
13362
13588
|
verbose: Boolean(options.verbose),
|
|
13363
13589
|
};
|
|
13364
13590
|
}
|
|
@@ -13413,31 +13639,31 @@ function createCommandLoggerResolver(options) {
|
|
|
13413
13639
|
};
|
|
13414
13640
|
}
|
|
13415
13641
|
const defaultClearLoginStatus = async (...args) => {
|
|
13416
|
-
const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-
|
|
13642
|
+
const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
|
|
13417
13643
|
return clearLoginStatus(...args);
|
|
13418
13644
|
};
|
|
13419
13645
|
const defaultLoginToHeybox = async (...args) => {
|
|
13420
|
-
const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-
|
|
13646
|
+
const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
|
|
13421
13647
|
return loginToHeybox(...args);
|
|
13422
13648
|
};
|
|
13423
13649
|
const defaultPrintLoginStatus = async (...args) => {
|
|
13424
|
-
const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-
|
|
13650
|
+
const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
|
|
13425
13651
|
return printLoginStatus(...args);
|
|
13426
13652
|
};
|
|
13427
13653
|
const defaultRunCreateCommand = async (...args) => {
|
|
13428
|
-
const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-
|
|
13654
|
+
const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-OZOIdeBz.cjs'); });
|
|
13429
13655
|
return runCreateCommand(...args);
|
|
13430
13656
|
};
|
|
13431
13657
|
const defaultRunDevCommand = async (...args) => {
|
|
13432
|
-
const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-
|
|
13658
|
+
const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-DXz8izSJ.cjs'); });
|
|
13433
13659
|
return runDevCommand(...args);
|
|
13434
13660
|
};
|
|
13435
13661
|
const defaultRunDoctorCommand = async (...args) => {
|
|
13436
|
-
const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-
|
|
13662
|
+
const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DjMSJoQ5.cjs'); });
|
|
13437
13663
|
return runDoctorCommand(...args);
|
|
13438
13664
|
};
|
|
13439
13665
|
const defaultRunRemoteCommand = async (...args) => {
|
|
13440
|
-
const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-
|
|
13666
|
+
const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-C77axNSw.cjs'); });
|
|
13441
13667
|
return runRemoteCommand(...args);
|
|
13442
13668
|
};
|
|
13443
13669
|
function resolveStandaloneLogger(options, verbose) {
|
|
@@ -13495,6 +13721,25 @@ function readCommandFromActionArgs(args) {
|
|
|
13495
13721
|
const lastArg = args[args.length - 1];
|
|
13496
13722
|
return lastArg instanceof Command ? lastArg : undefined;
|
|
13497
13723
|
}
|
|
13724
|
+
/**
|
|
13725
|
+
* 在 commander 解析前加载 .env 预设,把其中的 HB_SDK_* 变量注入 process.env(不覆盖已有值),
|
|
13726
|
+
* 并把 HB_SDK_SERVICE_TAG 同步到 CLI 全局请求配置。
|
|
13727
|
+
* 这样后续 resolveHeyboxApiBaseUrl / resolveHeyboxLoginBaseUrl 读 process.env 时即可拿到预设值。
|
|
13728
|
+
*/
|
|
13729
|
+
function preloadCliEnvPreset(argv, options = {}) {
|
|
13730
|
+
const result = loadEnvPreset(argv);
|
|
13731
|
+
if (!result.filePath) {
|
|
13732
|
+
return;
|
|
13733
|
+
}
|
|
13734
|
+
options.logger?.debug(`已加载 env 预设: ${result.filePath}`);
|
|
13735
|
+
if (result.appliedKeys.length) {
|
|
13736
|
+
options.logger?.debug(`env 预设生效: ${result.appliedKeys.join(', ')}`);
|
|
13737
|
+
}
|
|
13738
|
+
if (result.skippedKeys.length) {
|
|
13739
|
+
options.logger?.debug(`env 预设跳过(已有值): ${result.skippedKeys.join(', ')}`);
|
|
13740
|
+
}
|
|
13741
|
+
applyServiceTagIfNeeded(process.env.HB_SDK_SERVICE_TAG);
|
|
13742
|
+
}
|
|
13498
13743
|
function parsePositivePort(value) {
|
|
13499
13744
|
const parsed = Number(value);
|
|
13500
13745
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
@@ -13516,6 +13761,7 @@ exports.HB_SDK_SKILL_INDEX_URL = HB_SDK_SKILL_INDEX_URL;
|
|
|
13516
13761
|
exports.HB_SDK_SKILL_INSTALL_COMMAND = HB_SDK_SKILL_INSTALL_COMMAND;
|
|
13517
13762
|
exports.HB_SDK_SKILL_NAME = HB_SDK_SKILL_NAME;
|
|
13518
13763
|
exports.HB_SDK_SKILL_SOURCE = HB_SDK_SKILL_SOURCE;
|
|
13764
|
+
exports.applyServiceTagIfNeeded = applyServiceTagIfNeeded;
|
|
13519
13765
|
exports.commonjsGlobal = commonjsGlobal;
|
|
13520
13766
|
exports.createCliLogger = createCliLogger;
|
|
13521
13767
|
exports.createCliProgram = createCliProgram;
|
|
@@ -13525,4 +13771,5 @@ exports.readErrorMessage = readErrorMessage;
|
|
|
13525
13771
|
exports.requireEnvPaths = requireEnvPaths;
|
|
13526
13772
|
exports.requireOnetime = requireOnetime;
|
|
13527
13773
|
exports.requireSafeBuffer = requireSafeBuffer;
|
|
13774
|
+
exports.resolveHeyboxRylaiServiceTag = resolveHeyboxRylaiServiceTag;
|
|
13528
13775
|
exports.runCli = runCli;
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var promises = require('node:readline/promises');
|
|
4
4
|
var node_crypto = require('node:crypto');
|
|
5
5
|
var node_http = require('node:http');
|
|
6
|
-
var session = require('./session-
|
|
6
|
+
var session = require('./session-dRGPpyS1.cjs');
|
|
7
7
|
var browser = require('./browser-RAy8e8cV.cjs');
|
|
8
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-CsOcGUzF.cjs');
|
|
9
9
|
require('node:path');
|
|
10
10
|
require('fs');
|
|
11
11
|
require('constants');
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var promises = require('node:readline/promises');
|
|
4
|
-
var
|
|
4
|
+
var index = require('./index-CsOcGUzF.cjs');
|
|
5
|
+
var session = require('./session-dRGPpyS1.cjs');
|
|
5
6
|
var childProcess = require('node:child_process');
|
|
6
7
|
var fs = require('node:fs');
|
|
7
8
|
var fs$1 = require('node:fs/promises');
|
|
8
9
|
var path = require('node:path');
|
|
9
|
-
var context = require('./context-
|
|
10
|
-
var index = require('./index-Dor8wa6R.cjs');
|
|
11
|
-
require('node:crypto');
|
|
12
|
-
require('fs');
|
|
13
|
-
require('constants');
|
|
14
|
-
require('stream');
|
|
15
|
-
require('util');
|
|
16
|
-
require('assert');
|
|
17
|
-
require('path');
|
|
10
|
+
var context = require('./context-CKJlNcSN.cjs');
|
|
18
11
|
require('node:module');
|
|
12
|
+
require('path');
|
|
19
13
|
require('os');
|
|
20
14
|
require('readline');
|
|
21
15
|
require('tty');
|
|
16
|
+
require('assert');
|
|
22
17
|
require('events');
|
|
18
|
+
require('stream');
|
|
23
19
|
require('buffer');
|
|
20
|
+
require('util');
|
|
21
|
+
require('node:crypto');
|
|
22
|
+
require('fs');
|
|
23
|
+
require('constants');
|
|
24
24
|
|
|
25
25
|
function isValidMiniappManifestVersion(version) {
|
|
26
26
|
return getMiniappManifestVersionError(version) === undefined;
|
|
@@ -250,7 +250,7 @@ async function createDefaultCosClient(uploadToken) {
|
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
252
|
async function loadCosConstructor() {
|
|
253
|
-
const cosModule = await Promise.resolve().then(function () { return require('./index-
|
|
253
|
+
const cosModule = await Promise.resolve().then(function () { return require('./index-Cl5HFTBW.cjs'); }).then(function (n) { return n.index; });
|
|
254
254
|
return cosModule.default;
|
|
255
255
|
}
|
|
256
256
|
function formatSize(bytes) {
|
|
@@ -839,6 +839,7 @@ async function runRemoteDeployCommand(options, runtime) {
|
|
|
839
839
|
return finishRemoteCommand(options, runtime, output);
|
|
840
840
|
}
|
|
841
841
|
async function createRemoteCommandContext(options, runtime) {
|
|
842
|
+
index.applyServiceTagIfNeeded(options.serviceTag);
|
|
842
843
|
const logger = resolveRemoteLogger(options, runtime);
|
|
843
844
|
const environment = await context.resolveRemoteEnvironment({
|
|
844
845
|
allowUnsafeApiBaseUrl: options.allowUnsafeApiBaseUrl,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-CsOcGUzF.cjs');
|
|
4
4
|
var node_crypto = require('node:crypto');
|
|
5
5
|
var path = require('node:path');
|
|
6
6
|
var require$$0$2 = require('fs');
|
|
@@ -67,57 +67,6 @@ function isTruthyEnvFlag(value) {
|
|
|
67
67
|
.toLowerCase());
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
const globalHeyboxCliRequestConfig = {};
|
|
71
|
-
function readHeyboxCliRequestConfig() {
|
|
72
|
-
return normalizeHeyboxRylaiServiceTagConfig(globalHeyboxCliRequestConfig);
|
|
73
|
-
}
|
|
74
|
-
function resolveHeyboxRylaiServiceTag(pathWithQuery, config = readHeyboxCliRequestConfig()) {
|
|
75
|
-
const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
|
|
76
|
-
const pathname = pathWithQuery ? getPathname(pathWithQuery) : '';
|
|
77
|
-
const specialTag = normalized.special_tag;
|
|
78
|
-
if (pathname && specialTag?.path_prefix_list.some((prefix) => pathname.startsWith(prefix))) {
|
|
79
|
-
return specialTag.tag_name;
|
|
80
|
-
}
|
|
81
|
-
return normalized.default_tag;
|
|
82
|
-
}
|
|
83
|
-
function normalizeHeyboxRylaiServiceTagConfig(config) {
|
|
84
|
-
const defaultTag = normalizeHeyboxRylaiServiceTag(config.default_tag);
|
|
85
|
-
const specialTagName = normalizeHeyboxRylaiServiceTag(config.special_tag?.tag_name);
|
|
86
|
-
const pathPrefixList = config.special_tag?.path_prefix_list?.filter(isValidPathPrefix) || [];
|
|
87
|
-
return {
|
|
88
|
-
...(defaultTag ? { default_tag: defaultTag } : {}),
|
|
89
|
-
...(specialTagName && pathPrefixList.length
|
|
90
|
-
? {
|
|
91
|
-
special_tag: {
|
|
92
|
-
tag_name: specialTagName,
|
|
93
|
-
path_prefix_list: pathPrefixList,
|
|
94
|
-
},
|
|
95
|
-
}
|
|
96
|
-
: {}),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
function normalizeHeyboxRylaiServiceTag(value) {
|
|
100
|
-
const tag = String(value ?? '').trim();
|
|
101
|
-
if (!tag) {
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
if (/[\r\n]/.test(tag)) {
|
|
105
|
-
throw new Error('x-rylai-service-tag 不允许包含换行符');
|
|
106
|
-
}
|
|
107
|
-
return tag;
|
|
108
|
-
}
|
|
109
|
-
function isValidPathPrefix(value) {
|
|
110
|
-
return typeof value === 'string' && value.startsWith('/') && !/[\r\n]/.test(value);
|
|
111
|
-
}
|
|
112
|
-
function getPathname(pathWithQuery) {
|
|
113
|
-
try {
|
|
114
|
-
return new URL(pathWithQuery, 'https://api.xiaoheihe.cn').pathname;
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return '';
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
70
|
const SIGN_VERSION = '999.0.4';
|
|
122
71
|
const SIGN_CHARSET = 'AB45STUVWZEFGJ6CH01D237IXYPQRKLMN89';
|
|
123
72
|
function createHeyboxOpenPlatformSignParams(pathname, options = {}) {
|
|
@@ -217,7 +166,7 @@ function resolveHeyboxId(session) {
|
|
|
217
166
|
?.slice('heybox_id='.length);
|
|
218
167
|
}
|
|
219
168
|
function createHeyboxAuthHeaders(session, options = {}) {
|
|
220
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
169
|
+
const serviceTag = index.resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
221
170
|
return {
|
|
222
171
|
Cookie: session.cookieHeader,
|
|
223
172
|
Referer: HEYBOX_WEB_REFERER,
|
|
@@ -227,7 +176,7 @@ function createHeyboxAuthHeaders(session, options = {}) {
|
|
|
227
176
|
}
|
|
228
177
|
function createHeyboxRequestContext(session, options = {}) {
|
|
229
178
|
const heyboxId = resolveHeyboxId(session);
|
|
230
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
179
|
+
const serviceTag = index.resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
231
180
|
return {
|
|
232
181
|
baseUrl: HEYBOX_API_BASE_URL,
|
|
233
182
|
headers: createHeyboxAuthHeaders(session, options),
|
package/dist/cli.cjs
CHANGED
package/package.json
CHANGED
package/skill/references/cli.md
CHANGED
|
@@ -169,10 +169,27 @@ HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1 hb-sdk remote deploy --api-base-url http://12
|
|
|
169
169
|
|
|
170
170
|
默认发布策略是 `auto_publish=false`:运营审核通过后使用 `hb-sdk remote versions` 查看版本状态,再用 `hb-sdk remote release <version>` 发布。需要审核通过后自动发布并下架旧线上版本时,使用 `--auto-publish`。如需让指定用户预览未发布候选版本,使用 `hb-sdk remote allowlist add <heybox_id>` 管理预览白名单。
|
|
171
171
|
|
|
172
|
-
内部测试或预发环境可通过 `HB_SDK_API_BASE_URL` / `HB_SDK_LOGIN_BASE_URL` 设置默认后台环境,也可以用 `--api-base-url` / `--login-base-url` 覆盖单次命令。自定义地址只接受 origin,不允许包含 path、query 或 hash;API origin 默认还必须是 Heybox 受信 HTTPS 域名,只有本地联调等场景可显式使用 `--allow-unsafe-api-base-url` 或 `HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1` 放开。`apiBaseUrl` 影响 `hb-sdk remote` 里的远端平台后台 API,包括预检、CDN 上传凭证/回调、提交审核、版本、发布、撤回、下架、重新上架、详情和白名单等调用;`loginBaseUrl` 用于 `hb-sdk login` 的登录入口,以及 remote 命令前校验当前 CLI 登录态是否属于同一个登录环境。开发环境如需给后台请求带 `x-rylai-service-tag` 和 `special_tag
|
|
172
|
+
内部测试或预发环境可通过 `HB_SDK_API_BASE_URL` / `HB_SDK_LOGIN_BASE_URL` 设置默认后台环境,也可以用 `--api-base-url` / `--login-base-url` 覆盖单次命令。自定义地址只接受 origin,不允许包含 path、query 或 hash;API origin 默认还必须是 Heybox 受信 HTTPS 域名,只有本地联调等场景可显式使用 `--allow-unsafe-api-base-url` 或 `HB_SDK_ALLOW_UNSAFE_API_BASE_URL=1` 放开。`apiBaseUrl` 影响 `hb-sdk remote` 里的远端平台后台 API,包括预检、CDN 上传凭证/回调、提交审核、版本、发布、撤回、下架、重新上架、详情和白名单等调用;`loginBaseUrl` 用于 `hb-sdk login` 的登录入口,以及 remote 命令前校验当前 CLI 登录态是否属于同一个登录环境。开发环境如需给后台请求带 `x-rylai-service-tag` 和 `special_tag`,优先用 `--service-tag <tag>` 或 `HB_SDK_SERVICE_TAG`;path-prefix 级 `special_tag` 仍可在 `packages/hb-sdk/src/cli/config.ts` 里按 `@heybox/hb-types` 的 `RylaiServiceTagConfig` 配置。日志只输出 origin,不输出带身份和签名参数的完整请求 URL。
|
|
173
173
|
|
|
174
174
|
`hb-sdk doctor`、npm latest 检查、mock host 的 `network.request()` 不受这些配置影响。
|
|
175
175
|
|
|
176
|
+
切换测试环境时往往需要同时配置后台 host、登录 host 和 service tag。CLI 支持加载 `.env.<name>` 预设,把其中的 `HB_SDK_*` 变量一次性注入当前进程(不覆盖已有值):`--env <name>` 读取项目根下的 `.env.<name>`,`--env-file <path>` 显式指定路径且优先级更高,也可用 `HB_SDK_ENV=<name>` 触发。文件仅支持 `KEY=VALUE`、空行和 `#` 注释,不做变量插值;文件不存在时静默跳过。
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# 项目根准备 .env.test
|
|
180
|
+
# HB_SDK_API_BASE_URL=https://api.test.xiaoheihe.cn
|
|
181
|
+
# HB_SDK_LOGIN_BASE_URL=https://login.test.xiaoheihe.cn
|
|
182
|
+
# HB_SDK_SERVICE_TAG=my-test-tag
|
|
183
|
+
|
|
184
|
+
hb-sdk remote deploy --env test --release-note "测试环境验证"
|
|
185
|
+
hb-sdk remote info --env test
|
|
186
|
+
HB_SDK_ENV=test hb-sdk remote versions
|
|
187
|
+
hb-sdk remote deploy --env-file .env.local --release-note "本地联调"
|
|
188
|
+
hb-sdk remote deploy --env test --service-tag other-tag --release-note "灰度" # 单项 flag 覆盖预设
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`--env-file` 优先于 `--env`,`--service-tag` / `--api-base-url` / `--login-base-url` 优先于 `.env` 预设注入的同名变量,而预设又不会覆盖进程已有的环境变量,因此优先级为 flag > 进程 env > `.env` 预设 > 默认值。
|
|
192
|
+
|
|
176
193
|
Before precheck, build, upload, or submit audit, `hb-sdk remote deploy` must verify that the current project's bound mini-program belongs to the server-side current entity. If `detail.entity_id` differs from the current entity, the command fails with both entity ids/names and suggests `hb-sdk remote entity switch <entity-id>`. It must not auto-switch entities and must not continue into precheck/build/upload/submit on mismatch.
|
|
177
194
|
|
|
178
195
|
Agent rules:
|
package/skill/skill.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hb-sdk",
|
|
3
|
-
"skillVersion": "0.5.17+skill.
|
|
3
|
+
"skillVersion": "0.5.17+skill.0ad061ac9da8",
|
|
4
4
|
"sdk": {
|
|
5
5
|
"package": "@heybox/hb-sdk",
|
|
6
6
|
"version": "0.5.17",
|
|
7
7
|
"compatibility": "0.5.17"
|
|
8
8
|
},
|
|
9
9
|
"source": "https://open.xiaoheihe.cn/agent-skills/hb-sdk",
|
|
10
|
-
"integrity": "sha256-
|
|
10
|
+
"integrity": "sha256-0ad061ac9da821bfea0db71d30404999c1bd3eb5fcddfb0c22211bd9939db2ae"
|
|
11
11
|
}
|