@heybox/hb-sdk 0.8.0-alpha.9 → 0.8.0
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 +67 -0
- package/README.md +25 -19
- package/dist/cli-chunks/{build-DkokKVNy.cjs → build-PYCNacya.cjs} +8 -5
- package/dist/cli-chunks/{context-CKzZxKbF.cjs → context-m2W2XbL0.cjs} +42 -59
- package/dist/cli-chunks/{create-BQy5Jdmu.cjs → create-BdAg3WGA.cjs} +1 -1
- package/dist/cli-chunks/{dev-Dik2zr5R.cjs → dev-CyZuw7Yn.cjs} +26 -15
- package/dist/cli-chunks/{doctor-Byr4uwKG.cjs → doctor-DU8rCfUF.cjs} +1 -1
- package/dist/cli-chunks/{index-Cl0XaX8e.cjs → index-DATObqzK.cjs} +2 -2
- package/dist/cli-chunks/{index-BwGBr1ZA.cjs → index-MMW2ibQm.cjs} +15 -15
- package/dist/cli-chunks/{index.esm-BYifBABc.cjs → index.esm-BiAaAUFC.cjs} +8 -8
- package/dist/cli-chunks/{login-Dr9lclu3.cjs → login-B3TThMss.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-BIPrOtRO.cjs → project-vite-BQj8YLI4.cjs} +1 -1
- package/dist/cli-chunks/{remote-DXxyA14a.cjs → remote-DNvI7tHH.cjs} +57 -25
- package/dist/cli-chunks/{runtime-gate-DFjw66kF.cjs → runtime-gate-BEFp1w_s.cjs} +11 -3
- package/dist/cli-chunks/{runtime-permission-env-CjsCe5bp.cjs → runtime-permission-env-CtL8rsjB.cjs} +351 -0
- package/dist/cli-chunks/{session-B6Mo9eYW.cjs → session-DjBkjaF8.cjs} +1 -1
- package/dist/cli-chunks/{skill-f90sxv28.cjs → skill-cR_wnaw2.cjs} +2 -2
- package/dist/cli-chunks/{version-DDB_btOG.cjs → version-yEn1E2Bg.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-TzYf9L6C.js +99 -0
- package/dist/devtools/browser-dev-host/assets/{index-DaqmTjSF.js → index-C5MZZDa5.js} +4 -4
- package/dist/devtools/browser-dev-host/assets/index-P-ra4m1y.css +1 -0
- package/dist/devtools/browser-dev-host/assets/{workbench-state-wHgWRb7I.js → workbench-state-BwV7bm4n.js} +2 -2
- package/dist/devtools/browser-dev-host/index.html +3 -3
- package/dist/index.cjs.js +99 -1
- package/dist/index.esm.js +99 -1
- package/dist/protocol.cjs.js +189 -47
- package/dist/protocol.esm.js +189 -47
- package/dist/templates/vanilla-vite-js/package.json.ejs +2 -1
- package/dist/vite.cjs.js +281 -13
- package/dist/vite.esm.js +281 -13
- package/package.json +5 -5
- package/skill/SKILL.md +8 -9
- package/skill/references/api-protocol.md +1 -1
- package/skill/references/api-root.md +63 -21
- package/skill/references/cli.md +6 -6
- package/skill/references/examples.md +3 -3
- package/skill/references/recipes.md +35 -38
- package/skill/references/safety-boundaries.md +9 -5
- package/skill/skill.json +5 -5
- package/types/core/mini-dev-console.d.ts +36 -0
- package/types/miniapp-manifest/index.d.ts +1 -0
- package/types/miniapp-manifest/node.d.ts +3 -0
- package/types/miniapp-manifest/permissions.d.ts +37 -0
- package/types/miniapp-manifest/schema.d.ts +5 -0
- package/types/vite/index.d.ts +3 -1
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-CbhA4h8z.js +0 -97
- package/dist/devtools/browser-dev-host/assets/index-DJFB5ySU.css +0 -1
|
@@ -11,8 +11,8 @@ var require$$0$4 = require('url');
|
|
|
11
11
|
var require$$0 = require('zlib');
|
|
12
12
|
var require$$0$1 = require('buffer');
|
|
13
13
|
var require$$1 = require('util');
|
|
14
|
-
var index = require('./index-
|
|
15
|
-
var dev = require('./dev-
|
|
14
|
+
var index = require('./index-MMW2ibQm.cjs');
|
|
15
|
+
var dev = require('./dev-CyZuw7Yn.cjs');
|
|
16
16
|
require('node:module');
|
|
17
17
|
require('node:fs');
|
|
18
18
|
require('node:fs/promises');
|
|
@@ -27,12 +27,13 @@ require('node:net');
|
|
|
27
27
|
require('node:crypto');
|
|
28
28
|
require('node:dns/promises');
|
|
29
29
|
require('node:http');
|
|
30
|
-
require('./context-
|
|
31
|
-
require('./
|
|
30
|
+
require('./context-m2W2XbL0.cjs');
|
|
31
|
+
require('./runtime-permission-env-CtL8rsjB.cjs');
|
|
32
|
+
require('./version-yEn1E2Bg.cjs');
|
|
33
|
+
require('node:async_hooks');
|
|
34
|
+
require('./session-DjBkjaF8.cjs');
|
|
32
35
|
require('fs');
|
|
33
36
|
require('constants');
|
|
34
|
-
require('./runtime-permission-env-CjsCe5bp.cjs');
|
|
35
|
-
require('node:async_hooks');
|
|
36
37
|
require('undici');
|
|
37
38
|
require('./browser-RAy8e8cV.cjs');
|
|
38
39
|
require('node:process');
|
|
@@ -40,8 +41,7 @@ require('node:buffer');
|
|
|
40
41
|
require('node:url');
|
|
41
42
|
require('node:util');
|
|
42
43
|
require('node:child_process');
|
|
43
|
-
require('./project-vite-
|
|
44
|
-
require('./version-DDB_btOG.cjs');
|
|
44
|
+
require('./project-vite-BQj8YLI4.cjs');
|
|
45
45
|
|
|
46
46
|
var bufferUtil = {exports: {}};
|
|
47
47
|
|
|
@@ -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-DjBkjaF8.cjs');
|
|
7
7
|
var browser = require('./browser-RAy8e8cV.cjs');
|
|
8
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-MMW2ibQm.cjs');
|
|
9
9
|
require('node:path');
|
|
10
10
|
require('fs');
|
|
11
11
|
require('constants');
|
|
@@ -5,7 +5,7 @@ var fs$1 = require('node:fs/promises');
|
|
|
5
5
|
var node_module = require('node:module');
|
|
6
6
|
var path = require('node:path');
|
|
7
7
|
var node_url = require('node:url');
|
|
8
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-MMW2ibQm.cjs');
|
|
9
9
|
|
|
10
10
|
function findProjectRoot(startDir) {
|
|
11
11
|
let current = path.resolve(startDir);
|
|
@@ -1,16 +1,16 @@
|
|
|
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-MMW2ibQm.cjs');
|
|
5
|
+
var session = require('./session-DjBkjaF8.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 runtimePermissionEnv = require('./runtime-permission-env-
|
|
11
|
-
var runtimeGate = require('./runtime-gate-
|
|
10
|
+
var runtimePermissionEnv = require('./runtime-permission-env-CtL8rsjB.cjs');
|
|
11
|
+
var runtimeGate = require('./runtime-gate-BEFp1w_s.cjs');
|
|
12
12
|
var node_crypto = require('node:crypto');
|
|
13
|
-
var context = require('./context-
|
|
13
|
+
var context = require('./context-m2W2XbL0.cjs');
|
|
14
14
|
require('node:module');
|
|
15
15
|
require('path');
|
|
16
16
|
require('os');
|
|
@@ -23,6 +23,7 @@ require('buffer');
|
|
|
23
23
|
require('util');
|
|
24
24
|
require('fs');
|
|
25
25
|
require('constants');
|
|
26
|
+
require('./version-yEn1E2Bg.cjs');
|
|
26
27
|
require('node:async_hooks');
|
|
27
28
|
|
|
28
29
|
async function getCDNUploadInfo(options, runtime = {}) {
|
|
@@ -271,7 +272,7 @@ function createDefaultCosClient(uploadToken, COS) {
|
|
|
271
272
|
};
|
|
272
273
|
}
|
|
273
274
|
async function loadCosConstructor() {
|
|
274
|
-
const cosModule = await Promise.resolve().then(function () { return require('./index-
|
|
275
|
+
const cosModule = await Promise.resolve().then(function () { return require('./index-DATObqzK.cjs'); }).then(function (n) { return n.index; });
|
|
275
276
|
return cosModule.default;
|
|
276
277
|
}
|
|
277
278
|
function formatSize(bytes) {
|
|
@@ -530,6 +531,7 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
530
531
|
precheckVersion = precheck.version || precheck.version_normalized || fromVersion;
|
|
531
532
|
}
|
|
532
533
|
else {
|
|
534
|
+
const localPermissions = runtimePermissionEnv.readMiniappPermissionsFromPackageJson(projectRoot, runtimePermissionEnv.resolveMiniappSdkVersion());
|
|
533
535
|
if (typeof packageJson.scripts?.build !== 'string') {
|
|
534
536
|
throw new Error('package.json scripts.build 未定义,请添加 build 脚本');
|
|
535
537
|
}
|
|
@@ -552,7 +554,8 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
552
554
|
loginBaseUrl,
|
|
553
555
|
session: session$1,
|
|
554
556
|
}), { successText: '已读取远端小程序权限' });
|
|
555
|
-
|
|
557
|
+
const localNetworkEnabled = !localPermissions.declared || localPermissions.permissions?.network?.enabled === true;
|
|
558
|
+
skipPlatformCsp = localNetworkEnabled && context.shouldSkipMiniappPlatformCsp(detail.runtime_permissions);
|
|
556
559
|
}
|
|
557
560
|
catch (error) {
|
|
558
561
|
logger.warn('未读取到远端 Runtime 权限,构建将继续注入平台 CSP。');
|
|
@@ -561,7 +564,8 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
561
564
|
const pm = detectPackageManager(projectRoot);
|
|
562
565
|
const platform = runtime.platform ?? process.platform;
|
|
563
566
|
const buildMode = validateBuildMode(env.HB_SDK_ENV?.trim(), platform);
|
|
564
|
-
|
|
567
|
+
const buildScript = await readProjectBuildScript(projectRoot);
|
|
568
|
+
logger.info(`开始构建: ${pm} ${createBuildArgs(pm, buildMode, buildScript).join(' ')}`);
|
|
565
569
|
await runBuildScript(pm, projectRoot, runtime.spawn ?? childProcess.spawn, {
|
|
566
570
|
env: runtimePermissionEnv.createMiniappPlatformCspEnv(env, skipPlatformCsp),
|
|
567
571
|
mode: buildMode,
|
|
@@ -801,9 +805,10 @@ function detectPackageManager(projectRoot) {
|
|
|
801
805
|
return 'npm';
|
|
802
806
|
}
|
|
803
807
|
async function runBuildScript(pm, cwd, spawnImpl, options) {
|
|
808
|
+
const buildScript = await readProjectBuildScript(cwd);
|
|
804
809
|
await new Promise((resolve, reject) => {
|
|
805
810
|
const pipeStdoutToStderr = options.outputMode === 'stderr';
|
|
806
|
-
const buildArgs = createBuildArgs(pm, options.mode);
|
|
811
|
+
const buildArgs = createBuildArgs(pm, options.mode, buildScript);
|
|
807
812
|
const isWindows = options.platform === 'win32';
|
|
808
813
|
const [executable, args] = isWindows ? createWindowsBuildCommand(pm, buildArgs) : [pm, buildArgs];
|
|
809
814
|
const child = spawnImpl(executable, args, {
|
|
@@ -841,8 +846,18 @@ function validateBuildMode(mode, platform) {
|
|
|
841
846
|
function escapeWindowsCommandArgument(argument) {
|
|
842
847
|
return `"${argument}"`;
|
|
843
848
|
}
|
|
844
|
-
function
|
|
845
|
-
|
|
849
|
+
async function readProjectBuildScript(projectRoot) {
|
|
850
|
+
try {
|
|
851
|
+
const packageJson = JSON.parse(await fs$1.readFile(path.join(projectRoot, 'package.json'), 'utf8'));
|
|
852
|
+
return typeof packageJson.scripts?.build === 'string' ? packageJson.scripts.build : '';
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
return '';
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
function createBuildArgs(pm, mode, buildScript) {
|
|
859
|
+
const modeOption = /\bhb-sdk\s+build\b/.test(buildScript) ? '--env' : '--mode';
|
|
860
|
+
return ['run', 'build', ...(mode ? [...(pm === 'npm' ? ['--'] : []), modeOption, mode] : [])];
|
|
846
861
|
}
|
|
847
862
|
async function walkDistFiles(distDir) {
|
|
848
863
|
const results = [];
|
|
@@ -1171,7 +1186,10 @@ async function remoteEntitySwitch(options, context, runtime) {
|
|
|
1171
1186
|
async function remoteList(options, context, runtime) {
|
|
1172
1187
|
const result = await context.api.listMiniPrograms({ keyword: options.keyword, status: options.status });
|
|
1173
1188
|
const items = Array.isArray(result.items) ? result.items : [];
|
|
1174
|
-
const outputItems = items.map((item) => ({
|
|
1189
|
+
const outputItems = items.map((item) => ({
|
|
1190
|
+
...toCamelCaseDeep(item),
|
|
1191
|
+
bound: item.mini_program_id === context.binding,
|
|
1192
|
+
}));
|
|
1175
1193
|
const output = { changed: false, items: outputItems, total: readNumber(result.total, items.length) };
|
|
1176
1194
|
if (!options.json) {
|
|
1177
1195
|
if (items.length === 0) {
|
|
@@ -1228,9 +1246,11 @@ async function remoteBind(options, context$1, runtime) {
|
|
|
1228
1246
|
async function remoteInfo(options, context, runtime) {
|
|
1229
1247
|
const miniProgramId = requireBinding(context);
|
|
1230
1248
|
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
1231
|
-
const
|
|
1249
|
+
const localPermissions = runtimePermissionEnv.readMiniappPermissionsFromPackageJson(context.packageJson.projectRoot, runtimePermissionEnv.resolveMiniappSdkVersion());
|
|
1250
|
+
const permissionViews = runtimePermissionEnv.composeMiniappRuntimePermissions(localPermissions, detail.runtime_permissions).views;
|
|
1251
|
+
const output = { changed: false, miniProgramId, detail: toCamelCaseDeep(detail), permissions: permissionViews };
|
|
1232
1252
|
if (!options.json) {
|
|
1233
|
-
printMiniProgramDetail(context.logger, detail);
|
|
1253
|
+
printMiniProgramDetail(context.logger, detail, permissionViews);
|
|
1234
1254
|
}
|
|
1235
1255
|
return finishRemoteCommand(options, runtime, output);
|
|
1236
1256
|
}
|
|
@@ -1356,7 +1376,9 @@ async function remotePreview(options, context, runtime) {
|
|
|
1356
1376
|
}
|
|
1357
1377
|
async function remoteDangerousWrite(options, context, runtime) {
|
|
1358
1378
|
const miniProgramId = requireBinding(context);
|
|
1359
|
-
const version = options.command === 'release' || options.command === 'withdraw'
|
|
1379
|
+
const version = options.command === 'release' || options.command === 'withdraw'
|
|
1380
|
+
? requireNonEmpty(options.version, `remote ${options.command} 必须传 <version>`)
|
|
1381
|
+
: undefined;
|
|
1360
1382
|
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
1361
1383
|
await confirmDangerousRemoteChange(options, runtime, context.logger, {
|
|
1362
1384
|
miniProgramId,
|
|
@@ -1545,7 +1567,18 @@ function parseEntityId(value) {
|
|
|
1545
1567
|
return entityId;
|
|
1546
1568
|
}
|
|
1547
1569
|
async function listDeveloperEntitiesWithAccessFallback(context) {
|
|
1548
|
-
|
|
1570
|
+
let result;
|
|
1571
|
+
try {
|
|
1572
|
+
result = await context.api.listDeveloperEntities();
|
|
1573
|
+
}
|
|
1574
|
+
catch (error) {
|
|
1575
|
+
const fallback = createEntityFromAccessStatus(await context.api.accessStatus());
|
|
1576
|
+
if (!fallback) {
|
|
1577
|
+
throw error;
|
|
1578
|
+
}
|
|
1579
|
+
context.logger.debug('开发者主体列表不可用,已回退使用小程序工坊准入主体');
|
|
1580
|
+
return { fromAccessFallback: true, items: [fallback], total: 1 };
|
|
1581
|
+
}
|
|
1549
1582
|
const items = normalizeDeveloperEntities(result);
|
|
1550
1583
|
if (items.length > 0) {
|
|
1551
1584
|
return { items, total: readNumber(result.total, items.length) };
|
|
@@ -1716,7 +1749,7 @@ async function promptConfirm(message, runtime) {
|
|
|
1716
1749
|
rl.close();
|
|
1717
1750
|
}
|
|
1718
1751
|
}
|
|
1719
|
-
function printMiniProgramDetail(logger, detail) {
|
|
1752
|
+
function printMiniProgramDetail(logger, detail, permissionViews) {
|
|
1720
1753
|
logger.info(`Mini-program: ${detail.mini_program_id ?? '--'}`);
|
|
1721
1754
|
logger.info(`Name: ${detail.name ?? '--'}`);
|
|
1722
1755
|
logger.info(`Status: ${detail.status ?? '--'}`);
|
|
@@ -1727,14 +1760,13 @@ function printMiniProgramDetail(logger, detail) {
|
|
|
1727
1760
|
if (detail.protocol_string) {
|
|
1728
1761
|
logger.info(`Protocol: ${detail.protocol_string}`);
|
|
1729
1762
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
}
|
|
1763
|
+
logger.info('权限:');
|
|
1764
|
+
for (const view of permissionViews) {
|
|
1765
|
+
const approval = view.access === 'platform-approval' ? ` 需申请=是 批准=${view.approved ? '是' : '否'}` : ' 需申请=否';
|
|
1766
|
+
const configs = view.requestedConfig
|
|
1767
|
+
? ` requested=${JSON.stringify(view.requestedConfig)} approved=${JSON.stringify(view.approvedConfig)} effective=${JSON.stringify(view.effectiveConfig)}`
|
|
1768
|
+
: '';
|
|
1769
|
+
logger.info(` ${view.key}: 声明=${view.declared ? '是' : '否'}${approval} 最终=${view.effective ? '可用' : '不可用'}${configs}`);
|
|
1738
1770
|
}
|
|
1739
1771
|
}
|
|
1740
1772
|
function printDeveloperEntities(logger, entities) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var runtimePermissionEnv = require('./runtime-permission-env-
|
|
3
|
+
var runtimePermissionEnv = require('./runtime-permission-env-CtL8rsjB.cjs');
|
|
4
4
|
|
|
5
5
|
const MINIAPP_PLATFORM_VALUES = ['android', 'ios', 'ohos', 'windows', 'macos', 'linux'];
|
|
6
6
|
function isValidMiniappManifestVersion(version) {
|
|
@@ -32,10 +32,18 @@ function parseMiniappManifestJson(raw, sourceLabel = 'manifest.json') {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
function validateMiniappManifestForDeploy(manifest) {
|
|
35
|
+
const version = validateMiniappManifestVersion(manifest.version, 'manifest.version');
|
|
36
|
+
const sdkVersion = validateSdkVersion(manifest.sdkVersion, 'manifest.sdkVersion');
|
|
37
|
+
const permissions = runtimePermissionEnv.parseMiniappPermissions(manifest.permissions, {
|
|
38
|
+
present: Object.prototype.hasOwnProperty.call(manifest, 'permissions'),
|
|
39
|
+
sdkVersion,
|
|
40
|
+
sourceLabel: 'manifest.permissions',
|
|
41
|
+
});
|
|
35
42
|
return {
|
|
36
|
-
version
|
|
37
|
-
sdkVersion
|
|
43
|
+
version,
|
|
44
|
+
sdkVersion,
|
|
38
45
|
platforms: validateMiniappPlatforms(manifest.platforms, 'manifest.platforms'),
|
|
46
|
+
...(permissions.permissions === undefined ? {} : { permissions: permissions.permissions }),
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
function validateMiniappPlatforms(platforms, sourceLabel = 'platforms') {
|
package/dist/cli-chunks/{runtime-permission-env-CjsCe5bp.cjs → runtime-permission-env-CtL8rsjB.cjs}
RENAMED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var fs = require('node:fs');
|
|
4
|
+
var path = require('node:path');
|
|
5
|
+
var version = require('./version-yEn1E2Bg.cjs');
|
|
3
6
|
var node_async_hooks = require('node:async_hooks');
|
|
4
7
|
|
|
5
8
|
var re = {exports: {}};
|
|
@@ -2787,6 +2790,285 @@ function requireSemver () {
|
|
|
2787
2790
|
|
|
2788
2791
|
var semverExports = requireSemver();
|
|
2789
2792
|
|
|
2793
|
+
const MINI_PROGRAM_PERMISSION_KEYS = [
|
|
2794
|
+
'userInfo',
|
|
2795
|
+
'steamLibrary',
|
|
2796
|
+
'share',
|
|
2797
|
+
'storage',
|
|
2798
|
+
'filesystem',
|
|
2799
|
+
'clipboard',
|
|
2800
|
+
'leaderboard',
|
|
2801
|
+
'network',
|
|
2802
|
+
];
|
|
2803
|
+
const MINI_PROGRAM_PERMISSION_CATALOG = [
|
|
2804
|
+
{
|
|
2805
|
+
key: 'userInfo',
|
|
2806
|
+
name: '用户信息',
|
|
2807
|
+
description: '登录小程序并读取当前用户的授权信息。',
|
|
2808
|
+
access: 'declaration',
|
|
2809
|
+
risk: 'medium',
|
|
2810
|
+
config: {},
|
|
2811
|
+
methods: ['auth.login', 'user.getInfo'],
|
|
2812
|
+
conditions: ['继续执行黑盒登录、用户授权和可信手势规则。'],
|
|
2813
|
+
},
|
|
2814
|
+
{
|
|
2815
|
+
key: 'steamLibrary',
|
|
2816
|
+
name: 'Steam 游戏库',
|
|
2817
|
+
description: '读取当前用户授权的 Steam 游戏库。',
|
|
2818
|
+
access: 'declaration',
|
|
2819
|
+
risk: 'high',
|
|
2820
|
+
config: {},
|
|
2821
|
+
methods: ['user.getSteamGameList'],
|
|
2822
|
+
conditions: ['继续执行账号绑定和数据可用性规则。'],
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
key: 'share',
|
|
2826
|
+
name: '分享',
|
|
2827
|
+
description: '使用小程序分享、分享菜单和截图能力。',
|
|
2828
|
+
access: 'declaration',
|
|
2829
|
+
risk: 'medium',
|
|
2830
|
+
config: {},
|
|
2831
|
+
methods: ['share.copyLink', 'share.showShareMenu', 'share.screenshot'],
|
|
2832
|
+
conditions: ['继续执行分享参数校验和 Host 支持检查。'],
|
|
2833
|
+
},
|
|
2834
|
+
{
|
|
2835
|
+
key: 'storage',
|
|
2836
|
+
name: '键值存储',
|
|
2837
|
+
description: '读写按小程序隔离的简单键值数据。',
|
|
2838
|
+
access: 'declaration',
|
|
2839
|
+
risk: 'medium',
|
|
2840
|
+
config: {},
|
|
2841
|
+
methods: ['storage.getStorage', 'storage.setStorage'],
|
|
2842
|
+
conditions: ['仅用于简单键值存储,不包含文件系统。'],
|
|
2843
|
+
},
|
|
2844
|
+
{
|
|
2845
|
+
key: 'filesystem',
|
|
2846
|
+
name: '文件系统',
|
|
2847
|
+
description: '访问小程序沙盒文件和用户选择的外部文件。',
|
|
2848
|
+
access: 'declaration',
|
|
2849
|
+
risk: 'high',
|
|
2850
|
+
config: {},
|
|
2851
|
+
methods: [
|
|
2852
|
+
'network.download',
|
|
2853
|
+
'files.pickFiles',
|
|
2854
|
+
'files.pickDirectory',
|
|
2855
|
+
'files.saveFile',
|
|
2856
|
+
'file.create',
|
|
2857
|
+
'file.remove',
|
|
2858
|
+
'file.exists',
|
|
2859
|
+
'file.readText',
|
|
2860
|
+
'file.writeText',
|
|
2861
|
+
'file.readBytes',
|
|
2862
|
+
'file.writeBytes',
|
|
2863
|
+
'file.stat',
|
|
2864
|
+
'directory.create',
|
|
2865
|
+
'directory.remove',
|
|
2866
|
+
'directory.exists',
|
|
2867
|
+
'directory.list',
|
|
2868
|
+
],
|
|
2869
|
+
conditions: ['外部文件继续要求有效的用户选择、会话句柄和匹配的读写模式。'],
|
|
2870
|
+
},
|
|
2871
|
+
{
|
|
2872
|
+
key: 'clipboard',
|
|
2873
|
+
name: '剪贴板',
|
|
2874
|
+
description: '向系统剪贴板写入文本。',
|
|
2875
|
+
access: 'declaration',
|
|
2876
|
+
risk: 'medium',
|
|
2877
|
+
config: {},
|
|
2878
|
+
methods: ['device.setClipboard'],
|
|
2879
|
+
conditions: ['继续执行文本长度和 Host 支持限制。'],
|
|
2880
|
+
},
|
|
2881
|
+
{
|
|
2882
|
+
key: 'leaderboard',
|
|
2883
|
+
name: '排行榜',
|
|
2884
|
+
description: '读写小程序云排行榜。',
|
|
2885
|
+
access: 'declaration',
|
|
2886
|
+
risk: 'medium',
|
|
2887
|
+
config: {},
|
|
2888
|
+
methods: [
|
|
2889
|
+
'cloud.leaderboard.submit',
|
|
2890
|
+
'cloud.leaderboard.getList',
|
|
2891
|
+
'cloud.leaderboard.getCurrentUserEntry',
|
|
2892
|
+
'cloud.leaderboard.deleteCurrentUserEntry',
|
|
2893
|
+
'cloud.leaderboard.getInfo',
|
|
2894
|
+
],
|
|
2895
|
+
conditions: ['排行榜必须已创建,用户和资源规则保持不变。'],
|
|
2896
|
+
},
|
|
2897
|
+
{
|
|
2898
|
+
key: 'network',
|
|
2899
|
+
name: '网络',
|
|
2900
|
+
description: '通过 network 模块请求或下载外部资源。',
|
|
2901
|
+
access: 'platform-approval',
|
|
2902
|
+
risk: 'high',
|
|
2903
|
+
config: {
|
|
2904
|
+
useOfficialDomain: {
|
|
2905
|
+
type: 'boolean',
|
|
2906
|
+
required: false,
|
|
2907
|
+
default: false,
|
|
2908
|
+
description: '是否申请访问小黑盒官方域名。',
|
|
2909
|
+
},
|
|
2910
|
+
},
|
|
2911
|
+
methods: ['network.request', 'network.download'],
|
|
2912
|
+
conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
|
|
2913
|
+
},
|
|
2914
|
+
];
|
|
2915
|
+
new Set(MINI_PROGRAM_PERMISSION_KEYS);
|
|
2916
|
+
|
|
2917
|
+
const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(MINI_PROGRAM_PERMISSION_KEYS);
|
|
2918
|
+
function isManagedMiniProgramRuntimePermissionKey(key) {
|
|
2919
|
+
return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
|
|
2920
|
+
}
|
|
2921
|
+
function parseMiniProgramRuntimePermissions(snapshot) {
|
|
2922
|
+
if (!isRecord$2(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
|
|
2923
|
+
return { valid: false, permissions: {} };
|
|
2924
|
+
}
|
|
2925
|
+
if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
|
|
2926
|
+
return { valid: false, permissions: {} };
|
|
2927
|
+
}
|
|
2928
|
+
const seenKeys = new Set();
|
|
2929
|
+
const permissions = {};
|
|
2930
|
+
for (const rawEntry of snapshot.entries) {
|
|
2931
|
+
if (!isRecord$2(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
|
|
2932
|
+
return { valid: false, permissions: {} };
|
|
2933
|
+
}
|
|
2934
|
+
const inputKey = rawEntry.key.trim();
|
|
2935
|
+
const key = inputKey === 'network.request' ? 'network' : inputKey;
|
|
2936
|
+
if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled')) {
|
|
2937
|
+
return { valid: false, permissions: {} };
|
|
2938
|
+
}
|
|
2939
|
+
seenKeys.add(key);
|
|
2940
|
+
if (!isManagedMiniProgramRuntimePermissionKey(key)) {
|
|
2941
|
+
if (!isRecord$2(rawEntry.config))
|
|
2942
|
+
return { valid: false, permissions: {} };
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
2945
|
+
if (key === 'network') {
|
|
2946
|
+
const config = rawEntry.config;
|
|
2947
|
+
if (!isRecord$2(config) || typeof config.useOfficialDomain !== 'boolean') {
|
|
2948
|
+
return { valid: false, permissions: {} };
|
|
2949
|
+
}
|
|
2950
|
+
permissions[key] = {
|
|
2951
|
+
key,
|
|
2952
|
+
status: rawEntry.status,
|
|
2953
|
+
config: { useOfficialDomain: config.useOfficialDomain },
|
|
2954
|
+
};
|
|
2955
|
+
continue;
|
|
2956
|
+
}
|
|
2957
|
+
if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord$2(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
|
|
2958
|
+
return { valid: false, permissions: {} };
|
|
2959
|
+
}
|
|
2960
|
+
permissions[key] = {
|
|
2961
|
+
key,
|
|
2962
|
+
status: rawEntry.status,
|
|
2963
|
+
config: {},
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
return { valid: true, permissions };
|
|
2967
|
+
}
|
|
2968
|
+
function isRecord$2(value) {
|
|
2969
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
|
|
2973
|
+
function parseMiniappPermissions(value, options) {
|
|
2974
|
+
const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
|
|
2975
|
+
if (!options.present) {
|
|
2976
|
+
if (requiresExplicitPermissions(options.sdkVersion)) {
|
|
2977
|
+
throw new Error(`${sourceLabel} 在 @heybox/hb-sdk ${options.sdkVersion} 中必须声明;无权限需求时请配置空对象 {}`);
|
|
2978
|
+
}
|
|
2979
|
+
return { declared: false };
|
|
2980
|
+
}
|
|
2981
|
+
if (!isRecord$1(value)) {
|
|
2982
|
+
throw new Error(`${sourceLabel} 必须是 JSON 对象`);
|
|
2983
|
+
}
|
|
2984
|
+
const knownKeys = new Set(MINIAPP_PERMISSION_KEYS);
|
|
2985
|
+
for (const key of Object.keys(value)) {
|
|
2986
|
+
if (!knownKeys.has(key))
|
|
2987
|
+
throw new Error(`${sourceLabel} 包含未知权限:${key}`);
|
|
2988
|
+
}
|
|
2989
|
+
const permissions = {};
|
|
2990
|
+
for (const key of MINIAPP_PERMISSION_KEYS) {
|
|
2991
|
+
if (!Object.prototype.hasOwnProperty.call(value, key))
|
|
2992
|
+
continue;
|
|
2993
|
+
const declaration = value[key];
|
|
2994
|
+
const itemLabel = `${sourceLabel}.${key}`;
|
|
2995
|
+
if (!isRecord$1(declaration))
|
|
2996
|
+
throw new Error(`${itemLabel} 必须是 JSON 对象`);
|
|
2997
|
+
const definition = MINI_PROGRAM_PERMISSION_CATALOG.find((item) => item.key === key);
|
|
2998
|
+
if (!definition)
|
|
2999
|
+
throw new Error(`权限目录缺少定义:${key}`);
|
|
3000
|
+
const allowedFields = new Set(['enabled', ...Object.keys(definition.config)]);
|
|
3001
|
+
for (const field of Object.keys(declaration)) {
|
|
3002
|
+
if (!allowedFields.has(field))
|
|
3003
|
+
throw new Error(`${itemLabel} 包含未知字段:${field}`);
|
|
3004
|
+
}
|
|
3005
|
+
if (typeof declaration.enabled !== 'boolean')
|
|
3006
|
+
throw new Error(`${itemLabel}.enabled 必须是 boolean`);
|
|
3007
|
+
let useOfficialDomain = false;
|
|
3008
|
+
if (key === 'network') {
|
|
3009
|
+
if (declaration.useOfficialDomain !== undefined && typeof declaration.useOfficialDomain !== 'boolean') {
|
|
3010
|
+
throw new Error(`${itemLabel}.useOfficialDomain 必须是 boolean`);
|
|
3011
|
+
}
|
|
3012
|
+
useOfficialDomain = declaration.useOfficialDomain === true;
|
|
3013
|
+
}
|
|
3014
|
+
if (!declaration.enabled)
|
|
3015
|
+
continue;
|
|
3016
|
+
permissions[key] = key === 'network' ? { enabled: true, useOfficialDomain } : { enabled: true };
|
|
3017
|
+
}
|
|
3018
|
+
return { declared: true, permissions: permissions };
|
|
3019
|
+
}
|
|
3020
|
+
function requiresExplicitPermissions(sdkVersion) {
|
|
3021
|
+
const parsed = semverExports.parse(sdkVersion);
|
|
3022
|
+
if (!parsed)
|
|
3023
|
+
throw new Error(`sdkVersion 必须是合法 SemVer:${sdkVersion}`);
|
|
3024
|
+
return parsed.major > 0 || parsed.minor >= 9;
|
|
3025
|
+
}
|
|
3026
|
+
function getMissingPermissionsWarning(sourceLabel = 'package.json#heybox.permissions') {
|
|
3027
|
+
return `${sourceLabel} 尚未声明。当前按 0.8 兼容行为构建;0.9.0 起将拒绝构建,请尽快补充权限声明(无权限需求时配置 {})。`;
|
|
3028
|
+
}
|
|
3029
|
+
function composeMiniappRuntimePermissions(local, approvals) {
|
|
3030
|
+
const parsedApprovals = parseMiniProgramRuntimePermissions(approvals);
|
|
3031
|
+
const approvalRevision = isRecord$1(approvals) && Number.isInteger(approvals.revision) ? approvals.revision : undefined;
|
|
3032
|
+
const views = [];
|
|
3033
|
+
const entries = [];
|
|
3034
|
+
for (const definition of MINI_PROGRAM_PERMISSION_CATALOG) {
|
|
3035
|
+
const declaration = local.permissions?.[definition.key];
|
|
3036
|
+
const declared = !local.declared || declaration?.enabled === true;
|
|
3037
|
+
if (definition.access === 'declaration') {
|
|
3038
|
+
views.push({ key: definition.key, access: definition.access, declared, approved: null, effective: declared });
|
|
3039
|
+
if (declared)
|
|
3040
|
+
entries.push({ key: definition.key, status: 'enabled', config: {} });
|
|
3041
|
+
continue;
|
|
3042
|
+
}
|
|
3043
|
+
const approval = parsedApprovals.valid ? parsedApprovals.permissions[definition.key] : undefined;
|
|
3044
|
+
const approved = approval?.status === 'enabled';
|
|
3045
|
+
const requestedOfficialDomain = declaration?.enabled === true && 'useOfficialDomain' in declaration && declaration.useOfficialDomain;
|
|
3046
|
+
const approvedOfficialDomain = approval?.config.useOfficialDomain === true;
|
|
3047
|
+
const effective = declared && approved;
|
|
3048
|
+
const effectiveOfficialDomain = effective && (local.declared ? requestedOfficialDomain : true) && approvedOfficialDomain;
|
|
3049
|
+
views.push({
|
|
3050
|
+
key: definition.key,
|
|
3051
|
+
access: definition.access,
|
|
3052
|
+
declared,
|
|
3053
|
+
approved,
|
|
3054
|
+
requestedConfig: { useOfficialDomain: requestedOfficialDomain },
|
|
3055
|
+
approvedConfig: { useOfficialDomain: approvedOfficialDomain },
|
|
3056
|
+
effective,
|
|
3057
|
+
effectiveConfig: { useOfficialDomain: effectiveOfficialDomain },
|
|
3058
|
+
});
|
|
3059
|
+
if (declared) {
|
|
3060
|
+
entries.push({ key: definition.key, status: effective ? 'enabled' : 'disabled', config: { useOfficialDomain: effectiveOfficialDomain } });
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
return {
|
|
3064
|
+
runtimePermissions: { schema_version: 1, ...(approvalRevision === undefined ? {} : { revision: approvalRevision }), entries },
|
|
3065
|
+
views,
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
function isRecord$1(value) {
|
|
3069
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3070
|
+
}
|
|
3071
|
+
|
|
2790
3072
|
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
2791
3073
|
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
2792
3074
|
const MINIAPP_UPLOAD_BATCH_SIZE = 50;
|
|
@@ -3063,6 +3345,68 @@ function compareBytes(left, right) {
|
|
|
3063
3345
|
return left.length - right.length;
|
|
3064
3346
|
}
|
|
3065
3347
|
|
|
3348
|
+
function findNearestPackageJsonPath(startDir) {
|
|
3349
|
+
let current = path.resolve(startDir);
|
|
3350
|
+
while (true) {
|
|
3351
|
+
const packageJsonPath = path.join(current, 'package.json');
|
|
3352
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
3353
|
+
return packageJsonPath;
|
|
3354
|
+
}
|
|
3355
|
+
const parent = path.dirname(current);
|
|
3356
|
+
if (parent === current) {
|
|
3357
|
+
return path.join(path.resolve(startDir), 'package.json');
|
|
3358
|
+
}
|
|
3359
|
+
current = parent;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
function readMiniappPermissionsFromPackageJson(root, sdkVersion) {
|
|
3363
|
+
const { packageJson } = readMiniappPackageJson(root);
|
|
3364
|
+
const heybox = packageJson.heybox;
|
|
3365
|
+
if (heybox !== undefined && !isRecord(heybox)) {
|
|
3366
|
+
throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
|
|
3367
|
+
}
|
|
3368
|
+
const present = isRecord(heybox) && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
|
|
3369
|
+
return parseMiniappPermissions(isRecord(heybox) ? heybox.permissions : undefined, {
|
|
3370
|
+
present,
|
|
3371
|
+
sdkVersion,
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
function resolveMiniappSdkVersion() {
|
|
3375
|
+
if (!version.HB_SDK_VERSION.startsWith('__HB_SDK_'))
|
|
3376
|
+
return version.HB_SDK_VERSION;
|
|
3377
|
+
const packageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json'), 'utf8'));
|
|
3378
|
+
if (typeof packageJson.version !== 'string' || !packageJson.version)
|
|
3379
|
+
throw new Error('未能读取 @heybox/hb-sdk 当前版本号');
|
|
3380
|
+
return packageJson.version;
|
|
3381
|
+
}
|
|
3382
|
+
function readMiniappPackageJson(root, requireVersion) {
|
|
3383
|
+
const packageJsonPath = findNearestPackageJsonPath(root);
|
|
3384
|
+
let content;
|
|
3385
|
+
try {
|
|
3386
|
+
content = fs.readFileSync(packageJsonPath, 'utf8');
|
|
3387
|
+
}
|
|
3388
|
+
catch (error) {
|
|
3389
|
+
throw new Error(`@heybox/hb-sdk 读取 package.json 失败:${formatReason(error)}`);
|
|
3390
|
+
}
|
|
3391
|
+
let packageJson;
|
|
3392
|
+
try {
|
|
3393
|
+
packageJson = JSON.parse(content);
|
|
3394
|
+
}
|
|
3395
|
+
catch (error) {
|
|
3396
|
+
throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
|
|
3397
|
+
}
|
|
3398
|
+
return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
|
|
3399
|
+
}
|
|
3400
|
+
function isRecord(value) {
|
|
3401
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3402
|
+
}
|
|
3403
|
+
function formatReason(error) {
|
|
3404
|
+
if (error instanceof Error && error.message) {
|
|
3405
|
+
return error.message;
|
|
3406
|
+
}
|
|
3407
|
+
return String(error);
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3066
3410
|
const HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV = 'HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN';
|
|
3067
3411
|
const HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV = 'HB_SDK_RUNTIME_PERMISSION_CONTEXT';
|
|
3068
3412
|
const VERIFIED_RUNTIME_PERMISSION_CONTEXT = 'verified';
|
|
@@ -3142,6 +3486,7 @@ exports.LIST_USER_MINIPROGRAM_LEADERBOARD_API_PATH = LIST_USER_MINIPROGRAM_LEADE
|
|
|
3142
3486
|
exports.LIST_USER_MINIPROGRAM_VERSION_API_PATH = LIST_USER_MINIPROGRAM_VERSION_API_PATH;
|
|
3143
3487
|
exports.MINIAPP_UPLOAD_BATCH_SIZE = MINIAPP_UPLOAD_BATCH_SIZE;
|
|
3144
3488
|
exports.MINIAPP_UPLOAD_SCOPE = MINIAPP_UPLOAD_SCOPE;
|
|
3489
|
+
exports.MINI_PROGRAM_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
|
|
3145
3490
|
exports.PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH = PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH;
|
|
3146
3491
|
exports.RELEASE_USER_MINIPROGRAM_VERSION_API_PATH = RELEASE_USER_MINIPROGRAM_VERSION_API_PATH;
|
|
3147
3492
|
exports.REOPEN_USER_MINIPROGRAM_API_PATH = REOPEN_USER_MINIPROGRAM_API_PATH;
|
|
@@ -3153,13 +3498,19 @@ exports.USER_MINIPROGRAM_ACCESS_STATUS_API_PATH = USER_MINIPROGRAM_ACCESS_STATUS
|
|
|
3153
3498
|
exports.USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH = USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH;
|
|
3154
3499
|
exports.USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH = USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH;
|
|
3155
3500
|
exports.WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH = WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH;
|
|
3501
|
+
exports.composeMiniappRuntimePermissions = composeMiniappRuntimePermissions;
|
|
3156
3502
|
exports.createMiniappArtifactFileHeader = createMiniappArtifactFileHeader;
|
|
3157
3503
|
exports.createMiniappArtifactSignatureHeader = createMiniappArtifactSignatureHeader;
|
|
3158
3504
|
exports.createMiniappPlatformCspEnv = createMiniappPlatformCspEnv;
|
|
3505
|
+
exports.getMissingPermissionsWarning = getMissingPermissionsWarning;
|
|
3159
3506
|
exports.normalizeRelativePath = normalizeRelativePath;
|
|
3507
|
+
exports.parseMiniProgramRuntimePermissions = parseMiniProgramRuntimePermissions;
|
|
3508
|
+
exports.parseMiniappPermissions = parseMiniappPermissions;
|
|
3160
3509
|
exports.prepareMiniappArtifactFiles = prepareMiniappArtifactFiles;
|
|
3510
|
+
exports.readMiniappPermissionsFromPackageJson = readMiniappPermissionsFromPackageJson;
|
|
3161
3511
|
exports.relativePathContainsNodeModulesSegment = relativePathContainsNodeModulesSegment;
|
|
3162
3512
|
exports.requireSemver = requireSemver;
|
|
3513
|
+
exports.resolveMiniappSdkVersion = resolveMiniappSdkVersion;
|
|
3163
3514
|
exports.resolveMiniappUploadSessionFiles = resolveMiniappUploadSessionFiles;
|
|
3164
3515
|
exports.semverExports = semverExports;
|
|
3165
3516
|
exports.shouldSkipMiniappPlatformCspFromEnv = shouldSkipMiniappPlatformCspFromEnv;
|