@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.
- package/README.md +7 -1
- package/dist/cli-chunks/{context-DjepdCaa.cjs → context-D-cb_pNY.cjs} +1 -1
- package/dist/cli-chunks/{create-D3BBKay9.cjs → create-DlU4nWz_.cjs} +1 -1
- package/dist/cli-chunks/{dev-C3u5FXIy.cjs → dev-Bb4U965a.cjs} +992 -191
- package/dist/cli-chunks/{doctor-DEgZa2qC.cjs → doctor-DwDqOLdV.cjs} +1 -1
- package/dist/cli-chunks/{index-B5gEl9ow.cjs → index-B6gnwx39.cjs} +2 -2
- package/dist/cli-chunks/{index-CKat0ExC.cjs → index-gP0K2xx1.cjs} +13 -13
- package/dist/cli-chunks/{login-B6gERpSX.cjs → login-BFIcNgmi.cjs} +2 -2
- package/dist/cli-chunks/{remote-BfQiZzeJ.cjs → remote-YESvKni6.cjs} +4 -4
- package/dist/cli-chunks/{session-DPEq__gB.cjs → session-BRwveiW8.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/index.html +1 -0
- package/dist/devtools/mock-host/main.js +260 -65
- 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 +4 -3
- package/skill/SKILL.md +3 -1
- package/skill/references/api-root.md +8 -2
- package/skill/references/cli.md +4 -2
- package/skill/skill.json +4 -4
- package/types/protocol/dev-session.d.ts +25 -0
|
@@ -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-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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
+
var session = require('./session-BRwveiW8.cjs');
|
|
7
7
|
var browser = require('./browser-RAy8e8cV.cjs');
|
|
8
|
-
var index = require('./index-
|
|
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-
|
|
5
|
-
var session = require('./session-
|
|
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-
|
|
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-
|
|
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) {
|
package/dist/cli.cjs
CHANGED
|
@@ -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
|
-
|
|
4110
|
+
assertNetworkRequestUrl(requestUrl);
|
|
4106
4111
|
return requestUrl;
|
|
4107
4112
|
}
|
|
4108
|
-
function
|
|
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
|
-
|
|
6435
|
-
|
|
6436
|
-
let permissionState = clonePermissionState(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6525
|
-
|
|
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
|
|
6822
|
-
if (!
|
|
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
|
-
|
|
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
package/dist/index.esm.js
CHANGED
package/dist/vite.cjs.js
CHANGED