@heybox/hb-sdk 0.8.4 → 0.8.5
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/CHANGELOG.md +25 -0
- package/dist/cli-chunks/{build-DgV-or9j.cjs → build-zYnPSPFa.cjs} +5 -5
- package/dist/cli-chunks/{context-DlcETCGM.cjs → context-DWoKsM_O.cjs} +2 -2
- package/dist/cli-chunks/{create-BjJ6U5qS.cjs → create-C9FcEn9Y.cjs} +1 -1
- package/dist/cli-chunks/{dev-hIWir4Bp.cjs → dev-VxeEocjt.cjs} +321 -25
- package/dist/cli-chunks/{doctor-DImHJjzI.cjs → doctor-6Cf9o1hD.cjs} +1 -1
- package/dist/cli-chunks/{index-CbDWlPpw.cjs → index-BpLYUwNe.cjs} +2 -2
- package/dist/cli-chunks/{index-CO8AEaXW.cjs → index-Brq_-WV3.cjs} +159 -67
- package/dist/cli-chunks/{index.esm-COo1T4B1.cjs → index.esm-DMvmTtIS.cjs} +7 -7
- package/dist/cli-chunks/{login-DbbuUauB.cjs → login-DeZpNrkY.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-Dw04aEsD.cjs → project-vite-TFEwLzYM.cjs} +1 -1
- package/dist/cli-chunks/{remote-CWeqNVk_.cjs → remote-DOU11SNj.cjs} +7 -7
- package/dist/cli-chunks/{runtime-gate-PxUnfrPH.cjs → runtime-gate-DikSEEtm.cjs} +1 -1
- package/dist/cli-chunks/{runtime-permission-env-9GWrfOTi.cjs → runtime-permission-env-Bs_JqpTM.cjs} +1 -1
- package/dist/cli-chunks/{session-CRiCQkg-.cjs → session-CbisOcE4.cjs} +63 -1
- package/dist/cli-chunks/{skill-BZFvZvOT.cjs → skill-B82gXQhX.cjs} +2 -2
- package/dist/cli-chunks/{version-Bk5ehprU.cjs → version-UEmqQ6A-.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-MOwoKrAP.js +102 -0
- package/dist/devtools/browser-dev-host/assets/{desktop-app-launch-DnjiCJj1.js → desktop-app-launch-BcQjavzW.js} +1 -1
- package/dist/devtools/browser-dev-host/assets/{index-CjUagRoX.js → index-CS-AbGTE.js} +3 -3
- package/dist/devtools/browser-dev-host/index.html +2 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/vite.cjs.js +1 -1
- package/dist/vite.esm.js +1 -1
- package/package.json +5 -5
- package/skill/skill.json +4 -4
- package/types/modules/auth/index.d.ts +4 -0
- package/types/modules/cloud/index.d.ts +25 -0
- package/types/modules/user/index.d.ts +16 -0
- package/types/protocol/dev-session.d.ts +18 -0
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-C_NWoBa2.js +0 -102
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
本文件随 `@heybox/hb-sdk` npm 包公开分发,只记录外部小程序开发者可观察到的变化。
|
|
4
4
|
|
|
5
|
+
## 0.8.5 - 2026-10-02
|
|
6
|
+
|
|
7
|
+
> 影响级别:必须操作
|
|
8
|
+
> 开发者动作:使用手机真机调试时升级至 `0.8.5` 并重新运行 `hb-sdk dev`;小程序代码中依赖旧错误码的失败分支需按新的 `RATE_LIMITED` / `RATE_LIMITED_BY_RUNTIME` 调整。
|
|
9
|
+
> 兼容范围:公开 SDK API 形状与权限模型不变;小程序接口遇到平台限流时的错误码由 `REQUEST_FAILED` / `UNAUTHORIZED` 统一为 `RATE_LIMITED`,属有意的行为变更。Runtime 私有接口以外的公开网络能力不受影响。
|
|
10
|
+
|
|
11
|
+
### 必须操作
|
|
12
|
+
|
|
13
|
+
- 小程序接口遇到平台限流(HTTP 403/429)时返回的错误码统一为 `RATE_LIMITED`:错误数据里的 `status` 为上游状态码,`retryAfterMs`(可能缺失)为建议退避时长。此前分别返回 `REQUEST_FAILED`(auth / user / home_v2)或 `UNAUTHORIZED`(cloud.leaderboard,401 仍为 `UNAUTHORIZED`)。
|
|
14
|
+
- 新增本地拒绝错误码 `RATE_LIMITED_BY_RUNTIME`:Runtime 自身的每 session 配额与同一接口的循环检测触发时返回,错误数据里的 `origin` 为 `budget` 或 `loop`,请求不会到达上游。遇到上述两个错误码时请停止立即重试,避免把用户 IP 打成被封。
|
|
15
|
+
|
|
16
|
+
### 行为调整
|
|
17
|
+
|
|
18
|
+
- `user.getInfo()` / `auth.login()` / 排行榜接口 的同一份结果会在短时间内复用(身份 30s、资料 60s、榜单沿用既有 5 分钟)。账号切换与授权撤销会立即失效;Steam 换绑 / 解绑最多 30s 后生效。
|
|
19
|
+
- `hb-sdk dev` 会短暂复用已读取的调试信息,并在读取失败后逐步延长重试间隔,不再持续请求远端。
|
|
20
|
+
- 被平台限流时会暂停刷新并给出预计恢复时间,提示不要反复重启。
|
|
21
|
+
|
|
22
|
+
### 问题修复
|
|
23
|
+
|
|
24
|
+
- 修复手机真机调试反复重连时持续请求远端调试信息、进而触发平台限流的问题。
|
|
25
|
+
|
|
26
|
+
### 文档与工具
|
|
27
|
+
|
|
28
|
+
- 被平台限流时提示升级到最新版本。
|
|
29
|
+
|
|
5
30
|
## 0.8.4 - 2026-09-25
|
|
6
31
|
|
|
7
32
|
> 影响级别:常规
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
var fs$1 = require('node:fs');
|
|
4
4
|
var fs = require('node:fs/promises');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var runtimePermissionEnv = require('./runtime-permission-env-
|
|
6
|
+
var runtimePermissionEnv = require('./runtime-permission-env-Bs_JqpTM.cjs');
|
|
7
7
|
require('node:crypto');
|
|
8
8
|
require('node:zlib');
|
|
9
|
-
var runtimeGate = require('./runtime-gate-
|
|
10
|
-
var index = require('./index-
|
|
11
|
-
var projectVite = require('./project-vite-
|
|
12
|
-
require('./version-
|
|
9
|
+
var runtimeGate = require('./runtime-gate-DikSEEtm.cjs');
|
|
10
|
+
var index = require('./index-Brq_-WV3.cjs');
|
|
11
|
+
var projectVite = require('./project-vite-TFEwLzYM.cjs');
|
|
12
|
+
require('./version-UEmqQ6A-.cjs');
|
|
13
13
|
require('node:async_hooks');
|
|
14
14
|
require('node:module');
|
|
15
15
|
require('path');
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
var node_crypto = require('node:crypto');
|
|
4
4
|
var fs = require('node:fs/promises');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var runtimePermissionEnv = require('./runtime-permission-env-
|
|
6
|
+
var runtimePermissionEnv = require('./runtime-permission-env-Bs_JqpTM.cjs');
|
|
7
7
|
var fs$1 = require('node:fs');
|
|
8
8
|
var sharp = require('sharp');
|
|
9
|
-
var session = require('./session-
|
|
9
|
+
var session = require('./session-CbisOcE4.cjs');
|
|
10
10
|
|
|
11
11
|
async function inspectBasicInfoImage(bytes, sourcePath, kind) {
|
|
12
12
|
const inspected = await inspectDecodedBasicInfoImage(bytes, kind);
|
|
@@ -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-Brq_-WV3.cjs');
|
|
9
9
|
require('node:module');
|
|
10
10
|
require('os');
|
|
11
11
|
require('node:crypto');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var context = require('./context-
|
|
3
|
+
var context = require('./context-DWoKsM_O.cjs');
|
|
4
4
|
var node_crypto = require('node:crypto');
|
|
5
5
|
var fs = require('node:fs');
|
|
6
|
-
var runtimePermissionEnv = require('./runtime-permission-env-
|
|
6
|
+
var runtimePermissionEnv = require('./runtime-permission-env-Bs_JqpTM.cjs');
|
|
7
7
|
var os = require('node:os');
|
|
8
8
|
var path = require('node:path');
|
|
9
9
|
var net = require('node:net');
|
|
@@ -12,13 +12,13 @@ var node_http = require('node:http');
|
|
|
12
12
|
var node_module = require('node:module');
|
|
13
13
|
var undici = require('undici');
|
|
14
14
|
var fs$1 = require('node:fs/promises');
|
|
15
|
-
var index = require('./index-
|
|
15
|
+
var index = require('./index-Brq_-WV3.cjs');
|
|
16
16
|
var require$$0$1 = require('crypto');
|
|
17
17
|
var require$$0 = require('buffer');
|
|
18
|
-
var session = require('./session-
|
|
18
|
+
var session = require('./session-CbisOcE4.cjs');
|
|
19
19
|
var browser = require('./browser-RAy8e8cV.cjs');
|
|
20
|
-
var projectVite = require('./project-vite-
|
|
21
|
-
var version = require('./version-
|
|
20
|
+
var projectVite = require('./project-vite-TFEwLzYM.cjs');
|
|
21
|
+
var version = require('./version-UEmqQ6A-.cjs');
|
|
22
22
|
require('node:zlib');
|
|
23
23
|
|
|
24
24
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -1247,6 +1247,12 @@ function createContextFields(context) {
|
|
|
1247
1247
|
local_dev_launch_token: context.localDevLaunchToken,
|
|
1248
1248
|
mini_program_id: context.miniProgramId,
|
|
1249
1249
|
companion_manifest_sha256: context.companionManifestSha256,
|
|
1250
|
+
// 限流状态是加性字段:限流时才写入;显式置 null 表示已恢复,需要覆盖旧快照里的状态。
|
|
1251
|
+
...(context.rateLimit
|
|
1252
|
+
? { rate_limit: context.rateLimit }
|
|
1253
|
+
: context.rateLimit === null
|
|
1254
|
+
? { rate_limit: null }
|
|
1255
|
+
: {}),
|
|
1250
1256
|
};
|
|
1251
1257
|
}
|
|
1252
1258
|
function validateDevSessionCreatePayload(payload, allowedMiniUrlOrigins, runtimePermissions) {
|
|
@@ -1986,8 +1992,8 @@ const DEFAULT_CHANNEL_TRANSPORT = {
|
|
|
1986
1992
|
};
|
|
1987
1993
|
const IPV4_LOOPBACK_ADDRESSES = new net.BlockList();
|
|
1988
1994
|
IPV4_LOOPBACK_ADDRESSES.addSubnet('127.0.0.0', 8, 'ipv4');
|
|
1989
|
-
const { WebSocket, WebSocketServer } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/dev-
|
|
1990
|
-
const { parse: parseHtml } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/dev-
|
|
1995
|
+
const { WebSocket, WebSocketServer } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/dev-VxeEocjt.cjs', document.baseURI).href)))('ws');
|
|
1996
|
+
const { parse: parseHtml } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/dev-VxeEocjt.cjs', document.baseURI).href)))('parse5');
|
|
1991
1997
|
const BROWSER_DEV_HOST_ROOT_CANDIDATES = [
|
|
1992
1998
|
path.resolve(__dirname, 'devtools/browser-dev-host'),
|
|
1993
1999
|
path.resolve(__dirname, '../devtools/browser-dev-host'),
|
|
@@ -11086,7 +11092,7 @@ function assertNodeRuntimeCapabilities(ctx, settings) {
|
|
|
11086
11092
|
function createNodeRealtimeDriverRegistry() {
|
|
11087
11093
|
const registry = createRuntimeRealtimeDriverRegistry();
|
|
11088
11094
|
registry.registerLazy('node-websocket', async () => {
|
|
11089
|
-
const mod = await Promise.resolve().then(function () { return require('./index.esm-
|
|
11095
|
+
const mod = await Promise.resolve().then(function () { return require('./index.esm-DMvmTtIS.cjs'); });
|
|
11090
11096
|
return mod.createNodeWebSocketRuntimeDriver();
|
|
11091
11097
|
});
|
|
11092
11098
|
return registry;
|
|
@@ -15212,6 +15218,139 @@ const COMPANION_ARTIFACT_ACCESS_TOKEN_ENV = 'HB_SDK_COMPANION_ARTIFACT_ACCESS_TO
|
|
|
15212
15218
|
// 本地 PC 调试 manifest 的专用令牌:开窗时扩展还没拿到 LocalDevelopmentBinding,只能靠启动 URI 带来。
|
|
15213
15219
|
const MINI_PROGRAM_MANIFEST_ACCESS_TOKEN_ENV = 'HB_SDK_MINI_PROGRAM_MANIFEST_ACCESS_TOKEN';
|
|
15214
15220
|
const COMPANION_ARTIFACT_ACCESS_TOKEN_HEADER = 'x-hb-sdk-companion-dev-token';
|
|
15221
|
+
/** Dev Context 结果缓存 TTL 默认值;手机端重连不再 1:1 产生远端请求。 */
|
|
15222
|
+
const DEFAULT_DEV_CONTEXT_CACHE_TTL_MS = 30_000;
|
|
15223
|
+
/** 覆盖 Dev Context 缓存 TTL(毫秒);设为 0 关闭缓存。 */
|
|
15224
|
+
const DEV_CONTEXT_CACHE_TTL_ENV = 'HB_SDK_DEV_CONTEXT_TTL_MS';
|
|
15225
|
+
/** 普通失败的指数退避起点。 */
|
|
15226
|
+
const DEFAULT_DEV_CONTEXT_BACKOFF_START_MS = 1_000;
|
|
15227
|
+
/** 普通失败的指数退避上限(60s)。 */
|
|
15228
|
+
const DEFAULT_DEV_CONTEXT_BACKOFF_MAX_MS = 60_000;
|
|
15229
|
+
/** 限流类失败(403/429)的退避起点。 */
|
|
15230
|
+
const RATE_LIMIT_BACKOFF_START_MS = 30_000;
|
|
15231
|
+
/** 限流类失败的退避上限(300s)。 */
|
|
15232
|
+
const RATE_LIMIT_BACKOFF_MAX_MS = 300_000;
|
|
15233
|
+
/** 退避抖动比例:±20%。 */
|
|
15234
|
+
const DEV_CONTEXT_BACKOFF_JITTER_RATIO = 0.2;
|
|
15235
|
+
/** 覆盖退避上限(毫秒);同时作用于普通失败与限流类失败。 */
|
|
15236
|
+
const DEV_CONTEXT_BACKOFF_MAX_ENV = 'HB_SDK_BACKOFF_MAX_MS';
|
|
15237
|
+
/** 缓存命中的限流结果最长压制时间,避免封禁期内继续打远端。 */
|
|
15238
|
+
const DEV_CONTEXT_RATE_LIMIT_CACHE_MAX_MS = 300_000;
|
|
15239
|
+
/**
|
|
15240
|
+
* 启动时命中限流、值得等待窗口过去的时长上限(毫秒)。
|
|
15241
|
+
*
|
|
15242
|
+
* 只有网关明确给出、且不超过该上限的窗口才等待并重试一次(自动恢复,不必重启 CLI);
|
|
15243
|
+
* 更长或未知的窗口直接跳过等待,按限流原因阻塞真机调试——事故里封禁 24h,等下去只会把
|
|
15244
|
+
* `hb-sdk dev` 启动拖住几分钟却依然恢复不了。
|
|
15245
|
+
*/
|
|
15246
|
+
const DEV_CONTEXT_STARTUP_RATE_LIMIT_WAIT_MAX_MS = 30_000;
|
|
15247
|
+
/** 读取 Dev Context 缓存 TTL;非法值回落到默认 30s,0 表示关闭缓存。 */
|
|
15248
|
+
function resolveDevContextCacheTtlMs(env = process.env) {
|
|
15249
|
+
const raw = env[DEV_CONTEXT_CACHE_TTL_ENV];
|
|
15250
|
+
if (raw === undefined || raw.trim() === '')
|
|
15251
|
+
return DEFAULT_DEV_CONTEXT_CACHE_TTL_MS;
|
|
15252
|
+
const parsed = Number(raw);
|
|
15253
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_DEV_CONTEXT_CACHE_TTL_MS;
|
|
15254
|
+
}
|
|
15255
|
+
/**
|
|
15256
|
+
* 带 TTL 的 Dev Context 结果缓存。
|
|
15257
|
+
*
|
|
15258
|
+
* key = `projectRoot` + 当前绑定的 `miniProgramId`:同一项目内的启动读取、设备会话读取和
|
|
15259
|
+
* 权限刷新共用一份结果,避免手机端每次重连都打一次远端 `detail`。TTL 内命中不打远端;
|
|
15260
|
+
* `ttlMs` 为 0 时关闭缓存。
|
|
15261
|
+
*/
|
|
15262
|
+
function createDevContextCache(options) {
|
|
15263
|
+
const now = options.now ?? Date.now;
|
|
15264
|
+
const entries = new Map();
|
|
15265
|
+
const inflight = new Map();
|
|
15266
|
+
/**
|
|
15267
|
+
* 全局代际:任一次失效都自增,早于本次失效发起的请求不得写回缓存。
|
|
15268
|
+
*
|
|
15269
|
+
* 刻意不用「按 key 记录 generation」:那样全量失效时只能推进已经登记过的 key,
|
|
15270
|
+
* 而首次被全量失效的 key 不在表里,旧结果仍会回填(生产路径走的正是无参失效)。
|
|
15271
|
+
*/
|
|
15272
|
+
let generation = 0;
|
|
15273
|
+
const cacheEnabled = options.ttlMs > 0;
|
|
15274
|
+
const resolveTtlMs = (value) => {
|
|
15275
|
+
const dynamic = options.ttlMsOf?.(value);
|
|
15276
|
+
return typeof dynamic === 'number' && Number.isFinite(dynamic) && dynamic > 0
|
|
15277
|
+
? Math.max(options.ttlMs, Math.min(dynamic, DEV_CONTEXT_RATE_LIMIT_CACHE_MAX_MS))
|
|
15278
|
+
: options.ttlMs;
|
|
15279
|
+
};
|
|
15280
|
+
return {
|
|
15281
|
+
invalidate: (key) => {
|
|
15282
|
+
generation += 1;
|
|
15283
|
+
if (key === undefined) {
|
|
15284
|
+
entries.clear();
|
|
15285
|
+
inflight.clear();
|
|
15286
|
+
return;
|
|
15287
|
+
}
|
|
15288
|
+
entries.delete(key);
|
|
15289
|
+
inflight.delete(key);
|
|
15290
|
+
},
|
|
15291
|
+
peek: (key) => entries.get(key)?.value,
|
|
15292
|
+
read: (key) => {
|
|
15293
|
+
if (cacheEnabled) {
|
|
15294
|
+
const cached = entries.get(key);
|
|
15295
|
+
if (cached && cached.expiresAt > now())
|
|
15296
|
+
return Promise.resolve(cached.value);
|
|
15297
|
+
if (cached)
|
|
15298
|
+
entries.delete(key);
|
|
15299
|
+
}
|
|
15300
|
+
const pending = inflight.get(key);
|
|
15301
|
+
if (pending)
|
|
15302
|
+
return pending;
|
|
15303
|
+
const readGeneration = generation;
|
|
15304
|
+
const promise = options
|
|
15305
|
+
.load(key)
|
|
15306
|
+
.then((value) => {
|
|
15307
|
+
// 主动失效后,早先 in-flight 的结果不得写回缓存;ttlMs 为 0 表示完全关闭缓存。
|
|
15308
|
+
if (cacheEnabled && readGeneration === generation) {
|
|
15309
|
+
const ttlMs = resolveTtlMs(value);
|
|
15310
|
+
if (ttlMs > 0)
|
|
15311
|
+
entries.set(key, { expiresAt: now() + ttlMs, value });
|
|
15312
|
+
}
|
|
15313
|
+
return value;
|
|
15314
|
+
})
|
|
15315
|
+
.finally(() => {
|
|
15316
|
+
if (inflight.get(key) === promise)
|
|
15317
|
+
inflight.delete(key);
|
|
15318
|
+
});
|
|
15319
|
+
inflight.set(key, promise);
|
|
15320
|
+
return promise;
|
|
15321
|
+
},
|
|
15322
|
+
};
|
|
15323
|
+
}
|
|
15324
|
+
/** 退避上限:普通失败默认 60s,限流类默认 300s;两者都可被 HB_SDK_BACKOFF_MAX_MS 覆盖。 */
|
|
15325
|
+
function resolveDevContextBackoffLimits(env = process.env) {
|
|
15326
|
+
const raw = env[DEV_CONTEXT_BACKOFF_MAX_ENV];
|
|
15327
|
+
const parsed = raw === undefined || raw.trim() === '' ? Number.NaN : Number(raw);
|
|
15328
|
+
const override = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
15329
|
+
return {
|
|
15330
|
+
normalMaxMs: override ?? DEFAULT_DEV_CONTEXT_BACKOFF_MAX_MS,
|
|
15331
|
+
// 限流上限不得低于其起点,否则退避会退化成固定间隔。
|
|
15332
|
+
rateLimitMaxMs: Math.max(RATE_LIMIT_BACKOFF_START_MS, override ?? RATE_LIMIT_BACKOFF_MAX_MS),
|
|
15333
|
+
};
|
|
15334
|
+
}
|
|
15335
|
+
/**
|
|
15336
|
+
* 计算 Dev Context 失败退避时长。
|
|
15337
|
+
*
|
|
15338
|
+
* 普通失败 `1s → 2s → 4s → … → 60s`;限流类失败(403/429)`30s → 60s → … → 300s`;
|
|
15339
|
+
* 两者都带 ±20% 抖动,避免多个客户端同步重试。
|
|
15340
|
+
*/
|
|
15341
|
+
function computeDevContextBackoffDelayMs(options) {
|
|
15342
|
+
const limits = resolveDevContextBackoffLimits(options.env);
|
|
15343
|
+
const rateLimited = options.rateLimited === true;
|
|
15344
|
+
const startMs = rateLimited ? RATE_LIMIT_BACKOFF_START_MS : DEFAULT_DEV_CONTEXT_BACKOFF_START_MS;
|
|
15345
|
+
const maxMs = rateLimited ? limits.rateLimitMaxMs : limits.normalMaxMs;
|
|
15346
|
+
const attempt = Number.isFinite(options.attempt) ? Math.max(0, Math.floor(options.attempt)) : 0;
|
|
15347
|
+
const exponentialMs = startMs * 2 ** Math.min(attempt, 24);
|
|
15348
|
+
const random = options.random ?? Math.random;
|
|
15349
|
+
const randomValue = Math.min(1, Math.max(0, random()));
|
|
15350
|
+
const jittered = exponentialMs * (1 - DEV_CONTEXT_BACKOFF_JITTER_RATIO + 2 * DEV_CONTEXT_BACKOFF_JITTER_RATIO * randomValue);
|
|
15351
|
+
// 先抖动再封顶:否则 300s 的限流上限实际会被 ±20% 抖动突破到 360s。
|
|
15352
|
+
return Math.max(1, Math.round(Math.min(maxMs, jittered)));
|
|
15353
|
+
}
|
|
15215
15354
|
async function runDevCommand(options, runtime = {}) {
|
|
15216
15355
|
const logger = runtime.logger ?? index.createCliLogger();
|
|
15217
15356
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
@@ -15237,13 +15376,64 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15237
15376
|
const devSessionId = node_crypto.randomBytes(16).toString('hex');
|
|
15238
15377
|
const devContextPath = `/__hb_sdk__/dev-context/${node_crypto.randomBytes(32).toString('hex')}`;
|
|
15239
15378
|
const miniProgramPlatforms = runtimePermissionEnv.readMiniappPlatformsFromPackageJson(projectRoot);
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15379
|
+
// A1:Dev Context 结果缓存。启动读取、设备会话读取和权限刷新共用同一份结果,
|
|
15380
|
+
// 手机端重连不再 1:1 产生远端 `detail` 请求;限流时按网关建议时长延长压制。
|
|
15381
|
+
const defaultSleep = (ms) => new Promise(resolve => { setTimeout(resolve, ms).unref?.(); });
|
|
15382
|
+
const devContextCache = createDevContextCache({
|
|
15383
|
+
load: () => loadDevLaunchContext({
|
|
15384
|
+
env: runtime.env,
|
|
15385
|
+
fetchImpl,
|
|
15386
|
+
logger,
|
|
15387
|
+
projectRoot,
|
|
15388
|
+
timeoutMs: runtime.devContextTimeoutMs ?? DEFAULT_DEV_CONTEXT_TIMEOUT_MS,
|
|
15389
|
+
}),
|
|
15390
|
+
ttlMs: resolveDevContextCacheTtlMs(runtime.env ?? process.env),
|
|
15391
|
+
ttlMsOf: (result) => result.context.rateLimit?.retryAfterMs,
|
|
15246
15392
|
});
|
|
15393
|
+
/**
|
|
15394
|
+
* 读取 Dev Context。
|
|
15395
|
+
*
|
|
15396
|
+
* key 里带上当前 `package.json` 绑定的 miniProgramId:项目绑定变更会直接换成另一个缓存 key,
|
|
15397
|
+
* 立即重新请求远端,而不是等 30s TTL(限流时 300s)过期后才发现换了小程序。
|
|
15398
|
+
* 读绑定是本地文件读取,不打远端,符合「只读本地快照」的高频读范式。
|
|
15399
|
+
*/
|
|
15400
|
+
const readDevLaunchContext = async () => {
|
|
15401
|
+
const boundMiniProgramId = await context.readBoundMiniProgramId(projectRoot).catch(() => undefined);
|
|
15402
|
+
return devContextCache.read(`${projectRoot}\0${boundMiniProgramId ?? ''}`);
|
|
15403
|
+
};
|
|
15404
|
+
let { context: devLaunchContext, miniProgram } = await readDevLaunchContext();
|
|
15405
|
+
let lastRateLimitHint = '';
|
|
15406
|
+
// A3:提示只在内容变化时输出一次,避免手机端反复重连刷屏。
|
|
15407
|
+
const reportRateLimitOnce = (state) => {
|
|
15408
|
+
const hint = index.formatCliRateLimitHint(state);
|
|
15409
|
+
if (hint === lastRateLimitHint)
|
|
15410
|
+
return;
|
|
15411
|
+
lastRateLimitHint = hint;
|
|
15412
|
+
reportDevContextRateLimit(logger, state, runtime.env);
|
|
15413
|
+
};
|
|
15414
|
+
if (devLaunchContext.rateLimit?.limited)
|
|
15415
|
+
reportRateLimitOnce(devLaunchContext.rateLimit);
|
|
15416
|
+
// 启动即被限流时 `miniProgramId` 缺失,后面不会创建 token session,也就没有任何刷新路径
|
|
15417
|
+
// (三条读取入口都以 `source === 'remote'` 为前提),开发者只能重启 CLI。这里先等网关窗口
|
|
15418
|
+
// 过去再重试一次:窗口短就自动恢复,窗口长(例如封禁 24h)则不再空等,转为按限流原因阻塞
|
|
15419
|
+
// 真机调试,而不是误报「未登录 / 未绑定」。
|
|
15420
|
+
const startupRateLimit = devLaunchContext.rateLimit;
|
|
15421
|
+
if (!devLaunchContext.miniProgramId && startupRateLimit?.limited) {
|
|
15422
|
+
const windowMs = startupRateLimit.retryAfterMs;
|
|
15423
|
+
if (windowMs !== undefined && windowMs <= DEV_CONTEXT_STARTUP_RATE_LIMIT_WAIT_MAX_MS) {
|
|
15424
|
+
logger.warn(`已被网关限流,等待 ${Math.round(windowMs / 1000)} 秒后重试一次…`);
|
|
15425
|
+
await (runtime.sleep ?? defaultSleep)(windowMs);
|
|
15426
|
+
// 限流结果在缓存里最多压制 300s,重试前必须先失效,否则读到的还是同一条。
|
|
15427
|
+
devContextCache.invalidate();
|
|
15428
|
+
const retried = await readDevLaunchContext();
|
|
15429
|
+
if (retried.context.miniProgramId) {
|
|
15430
|
+
devLaunchContext = retried.context;
|
|
15431
|
+
miniProgram = retried.miniProgram;
|
|
15432
|
+
// 已恢复正常:允许后续再次限流时重新提示。
|
|
15433
|
+
lastRateLimitHint = '';
|
|
15434
|
+
}
|
|
15435
|
+
}
|
|
15436
|
+
}
|
|
15247
15437
|
let currentDevContext = devLaunchContext;
|
|
15248
15438
|
let contextRevision = 1;
|
|
15249
15439
|
let launchRuntimePermissions = context.createMobileDevSessionRuntimePermissions(devLaunchContext);
|
|
@@ -15253,6 +15443,7 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15253
15443
|
let currentExpiresAt;
|
|
15254
15444
|
let refreshDevCsp;
|
|
15255
15445
|
let lastTemporaryWarning = '';
|
|
15446
|
+
let hasReportedBindingChange = false;
|
|
15256
15447
|
let tokenSession;
|
|
15257
15448
|
const updateLocalContext = (allowedTemporaryKeys) => {
|
|
15258
15449
|
const grant = runtimePermissionEnv.createMiniProgramLocalDevGrant({ declaredPermissions: currentDevContext.declaredPermissions ?? {},
|
|
@@ -15271,6 +15462,16 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15271
15462
|
launchRuntimePermissions = context.createMobileDevSessionRuntimePermissions(currentDevContext);
|
|
15272
15463
|
refreshDevCsp?.();
|
|
15273
15464
|
};
|
|
15465
|
+
// A3:把限流状态透出给浏览器调试页与宿主页,让手机端停止重连自激循环。
|
|
15466
|
+
const applyRateLimitState = (state) => {
|
|
15467
|
+
currentDevContext = { ...currentDevContext, rateLimit: state };
|
|
15468
|
+
updateLocalContext();
|
|
15469
|
+
browserDevHost.updateBootstrap({ devContext: currentDevContext });
|
|
15470
|
+
if (state)
|
|
15471
|
+
reportRateLimitOnce(state);
|
|
15472
|
+
else
|
|
15473
|
+
lastRateLimitHint = '';
|
|
15474
|
+
};
|
|
15274
15475
|
updateLocalContext();
|
|
15275
15476
|
const readLaunchSource = () => ({
|
|
15276
15477
|
devContext: currentDevContext,
|
|
@@ -15368,14 +15569,25 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15368
15569
|
},
|
|
15369
15570
|
readMobileDevSessionContext: async () => {
|
|
15370
15571
|
if (currentDevContext.source === 'remote') {
|
|
15371
|
-
const refreshed = await
|
|
15372
|
-
|
|
15373
|
-
|
|
15572
|
+
const refreshed = await readDevLaunchContext();
|
|
15573
|
+
if (refreshed.context.rateLimit?.limited) {
|
|
15574
|
+
// 被限流时不再替换上下文,只透出限流状态;手机端据此停止重连。
|
|
15575
|
+
applyRateLimitState(refreshed.context.rateLimit);
|
|
15576
|
+
}
|
|
15577
|
+
else if (refreshed.context.source === 'remote' && refreshed.context.miniProgramId === currentDevContext.miniProgramId) {
|
|
15374
15578
|
if (JSON.stringify(currentDevContext.runtimePermissions) !== JSON.stringify(refreshed.context.runtimePermissions))
|
|
15375
15579
|
contextRevision++;
|
|
15376
15580
|
currentDevContext = withCurrentLocalDevLaunchToken(refreshed.context, currentLocalDevLaunchToken);
|
|
15377
15581
|
updateLocalContext();
|
|
15378
15582
|
browserDevHost.updateBootstrap({ devContext: currentDevContext });
|
|
15583
|
+
hasReportedBindingChange = false;
|
|
15584
|
+
}
|
|
15585
|
+
else if (refreshed.context.source === 'remote' && refreshed.context.miniProgramId !== currentDevContext.miniProgramId) {
|
|
15586
|
+
// 绑定已变更:保留当前上下文不误发,但必须提示重启,避免真机调试一直用旧小程序。
|
|
15587
|
+
if (!hasReportedBindingChange) {
|
|
15588
|
+
hasReportedBindingChange = true;
|
|
15589
|
+
logger.warn('检测到项目绑定已变更,请重新运行 hb-sdk dev 后再扫码调试');
|
|
15590
|
+
}
|
|
15379
15591
|
}
|
|
15380
15592
|
}
|
|
15381
15593
|
return currentDevContext;
|
|
@@ -15401,8 +15613,11 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15401
15613
|
companionDeclared: currentDevContext.declaredPermissions?.companion?.enabled === true && runtimePermissionEnv.hasMiniappDesktopPlatform(currentDevContext.platforms),
|
|
15402
15614
|
miniProgramId: devLaunchContext.miniProgramId,
|
|
15403
15615
|
refreshPermissions: async () => {
|
|
15404
|
-
const refreshed = await
|
|
15405
|
-
|
|
15616
|
+
const refreshed = await readDevLaunchContext();
|
|
15617
|
+
// 限流必须原样抛出,才能走 30s 起、上限 300s 的退避与「请勿反复重启」提示。
|
|
15618
|
+
if (refreshed.context.rateLimit?.limited) {
|
|
15619
|
+
throw index.createCliRateLimitedErrorFromState(refreshed.context.rateLimit);
|
|
15620
|
+
}
|
|
15406
15621
|
if (refreshed.context.miniProgramId !== devLaunchContext.miniProgramId)
|
|
15407
15622
|
throw new Error('项目绑定已变更,请重新启动调试');
|
|
15408
15623
|
if (refreshed.context.source !== 'remote')
|
|
@@ -15428,13 +15643,21 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15428
15643
|
});
|
|
15429
15644
|
},
|
|
15430
15645
|
onReadiness: devReadiness => browserDevHost.updateBootstrap({ devReadiness }),
|
|
15646
|
+
// 主动失效:项目绑定变更或开发者点重试后立即重新请求(key 会带上新绑定,这里清空全部)。
|
|
15647
|
+
onInvalidate: () => devContextCache.invalidate(),
|
|
15648
|
+
// 限流状态与恢复都要透出给调试页与宿主页。
|
|
15649
|
+
onRateLimit: state => applyRateLimitState(state),
|
|
15431
15650
|
projectRoot,
|
|
15432
15651
|
timeoutMs: runtime.devContextTimeoutMs ?? DEFAULT_DEV_CONTEXT_TIMEOUT_MS,
|
|
15433
15652
|
});
|
|
15434
15653
|
closers.push(tokenSession.close);
|
|
15435
15654
|
}
|
|
15436
15655
|
else {
|
|
15437
|
-
|
|
15656
|
+
// 限流与「未登录 / 未绑定」是两回事:前者等窗口过去即可,后者要开发者去操作。
|
|
15657
|
+
// 用限流原因阻塞真机调试,避免把已封禁误报成登录/绑定问题。
|
|
15658
|
+
const reason = devLaunchContext.rateLimit?.limited
|
|
15659
|
+
? `真机调试暂不可用:${index.formatCliRateLimitHint(devLaunchContext.rateLimit)}`
|
|
15660
|
+
: '登录或小程序绑定不可用,请完成 CLI 登录和项目绑定';
|
|
15438
15661
|
browserDevHost.updateBootstrap({
|
|
15439
15662
|
devReadiness: {
|
|
15440
15663
|
browser: { state: 'ready' },
|
|
@@ -15444,11 +15667,35 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
15444
15667
|
});
|
|
15445
15668
|
}
|
|
15446
15669
|
const packagePath = path.join(projectRoot, 'package.json');
|
|
15670
|
+
/**
|
|
15671
|
+
* 上一次生效的声明指纹。
|
|
15672
|
+
*
|
|
15673
|
+
* `watchFile` 是 mtime 轮询、不比较内容,版本号或依赖的普通写入也会触发;不比对就直接
|
|
15674
|
+
* `refresh()` 会清空缓存并立刻打一次远端 `detail`(密集写入可达数十次/分钟)。
|
|
15675
|
+
*/
|
|
15676
|
+
let lastDeclarationFingerprint;
|
|
15677
|
+
const readDeclarationFingerprint = () => JSON.stringify([
|
|
15678
|
+
runtimePermissionEnv.readMiniappPermissionsFromPackageJson(projectRoot, runtimePermissionEnv.resolveMiniappSdkVersion()).permissions ?? null,
|
|
15679
|
+
runtimePermissionEnv.readMiniappPlatformsFromPackageJson(projectRoot),
|
|
15680
|
+
context.readBoundMiniProgramId(projectRoot),
|
|
15681
|
+
]);
|
|
15682
|
+
// 先记录启动时已生效的声明,这样与调试声明无关的写入(版本号、依赖等)不会触发远端刷新。
|
|
15683
|
+
try {
|
|
15684
|
+
lastDeclarationFingerprint = readDeclarationFingerprint();
|
|
15685
|
+
}
|
|
15686
|
+
catch {
|
|
15687
|
+
// 读不出来就交给下面的 onDeclarationChange 走异常分支。
|
|
15688
|
+
}
|
|
15447
15689
|
const onDeclarationChange = () => {
|
|
15448
15690
|
try {
|
|
15449
15691
|
const previouslyTemporary = new Set(currentDevContext.localDevGrant?.entries.map(entry => entry.key));
|
|
15450
15692
|
const local = runtimePermissionEnv.readMiniappPermissionsFromPackageJson(projectRoot, runtimePermissionEnv.resolveMiniappSdkVersion());
|
|
15451
15693
|
const platforms = runtimePermissionEnv.readMiniappPlatformsFromPackageJson(projectRoot);
|
|
15694
|
+
// 与调试声明无关的写入(版本号、依赖等)不触发远端刷新。
|
|
15695
|
+
const fingerprint = JSON.stringify([local.permissions ?? null, platforms, context.readBoundMiniProgramId(projectRoot)]);
|
|
15696
|
+
if (fingerprint === lastDeclarationFingerprint)
|
|
15697
|
+
return;
|
|
15698
|
+
lastDeclarationFingerprint = fingerprint;
|
|
15452
15699
|
contextRevision++;
|
|
15453
15700
|
currentDevContext = { ...currentDevContext, declaredPermissions: local.permissions ?? {}, platforms,
|
|
15454
15701
|
runtimePermissions: runtimePermissionEnv.composeMiniappRuntimePermissions(local, currentDevContext.runtimePermissions).runtimePermissions };
|
|
@@ -15555,9 +15802,33 @@ async function loadDevLaunchContext(options) {
|
|
|
15555
15802
|
throw new Error(`版本资料配置失败:${index.readRedactedErrorMessage(error)}。请配置 heybox.name/icon/coverImages 后重试。`, { cause: error });
|
|
15556
15803
|
if (error instanceof context.MiniProgramProjectBindingError && error.code.startsWith('PACKAGE_JSON_'))
|
|
15557
15804
|
throw error;
|
|
15805
|
+
// A3:限流要作为结构化状态继续透出;不能和其它错误一样只报「未连接线上上下文」。
|
|
15806
|
+
const rateLimitState = index.readCliRateLimitState(error);
|
|
15807
|
+
if (rateLimitState) {
|
|
15808
|
+
return {
|
|
15809
|
+
context: {
|
|
15810
|
+
...anonymous(index.formatCliRateLimitHint(rateLimitState)).context,
|
|
15811
|
+
rateLimit: rateLimitState,
|
|
15812
|
+
},
|
|
15813
|
+
miniProgram: null,
|
|
15814
|
+
};
|
|
15815
|
+
}
|
|
15558
15816
|
return anonymous('未连接线上上下文,请检查 CLI 登录态、项目绑定和网络');
|
|
15559
15817
|
}
|
|
15560
15818
|
}
|
|
15819
|
+
/**
|
|
15820
|
+
* 输出限流提示并强提示升级。
|
|
15821
|
+
*
|
|
15822
|
+
* 老版本 CLI 无法被强制升级,只能在此明确提示「请勿反复重启」并引导更新。
|
|
15823
|
+
*/
|
|
15824
|
+
function reportDevContextRateLimit(logger, state, env) {
|
|
15825
|
+
void index.printRateLimitUpgradeHint({
|
|
15826
|
+
env,
|
|
15827
|
+
logger,
|
|
15828
|
+
...(state.retryAfterMs === undefined ? {} : { retryAfterMs: state.retryAfterMs }),
|
|
15829
|
+
...(state.message ? { gatewayMessage: state.message } : {}),
|
|
15830
|
+
}).catch(() => undefined);
|
|
15831
|
+
}
|
|
15561
15832
|
function createMiniProgramSummary(miniProgramId, detail) {
|
|
15562
15833
|
const id = typeof detail.mini_program_id === 'string' && detail.mini_program_id.trim() ? detail.mini_program_id.trim() : miniProgramId;
|
|
15563
15834
|
return {
|
|
@@ -15828,6 +16099,7 @@ function startLocalDevLaunchTokenSession(options) {
|
|
|
15828
16099
|
let ticket;
|
|
15829
16100
|
let pending;
|
|
15830
16101
|
let refreshing = false;
|
|
16102
|
+
let consecutiveFailures = 0;
|
|
15831
16103
|
const getTicket = async (companionManifestSha256) => {
|
|
15832
16104
|
if (closed)
|
|
15833
16105
|
return undefined;
|
|
@@ -15856,8 +16128,9 @@ function startLocalDevLaunchTokenSession(options) {
|
|
|
15856
16128
|
refreshing = true;
|
|
15857
16129
|
try {
|
|
15858
16130
|
if (options.refreshPermissions && Date.now() >= permissionsRefreshAt) {
|
|
15859
|
-
|
|
16131
|
+
// A-3:无论成败都推进,否则权限刷新失败后每一轮重试都会再打一次远端 detail。
|
|
15860
16132
|
permissionsRefreshAt = Date.now() + 30_000;
|
|
16133
|
+
companionDeclared = await options.refreshPermissions();
|
|
15861
16134
|
}
|
|
15862
16135
|
let manifest;
|
|
15863
16136
|
let snapshotError;
|
|
@@ -15902,18 +16175,35 @@ function startLocalDevLaunchTokenSession(options) {
|
|
|
15902
16175
|
hasReportedTokenFailure = false;
|
|
15903
16176
|
options.logger.success('本地调试凭证已恢复');
|
|
15904
16177
|
}
|
|
16178
|
+
if (consecutiveFailures > 0) {
|
|
16179
|
+
consecutiveFailures = 0;
|
|
16180
|
+
options.onRateLimit?.(null);
|
|
16181
|
+
}
|
|
15905
16182
|
}
|
|
15906
16183
|
catch (error) {
|
|
15907
16184
|
if (closed)
|
|
15908
16185
|
return;
|
|
15909
|
-
|
|
16186
|
+
// A2 + A3:限流类错误走 30s 起、上限 300s 的退避,并明确提示不要反复重启。
|
|
16187
|
+
const rateLimitState = index.readCliRateLimitState(error);
|
|
16188
|
+
consecutiveFailures += 1;
|
|
16189
|
+
if (rateLimitState) {
|
|
16190
|
+
// 限流提示统一由 onRateLimit 出口负责(runDevCommand 走 reportRateLimitOnce,
|
|
16191
|
+
// 保证同一文案只输出一次);这里不再自己 warn,避免同一次限流打印两行。
|
|
16192
|
+
options.onRateLimit?.(rateLimitState);
|
|
16193
|
+
}
|
|
16194
|
+
else if (!hasReportedTokenFailure) {
|
|
15910
16195
|
options.logger.warn('本地调试凭证获取失败,将自动重试;Web / Browser Fake 仍可使用');
|
|
15911
16196
|
}
|
|
15912
16197
|
hasReportedTokenFailure = true;
|
|
15913
|
-
options.onReadiness({ browser: { state: 'ready' },
|
|
16198
|
+
options.onReadiness({ browser: { state: 'ready' },
|
|
16199
|
+
mobile: { state: 'blocked', reason: rateLimitState ? index.formatCliRateLimitHint(rateLimitState) : '调试凭证暂不可用' },
|
|
15914
16200
|
companion: { state: 'blocked', reason: safeCompanionFailureReason(error) } });
|
|
15915
16201
|
options.logger.debug(`本地调试凭证获取失败,详细原因:${index.readRedactedErrorMessage(error, { verbose: true })}`);
|
|
15916
|
-
schedule(
|
|
16202
|
+
schedule(computeDevContextBackoffDelayMs({
|
|
16203
|
+
attempt: consecutiveFailures - 1,
|
|
16204
|
+
env: options.env,
|
|
16205
|
+
rateLimited: rateLimitState !== null,
|
|
16206
|
+
}));
|
|
15917
16207
|
}
|
|
15918
16208
|
finally {
|
|
15919
16209
|
refreshing = false;
|
|
@@ -15943,6 +16233,8 @@ function startLocalDevLaunchTokenSession(options) {
|
|
|
15943
16233
|
return {
|
|
15944
16234
|
getTicket,
|
|
15945
16235
|
refresh: () => {
|
|
16236
|
+
// 项目绑定变更或开发者主动重试:主动失效 Dev Context 缓存后立即重新请求。
|
|
16237
|
+
options.onInvalidate?.();
|
|
15946
16238
|
permissionsRefreshAt = 0;
|
|
15947
16239
|
publishedDigest = undefined;
|
|
15948
16240
|
if (refreshTimer)
|
|
@@ -16194,8 +16486,12 @@ function isPrivateIPv4(address) {
|
|
|
16194
16486
|
|
|
16195
16487
|
var dev = /*#__PURE__*/Object.freeze({
|
|
16196
16488
|
__proto__: null,
|
|
16489
|
+
computeDevContextBackoffDelayMs: computeDevContextBackoffDelayMs,
|
|
16490
|
+
createDevContextCache: createDevContextCache,
|
|
16197
16491
|
createMiniProgramDevLaunchVitePlugin: createMiniProgramDevLaunchVitePlugin,
|
|
16198
16492
|
normalizeExpiresAt: normalizeExpiresAt,
|
|
16493
|
+
resolveDevContextBackoffLimits: resolveDevContextBackoffLimits,
|
|
16494
|
+
resolveDevContextCacheTtlMs: resolveDevContextCacheTtlMs,
|
|
16199
16495
|
runDevCommand: runDevCommand,
|
|
16200
16496
|
startLocalDevLaunchTokenSession: startLocalDevLaunchTokenSession
|
|
16201
16497
|
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index$2 = require('./index-
|
|
3
|
+
var index$2 = require('./index-Brq_-WV3.cjs');
|
|
4
4
|
var require$$0$3 = require('fs');
|
|
5
5
|
var require$$0$2 = require('crypto');
|
|
6
6
|
var require$$1$2 = require('path');
|
|
7
7
|
var require$$0$5 = require('assert');
|
|
8
8
|
var require$$0$4 = require('events');
|
|
9
9
|
var require$$1$1 = require('util');
|
|
10
|
-
var runtimePermissionEnv = require('./runtime-permission-env-
|
|
10
|
+
var runtimePermissionEnv = require('./runtime-permission-env-Bs_JqpTM.cjs');
|
|
11
11
|
var require$$0$7 = require('net');
|
|
12
12
|
var require$$0$6 = require('url');
|
|
13
13
|
var require$$2$1 = require('http');
|