@heybox/hb-sdk 0.6.5 → 0.6.6-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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-CKat0ExC.cjs');
7
+ var index = require('./index-gP0K2xx1.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-CKat0ExC.cjs');
3
+ var index$2 = require('./index-gP0K2xx1.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-DjepdCaa.cjs');
10
+ var context$1 = require('./context-D-cb_pNY.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-CKat0ExC.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-gP0K2xx1.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-CKat0ExC.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-gP0K2xx1.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-CKat0ExC.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-gP0K2xx1.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-CKat0ExC.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-gP0K2xx1.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-CKat0ExC.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-gP0K2xx1.cjs', document.baseURI).href)));
250
250
  function __require() { return require$1("node:process"); }
251
251
 
252
252
  var help = {};
@@ -13347,7 +13347,7 @@ function getPathname(pathWithQuery) {
13347
13347
  }
13348
13348
 
13349
13349
  const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
13350
- const BUILT_CLI_VERSION = '0.6.5';
13350
+ const BUILT_CLI_VERSION = '0.6.6-alpha.1';
13351
13351
  const PACKAGE_JSON_CANDIDATES = [
13352
13352
  path.resolve(__dirname, '..', '..', 'package.json'),
13353
13353
  path.resolve(__dirname, '..', 'package.json'),
@@ -13668,31 +13668,31 @@ function createCommandLoggerResolver(options) {
13668
13668
  };
13669
13669
  }
13670
13670
  const defaultClearLoginStatus = async (...args) => {
13671
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-B6gERpSX.cjs'); });
13671
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-BFIcNgmi.cjs'); });
13672
13672
  return clearLoginStatus(...args);
13673
13673
  };
13674
13674
  const defaultLoginToHeybox = async (...args) => {
13675
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-B6gERpSX.cjs'); });
13675
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-BFIcNgmi.cjs'); });
13676
13676
  return loginToHeybox(...args);
13677
13677
  };
13678
13678
  const defaultPrintLoginStatus = async (...args) => {
13679
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-B6gERpSX.cjs'); });
13679
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-BFIcNgmi.cjs'); });
13680
13680
  return printLoginStatus(...args);
13681
13681
  };
13682
13682
  const defaultRunCreateCommand = async (...args) => {
13683
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-D3BBKay9.cjs'); });
13683
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-DlU4nWz_.cjs'); });
13684
13684
  return runCreateCommand(...args);
13685
13685
  };
13686
13686
  const defaultRunDevCommand = async (...args) => {
13687
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-C3u5FXIy.cjs'); });
13687
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-Bb4U965a.cjs'); });
13688
13688
  return runDevCommand(...args);
13689
13689
  };
13690
13690
  const defaultRunDoctorCommand = async (...args) => {
13691
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DEgZa2qC.cjs'); });
13691
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DwDqOLdV.cjs'); });
13692
13692
  return runDoctorCommand(...args);
13693
13693
  };
13694
13694
  const defaultRunRemoteCommand = async (...args) => {
13695
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-BfQiZzeJ.cjs'); });
13695
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-YESvKni6.cjs'); });
13696
13696
  return runRemoteCommand(...args);
13697
13697
  };
13698
13698
  function resolveStandaloneLogger(options, verbose) {
@@ -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-DPEq__gB.cjs');
6
+ var session = require('./session-BRwveiW8.cjs');
7
7
  var browser = require('./browser-RAy8e8cV.cjs');
8
- var index = require('./index-CKat0ExC.cjs');
8
+ var index = require('./index-gP0K2xx1.cjs');
9
9
  require('node:path');
10
10
  require('fs');
11
11
  require('constants');
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var promises = require('node:readline/promises');
4
- var index = require('./index-CKat0ExC.cjs');
5
- var session = require('./session-DPEq__gB.cjs');
4
+ var index = require('./index-gP0K2xx1.cjs');
5
+ var session = require('./session-BRwveiW8.cjs');
6
6
  var childProcess = require('node:child_process');
7
7
  var fs = require('node:fs');
8
8
  var fs$1 = require('node:fs/promises');
9
9
  var path = require('node:path');
10
- var context = require('./context-DjepdCaa.cjs');
10
+ var context = require('./context-D-cb_pNY.cjs');
11
11
  require('node:module');
12
12
  require('path');
13
13
  require('os');
@@ -264,7 +264,7 @@ async function createDefaultCosClient(uploadToken) {
264
264
  };
265
265
  }
266
266
  async function loadCosConstructor() {
267
- const cosModule = await Promise.resolve().then(function () { return require('./index-B5gEl9ow.cjs'); }).then(function (n) { return n.index; });
267
+ const cosModule = await Promise.resolve().then(function () { return require('./index-B6gnwx39.cjs'); }).then(function (n) { return n.index; });
268
268
  return cosModule.default;
269
269
  }
270
270
  function formatSize(bytes) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-CKat0ExC.cjs');
3
+ var index = require('./index-gP0K2xx1.cjs');
4
4
  var node_crypto = require('node:crypto');
5
5
  var path = require('node:path');
6
6
  var require$$0$2 = require('fs');
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./cli-chunks/index-CKat0ExC.cjs');
3
+ var index = require('./cli-chunks/index-gP0K2xx1.cjs');
4
4
  require('node:module');
5
5
  require('node:fs');
6
6
  require('node:fs/promises');
@@ -384,6 +384,7 @@
384
384
  <div class="actions" style="margin-top: 10px">
385
385
  <button id="reset-permissions-button" type="button">恢复初始权限</button>
386
386
  </div>
387
+ <div class="mac-app-status" id="permission-persistence-status"></div>
387
388
  <ul class="release-diagnostics" id="release-diagnostics"></ul>
388
389
  </section>
389
390
 
@@ -3427,6 +3427,11 @@ function requireBrowser () {
3427
3427
 
3428
3428
  var browserExports = requireBrowser();
3429
3429
 
3430
+ /** Dev Shell 读取局域网 Dev Session endpoint 的 query 参数。 */
3431
+ const MINI_PROGRAM_DEV_CONTEXT_QUERY_PARAM = 'dev_context_url';
3432
+ /** Mock Host 创建和读取 Dev Session 的固定路径。 */
3433
+ const MINI_PROGRAM_DEV_CONTEXT_PATH = '/__hb_sdk__/dev-context';
3434
+
3430
3435
  function createCSPViolationPanel(container) {
3431
3436
  const seen = new Set();
3432
3437
  const list = document.createElement('ol');
@@ -4102,57 +4107,14 @@ function assertNetworkAllowedKeys(payload) {
4102
4107
  }
4103
4108
  function readNetworkRequestUrl(value) {
4104
4109
  const requestUrl = readMiniProgramRuntimeHttpUrl(value, 'network.request url 必须是 HTTP(S) URL');
4105
- assertPublicNetworkRequestUrl(requestUrl);
4110
+ assertNetworkRequestUrl(requestUrl);
4106
4111
  return requestUrl;
4107
4112
  }
4108
- function assertPublicNetworkRequestUrl(requestUrl) {
4113
+ function assertNetworkRequestUrl(requestUrl) {
4109
4114
  const url = new URL(requestUrl);
4110
4115
  if (url.username || url.password) {
4111
4116
  throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request url 不允许包含用户信息');
4112
4117
  }
4113
- if (isUnsafeNetworkHost(url.hostname)) {
4114
- throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'network.request url 不允许指向本机、内网或保留地址');
4115
- }
4116
- }
4117
- function isUnsafeNetworkHost(hostname) {
4118
- const normalizedHost = hostname.toLowerCase();
4119
- const ipv6Host = normalizedHost.startsWith('[') && normalizedHost.endsWith(']')
4120
- ? normalizedHost.slice(1, -1)
4121
- : normalizedHost;
4122
- if (normalizedHost === 'localhost' ||
4123
- normalizedHost.endsWith('.localhost') ||
4124
- normalizedHost.endsWith('.local') ||
4125
- normalizedHost === 'metadata.google.internal') {
4126
- return true;
4127
- }
4128
- if (isUnsafeIPv4Host(normalizedHost)) {
4129
- return true;
4130
- }
4131
- return isUnsafeIPv6Host(ipv6Host);
4132
- }
4133
- function isUnsafeIPv4Host(hostname) {
4134
- if (!/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
4135
- return false;
4136
- }
4137
- const parts = hostname.split('.').map(part => Number(part));
4138
- if (parts.some(part => !Number.isInteger(part) || part < 0 || part > 255)) {
4139
- return true;
4140
- }
4141
- const [a, b] = parts;
4142
- return (a === 0 ||
4143
- a === 10 ||
4144
- a === 127 ||
4145
- (a === 100 && b >= 64 && b <= 127) ||
4146
- (a === 169 && b === 254) ||
4147
- (a === 172 && b >= 16 && b <= 31) ||
4148
- (a === 192 && b === 168));
4149
- }
4150
- function isUnsafeIPv6Host(hostname) {
4151
- return (hostname === '::' ||
4152
- hostname === '::1' ||
4153
- hostname.startsWith('fc') ||
4154
- hostname.startsWith('fd') ||
4155
- hostname.startsWith('fe80:'));
4156
4118
  }
4157
4119
  function readNetworkRequestHeaders(value) {
4158
4120
  const headers = readStringRecord(value, 'network.request headers 必须是 Record<string, string>');
@@ -6385,6 +6347,7 @@ function isPlainRecord(value) {
6385
6347
 
6386
6348
  const NETWORK_PROXY_PATH = '/__hb_sdk_mock_network__';
6387
6349
  const MOCK_HOST_BOOTSTRAP_PATH = '/__hb_sdk_bootstrap__';
6350
+ const DEV_PERMISSIONS_PATH = '/__hb_sdk__/dev-permissions';
6388
6351
  const RUNTIME_GATE_PROBE_METHOD = 'runtime.gate.probe';
6389
6352
  const params = new URL(location.href).searchParams;
6390
6353
  const miniUrl = params.get('mini_url');
@@ -6397,6 +6360,9 @@ const storage = new Map();
6397
6360
  const logs = [];
6398
6361
  let handshaken = false;
6399
6362
  let navigationBarStyle = 'dark';
6363
+ let mobileQrGeneration = 0;
6364
+ let mobileQrRefreshTimer;
6365
+ let mobileDevSessionCreation = Promise.resolve();
6400
6366
  let currentUser = {
6401
6367
  heybox_id: 'debug_user',
6402
6368
  nickname: 'PC Debug User',
@@ -6419,6 +6385,7 @@ const elements = {
6419
6385
  mobileQrStatus: queryElement('#mobile-qr-status'),
6420
6386
  nicknameInput: queryElement('#nickname-input'),
6421
6387
  networkPermissionSelect: queryElement('#network-permission-select'),
6388
+ permissionPersistenceStatus: queryElement('#permission-persistence-status'),
6422
6389
  releaseDiagnostics: queryElement('#release-diagnostics'),
6423
6390
  resetPermissionsButton: queryElement('#reset-permissions-button'),
6424
6391
  storageSnapshot: queryElement('#storage-snapshot'),
@@ -6431,9 +6398,12 @@ if (!miniUrl) {
6431
6398
  }
6432
6399
  const miniProgramUrl = miniUrl;
6433
6400
  const bootstrap = await loadMockHostBootstrap();
6434
- const devContext = bootstrap.devContext;
6435
- const initialPermissionState = createMiniProgramMockPermissionState(devContext);
6436
- let permissionState = clonePermissionState(initialPermissionState);
6401
+ let devContext = bootstrap.devContext;
6402
+ let remotePermissionState = createMiniProgramMockPermissionState(devContext);
6403
+ let permissionState = clonePermissionState(remotePermissionState);
6404
+ let hasPermissionOverride = false;
6405
+ let permissionActionMessage = '';
6406
+ await loadPersistedPermissionConfiguration();
6437
6407
  const iframe = document.createElement('iframe');
6438
6408
  iframe.src = appendNonce(miniProgramUrl, nonce);
6439
6409
  iframe.allow = 'clipboard-read; clipboard-write';
@@ -6468,6 +6438,7 @@ updateStorageSnapshot();
6468
6438
  updatePermissionControls();
6469
6439
  window.addEventListener('message', handleMessage);
6470
6440
  window.addEventListener('beforeunload', () => {
6441
+ clearMobileQrRefreshTimer();
6471
6442
  postEvent('unload', { timestamp: Date.now() });
6472
6443
  });
6473
6444
  queryElement('#login-button').addEventListener('click', () => {
@@ -6494,13 +6465,10 @@ elements.mobileLanSelect.addEventListener('change', () => {
6494
6465
  void updateMobileQrCode();
6495
6466
  });
6496
6467
  elements.networkPermissionSelect.addEventListener('change', () => {
6497
- permissionState.networkRequest.status =
6498
- elements.networkPermissionSelect.value === 'enabled' ? 'enabled' : 'disabled';
6499
- rebuildRuntimeWithPermissions();
6468
+ void savePermissionOverride(elements.networkPermissionSelect.value === 'enabled' ? 'enabled' : 'disabled');
6500
6469
  });
6501
6470
  elements.resetPermissionsButton.addEventListener('click', () => {
6502
- permissionState = clonePermissionState(initialPermissionState);
6503
- rebuildRuntimeWithPermissions();
6471
+ void resetPermissionOverride();
6504
6472
  });
6505
6473
  const mobileAppQrReady = setupMobileAppQr();
6506
6474
  function createRuntime() {
@@ -6515,14 +6483,149 @@ function rebuildRuntimeWithPermissions() {
6515
6483
  }
6516
6484
  function updatePermissionControls() {
6517
6485
  elements.devContextStatus.textContent =
6518
- devContext.source === 'remote'
6519
- ? `已连接线上配置${devContext.miniProgramId ? ` · ${devContext.miniProgramId}` : ''}`
6520
- : '匿名本地沙箱';
6486
+ devContext.source === 'remote' ? `已连接线上配置${devContext.miniProgramId ? ` · ${devContext.miniProgramId}` : ''}` : '匿名本地沙箱';
6521
6487
  elements.networkPermissionSelect.value = permissionState.networkRequest.status;
6488
+ const remoteLabel = readPermissionStatusLabel(remotePermissionState.networkRequest.status);
6489
+ const localLabel = readPermissionStatusLabel(permissionState.networkRequest.status);
6490
+ const sourceDescription = hasPermissionOverride
6491
+ ? `远端基线:${remoteLabel} · 本地覆盖:${localLabel}`
6492
+ : `${devContext.source === 'remote' ? '当前使用远端权限' : '当前使用匿名默认权限'}:${remoteLabel}`;
6493
+ elements.permissionPersistenceStatus.textContent = permissionActionMessage
6494
+ ? `${sourceDescription} · ${permissionActionMessage}`
6495
+ : sourceDescription;
6522
6496
  const diagnostics = createMiniProgramDevReleaseDiagnostics(devContext, permissionState);
6523
- elements.releaseDiagnostics.innerHTML = diagnostics
6524
- .map((diagnostic) => `<li>${escapeHtml(diagnostic.message)}</li>`)
6525
- .join('');
6497
+ elements.releaseDiagnostics.innerHTML = diagnostics.map((diagnostic) => `<li>${escapeHtml(diagnostic.message)}</li>`).join('');
6498
+ }
6499
+ async function loadPersistedPermissionConfiguration() {
6500
+ try {
6501
+ const response = await fetch(DEV_PERMISSIONS_PATH, { cache: 'no-store' });
6502
+ const payload = await response.json();
6503
+ const configuration = readPermissionConfiguration(payload);
6504
+ if (!response.ok || !configuration) {
6505
+ throw new Error('权限持久化配置加载失败');
6506
+ }
6507
+ applyPermissionConfiguration(configuration);
6508
+ }
6509
+ catch {
6510
+ permissionActionMessage = '权限持久化暂不可用,刷新或重启后可能丢失本页修改。';
6511
+ }
6512
+ }
6513
+ async function savePermissionOverride(status) {
6514
+ elements.networkPermissionSelect.disabled = true;
6515
+ elements.resetPermissionsButton.disabled = true;
6516
+ permissionState = {
6517
+ networkRequest: {
6518
+ ...permissionState.networkRequest,
6519
+ status,
6520
+ },
6521
+ };
6522
+ hasPermissionOverride = true;
6523
+ permissionActionMessage = '正在保存本地权限覆盖...';
6524
+ rebuildRuntimeWithPermissions();
6525
+ void updateMobileQrCode();
6526
+ try {
6527
+ const response = await fetch(DEV_PERMISSIONS_PATH, {
6528
+ body: JSON.stringify({
6529
+ runtime_permissions: createMiniProgramMockRuntimePermissions(permissionState),
6530
+ }),
6531
+ headers: { 'content-type': 'application/json' },
6532
+ method: 'PUT',
6533
+ });
6534
+ const payload = await response.json();
6535
+ const configuration = readPermissionConfiguration(payload);
6536
+ if (!response.ok || !configuration) {
6537
+ throw new Error(readResponseMessage(payload) ?? '保存失败');
6538
+ }
6539
+ applyPermissionConfiguration(configuration, configuration.persistenceError || '本地权限覆盖已保存。');
6540
+ rebuildRuntimeWithPermissions();
6541
+ }
6542
+ catch (error) {
6543
+ permissionActionMessage = `${readErrorText(error)},当前页面仍会应用该权限,但刷新或重启后会丢失。`;
6544
+ updatePermissionControls();
6545
+ }
6546
+ finally {
6547
+ elements.networkPermissionSelect.disabled = false;
6548
+ elements.resetPermissionsButton.disabled = false;
6549
+ }
6550
+ }
6551
+ async function resetPermissionOverride() {
6552
+ elements.networkPermissionSelect.disabled = true;
6553
+ elements.resetPermissionsButton.disabled = true;
6554
+ try {
6555
+ const response = await fetch(DEV_PERMISSIONS_PATH, {
6556
+ method: 'DELETE',
6557
+ });
6558
+ const payload = await response.json();
6559
+ const configuration = readPermissionConfiguration(payload);
6560
+ if (!response.ok || !configuration) {
6561
+ throw new Error(readResponseMessage(payload) ?? '重置失败');
6562
+ }
6563
+ else {
6564
+ applyPermissionConfiguration(configuration, configuration.source === 'remote' ? '已重新读取远端权限并清除本地覆盖。' : '已清除本地权限覆盖。');
6565
+ }
6566
+ rebuildRuntimeWithPermissions();
6567
+ void updateMobileQrCode();
6568
+ }
6569
+ catch (error) {
6570
+ permissionActionMessage = `重置失败:${readErrorText(error)}`;
6571
+ updatePermissionControls();
6572
+ }
6573
+ finally {
6574
+ elements.networkPermissionSelect.disabled = false;
6575
+ elements.resetPermissionsButton.disabled = false;
6576
+ }
6577
+ }
6578
+ function readPermissionConfiguration(value) {
6579
+ if (!isRecord(value) || (value.source !== 'anonymous' && value.source !== 'remote')) {
6580
+ return undefined;
6581
+ }
6582
+ const remotePermissions = value.remote_permissions;
6583
+ const remoteParsed = parseMiniProgramRuntimePermissions(remotePermissions);
6584
+ const overridePermissions = value.override_permissions;
6585
+ const overrideParsed = parseMiniProgramRuntimePermissions(overridePermissions);
6586
+ if (remotePermissions !== undefined && !remoteParsed.valid) {
6587
+ return undefined;
6588
+ }
6589
+ if (overridePermissions !== undefined && !overrideParsed.valid) {
6590
+ return undefined;
6591
+ }
6592
+ const source = value.source;
6593
+ const fallbackContext = { };
6594
+ return {
6595
+ source,
6596
+ miniProgramId: typeof value.mini_program_id === 'string' ? value.mini_program_id : undefined,
6597
+ remotePermissions,
6598
+ remoteState: createMiniProgramMockPermissionState(remotePermissions === undefined ? fallbackContext : { runtimePermissions: remotePermissions }),
6599
+ ...(overridePermissions === undefined
6600
+ ? {}
6601
+ : {
6602
+ overrideState: createMiniProgramMockPermissionState({ runtimePermissions: overridePermissions }),
6603
+ }),
6604
+ persistenceError: typeof value.persistence_error === 'string' ? value.persistence_error : undefined,
6605
+ };
6606
+ }
6607
+ function applyPermissionConfiguration(configuration, message) {
6608
+ devContext =
6609
+ configuration.source === 'remote'
6610
+ ? {
6611
+ source: 'remote',
6612
+ miniProgramId: configuration.miniProgramId,
6613
+ runtimePermissions: configuration.remotePermissions,
6614
+ }
6615
+ : { source: 'anonymous', warning: devContext.warning };
6616
+ remotePermissionState = clonePermissionState(configuration.remoteState);
6617
+ permissionState = clonePermissionState(configuration.overrideState ?? configuration.remoteState);
6618
+ hasPermissionOverride = Boolean(configuration.overrideState);
6619
+ permissionActionMessage = message ?? configuration.persistenceError ?? '';
6620
+ }
6621
+ function readPermissionStatusLabel(status) {
6622
+ return status === 'enabled' ? '允许' : '拒绝';
6623
+ }
6624
+ function readResponseMessage(value) {
6625
+ return isRecord(value) && typeof value.message === 'string' ? value.message : undefined;
6626
+ }
6627
+ function readErrorText(error) {
6628
+ return error instanceof Error && error.message ? error.message : '操作失败';
6526
6629
  }
6527
6630
  function clonePermissionState(state) {
6528
6631
  return {
@@ -6754,9 +6857,7 @@ async function loadMockHostBootstrap() {
6754
6857
  devContext: readDevContext(payload.devContext, payload.runtimePermissions),
6755
6858
  lanAddresses: Array.isArray(payload.lanAddresses) ? payload.lanAddresses.filter(isLanAddress) : [],
6756
6859
  macAppProtocol: typeof payload.macAppProtocol === 'string' ? payload.macAppProtocol : undefined,
6757
- nativeAppLaunchUnavailableReason: typeof payload.nativeAppLaunchUnavailableReason === 'string'
6758
- ? payload.nativeAppLaunchUnavailableReason
6759
- : undefined,
6860
+ nativeAppLaunchUnavailableReason: typeof payload.nativeAppLaunchUnavailableReason === 'string' ? payload.nativeAppLaunchUnavailableReason : undefined,
6760
6861
  runtimePermissions: payload.runtimePermissions,
6761
6862
  };
6762
6863
  }
@@ -6805,6 +6906,8 @@ function setupMobileLanSelect() {
6805
6906
  elements.mobileLanSelect.disabled = !hasLanAddress;
6806
6907
  }
6807
6908
  async function updateMobileQrCode() {
6909
+ const generation = ++mobileQrGeneration;
6910
+ clearMobileQrRefreshTimer();
6808
6911
  if (nativeAppLaunchUnavailableReason) {
6809
6912
  elements.mobileQrImage.removeAttribute('src');
6810
6913
  elements.mobileQrImage.hidden = true;
@@ -6818,8 +6921,8 @@ async function updateMobileQrCode() {
6818
6921
  elements.mobileQrStatus.textContent = '';
6819
6922
  return;
6820
6923
  }
6821
- const payload = selected.mobileAppQrPayload;
6822
- if (!payload) {
6924
+ const basePayload = selected.mobileAppQrPayload;
6925
+ if (!basePayload) {
6823
6926
  elements.mobileQrImage.removeAttribute('src');
6824
6927
  elements.mobileQrImage.hidden = true;
6825
6928
  elements.mobileQrStatus.textContent = '真机调试配置不可用,请重启 hb-sdk dev 后重试。';
@@ -6827,20 +6930,112 @@ async function updateMobileQrCode() {
6827
6930
  }
6828
6931
  elements.mobileQrStatus.textContent = '正在生成二维码...';
6829
6932
  try {
6830
- elements.mobileQrImage.src = await browserExports.toDataURL(payload, {
6933
+ const devSession = await createMobileDevSession(selected);
6934
+ if (generation !== mobileQrGeneration) {
6935
+ return;
6936
+ }
6937
+ const payload = applyDevContextToMobileQrPayload(basePayload, devSession.url);
6938
+ const imageUrl = await browserExports.toDataURL(payload, {
6831
6939
  errorCorrectionLevel: 'M',
6832
6940
  margin: 1,
6833
6941
  width: 176,
6834
6942
  });
6943
+ if (generation !== mobileQrGeneration) {
6944
+ return;
6945
+ }
6946
+ elements.mobileQrImage.src = imageUrl;
6835
6947
  elements.mobileQrImage.hidden = false;
6836
6948
  elements.mobileQrStatus.textContent = '';
6949
+ scheduleMobileQrRefresh(devSession.expiresAt, generation);
6837
6950
  }
6838
6951
  catch {
6952
+ if (generation !== mobileQrGeneration) {
6953
+ return;
6954
+ }
6839
6955
  elements.mobileQrImage.removeAttribute('src');
6840
6956
  elements.mobileQrImage.hidden = true;
6841
6957
  elements.mobileQrStatus.textContent = '二维码生成失败';
6842
6958
  }
6843
6959
  }
6960
+ async function createMobileDevSession(selected) {
6961
+ const creation = mobileDevSessionCreation.then(() => requestMobileDevSession(selected));
6962
+ mobileDevSessionCreation = creation.then(() => undefined, () => undefined);
6963
+ return creation;
6964
+ }
6965
+ async function requestMobileDevSession(selected) {
6966
+ const miniUrl = new URL(selected.appUrl);
6967
+ const response = await fetch(MINI_PROGRAM_DEV_CONTEXT_PATH, {
6968
+ body: JSON.stringify({
6969
+ mini_url_origin: miniUrl.origin,
6970
+ runtime_permissions: createMiniProgramMockRuntimePermissions({
6971
+ ...permissionState,
6972
+ networkRequest: {
6973
+ ...permissionState.networkRequest,
6974
+ useOfficialDomain: false,
6975
+ },
6976
+ }),
6977
+ }),
6978
+ headers: { 'content-type': 'application/json' },
6979
+ method: 'POST',
6980
+ });
6981
+ if (!response.ok) {
6982
+ throw new Error('Failed to create mobile Dev Session');
6983
+ }
6984
+ const result = await response.json();
6985
+ if (!isRecord(result) ||
6986
+ typeof result.token !== 'string' ||
6987
+ !/^[a-f0-9]{64}$/.test(result.token) ||
6988
+ typeof result.expires_at !== 'number' ||
6989
+ !Number.isFinite(result.expires_at) ||
6990
+ result.expires_at <= Date.now()) {
6991
+ throw new Error('Invalid mobile Dev Session response');
6992
+ }
6993
+ const devContextUrl = new URL(`${MINI_PROGRAM_DEV_CONTEXT_PATH}/${result.token}`, location.origin);
6994
+ devContextUrl.hostname = miniUrl.hostname;
6995
+ return {
6996
+ expiresAt: result.expires_at,
6997
+ url: devContextUrl.toString(),
6998
+ };
6999
+ }
7000
+ function scheduleMobileQrRefresh(expiresAt, generation) {
7001
+ mobileQrRefreshTimer = window.setTimeout(() => {
7002
+ if (generation !== mobileQrGeneration) {
7003
+ return;
7004
+ }
7005
+ elements.mobileQrImage.removeAttribute('src');
7006
+ elements.mobileQrImage.hidden = true;
7007
+ elements.mobileQrStatus.textContent = '二维码已过期,正在重新生成...';
7008
+ void updateMobileQrCode();
7009
+ }, Math.max(0, expiresAt - Date.now()));
7010
+ }
7011
+ function clearMobileQrRefreshTimer() {
7012
+ if (mobileQrRefreshTimer === undefined) {
7013
+ return;
7014
+ }
7015
+ window.clearTimeout(mobileQrRefreshTimer);
7016
+ mobileQrRefreshTimer = undefined;
7017
+ }
7018
+ function applyDevContextToMobileQrPayload(payload, devContextUrl) {
7019
+ const protocolMarker = '#heybox://';
7020
+ const protocolIndex = payload.indexOf(protocolMarker);
7021
+ if (protocolIndex < 0) {
7022
+ throw new Error('Invalid mobile App QR payload');
7023
+ }
7024
+ const encodedPayload = payload.slice(protocolIndex + protocolMarker.length);
7025
+ const openWindowPayload = JSON.parse(decodeURIComponent(encodedPayload));
7026
+ if (!isRecord(openWindowPayload) || !isRecord(openWindowPayload.webview)) {
7027
+ throw new Error('Invalid mobile App openWindow payload');
7028
+ }
7029
+ const devShellUrlValue = openWindowPayload.webview.url;
7030
+ if (typeof devShellUrlValue !== 'string') {
7031
+ throw new Error('Missing mobile App dev shell URL');
7032
+ }
7033
+ const devShellUrl = new URL(devShellUrlValue);
7034
+ devShellUrl.searchParams.delete('dev_network_request');
7035
+ devShellUrl.searchParams.set(MINI_PROGRAM_DEV_CONTEXT_QUERY_PARAM, devContextUrl);
7036
+ openWindowPayload.webview.url = devShellUrl.toString();
7037
+ return `${payload.slice(0, protocolIndex)}${protocolMarker}${encodeURIComponent(JSON.stringify(openWindowPayload))}`;
7038
+ }
6844
7039
  function updateNativeAppLaunchAvailability() {
6845
7040
  const isUnavailable = Boolean(nativeAppLaunchUnavailableReason);
6846
7041
  elements.macAppButton.disabled = isUnavailable;
package/dist/index.cjs.js CHANGED
@@ -325,7 +325,7 @@ function createMessageId() {
325
325
  /** 构建时替换为当前发布包的实际版本。 */
326
326
  const HB_SDK_VERSION = typeof undefined === 'string'
327
327
  ? undefined
328
- : '0.6.5';
328
+ : '0.6.6-alpha.1';
329
329
 
330
330
  /**
331
331
  * 判断未知数据是否符合小程序 bridge 消息信封。
package/dist/index.esm.js CHANGED
@@ -321,7 +321,7 @@ function createMessageId() {
321
321
  /** 构建时替换为当前发布包的实际版本。 */
322
322
  const HB_SDK_VERSION = typeof undefined === 'string'
323
323
  ? undefined
324
- : '0.6.5';
324
+ : '0.6.6-alpha.1';
325
325
 
326
326
  /**
327
327
  * 判断未知数据是否符合小程序 bridge 消息信封。
package/dist/vite.cjs.js CHANGED
@@ -7,7 +7,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
7
7
  /** 构建时替换为当前发布包的实际版本。 */
8
8
  const HB_SDK_VERSION = typeof undefined === 'string'
9
9
  ? undefined
10
- : '0.6.5';
10
+ : '0.6.6-alpha.1';
11
11
 
12
12
  var re = {exports: {}};
13
13
 
package/dist/vite.esm.js CHANGED
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  /** 构建时替换为当前发布包的实际版本。 */
5
5
  const HB_SDK_VERSION = typeof undefined === 'string'
6
6
  ? undefined
7
- : '0.6.5';
7
+ : '0.6.6-alpha.1';
8
8
 
9
9
  var re = {exports: {}};
10
10