@heybox/hb-sdk 0.8.0-alpha.3 → 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 +136 -422
- package/README.md +28 -18
- package/dist/cli-chunks/{build-qWzAbpS7.cjs → build-PYCNacya.cjs} +8 -5
- package/dist/cli-chunks/{context-CtS2Thp0.cjs → context-m2W2XbL0.cjs} +42 -59
- package/dist/cli-chunks/{create-PV5ua977.cjs → create-BdAg3WGA.cjs} +2 -2
- package/dist/cli-chunks/{dev-CwKbAm_H.cjs → dev-CyZuw7Yn.cjs} +76 -64
- package/dist/cli-chunks/{doctor-tJUGOYrm.cjs → doctor-DU8rCfUF.cjs} +1 -1
- package/dist/cli-chunks/{index-DVuD75Hr.cjs → index-DATObqzK.cjs} +2 -2
- package/dist/cli-chunks/{index-De687C6-.cjs → index-MMW2ibQm.cjs} +32 -21
- package/dist/cli-chunks/{index.esm-B-4yrLNm.cjs → index.esm-BiAaAUFC.cjs} +8 -8
- package/dist/cli-chunks/{login-DolpqD8K.cjs → login-B3TThMss.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-1rvkK-M8.cjs → project-vite-BQj8YLI4.cjs} +1 -1
- package/dist/cli-chunks/{remote-rIAQE_G2.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-CzaM2Cq3.cjs → session-DjBkjaF8.cjs} +1 -1
- package/dist/cli-chunks/{skill-CM40_9WH.cjs → skill-cR_wnaw2.cjs} +2 -2
- package/dist/cli-chunks/{version-Bz-AfXQU.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-CeP6SLB3.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-BwV7bm4n.js +5 -0
- package/dist/devtools/browser-dev-host/index.html +3 -3
- package/dist/index.cjs.js +100 -2
- package/dist/index.esm.js +100 -2
- package/dist/protocol.cjs.js +189 -47
- package/dist/protocol.esm.js +189 -47
- package/dist/templates/{vue3-vite-ts → vanilla-vite-js}/.gitignore.ejs +0 -1
- package/dist/templates/vanilla-vite-js/README.md.ejs +14 -0
- package/dist/templates/vanilla-vite-js/index.html.ejs +20 -0
- package/dist/templates/vanilla-vite-js/package.json.ejs +22 -0
- package/dist/templates/vanilla-vite-js/src/assets/heybox-logo.svg +8 -0
- package/dist/templates/vanilla-vite-js/src/main.js +39 -0
- package/dist/templates/vanilla-vite-js/src/styles.css +155 -0
- package/dist/templates/{vue3-vite-ts/vite.config.ts → vanilla-vite-js/vite.config.js} +1 -2
- package/dist/vite.cjs.js +281 -13
- package/dist/vite.esm.js +281 -13
- package/package.json +13 -9
- package/skill/SKILL.md +8 -9
- package/skill/references/api-protocol.md +1 -3
- package/skill/references/api-root.md +65 -21
- package/skill/references/cli.md +17 -5
- package/skill/references/examples.md +3 -3
- package/skill/references/recipes.md +40 -41
- 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/modules/share/index.d.ts +1 -1
- package/types/modules/share/show-share-menu.d.ts +1 -1
- package/types/modules/share/types.d.ts +2 -4
- package/types/vite/index.d.ts +3 -1
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-uq-Wac6k.js +0 -97
- package/dist/devtools/browser-dev-host/assets/index-KD2f3Jdz.css +0 -1
- package/dist/devtools/browser-dev-host/assets/workbench-state-D-1U0JRq.js +0 -5
- package/dist/templates/vue3-vite-ts/README.md.ejs +0 -47
- package/dist/templates/vue3-vite-ts/index.html.ejs +0 -12
- package/dist/templates/vue3-vite-ts/package.json.ejs +0 -33
- package/dist/templates/vue3-vite-ts/src/App.vue +0 -78
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +0 -148
- package/dist/templates/vue3-vite-ts/src/auth-handoff.ts +0 -46
- package/dist/templates/vue3-vite-ts/src/main.ts +0 -5
- package/dist/templates/vue3-vite-ts/src/styles.css +0 -60
- package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +0 -1
- package/dist/templates/vue3-vite-ts/tsconfig.app.json +0 -17
- package/dist/templates/vue3-vite-ts/tsconfig.json +0 -11
- package/dist/templates/vue3-vite-ts/tsconfig.node.json +0 -11
- package/dist/templates/vue3-vite-ts/vitest.config.ts +0 -10
package/dist/vite.esm.js
CHANGED
|
@@ -5,7 +5,30 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
5
5
|
/** 构建时替换为当前发布包的实际版本。 */
|
|
6
6
|
const HB_SDK_VERSION = typeof undefined === 'string'
|
|
7
7
|
? undefined
|
|
8
|
-
: '0.8.0
|
|
8
|
+
: '0.8.0';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* iframe 与调试台页面的开发期 console 捕获转发。
|
|
12
|
+
*
|
|
13
|
+
* 双条件门控(iframe 转发):
|
|
14
|
+
* 1. 构建期:`hb-sdk dev`(vite serve)注入 `false`;`hb-sdk build` /
|
|
15
|
+
* `vite build`(生产)永不注入或替换为 `false`,本模块被死代码消除。
|
|
16
|
+
* 2. 运行期:仅在 `window.name` 为 `__hb_sdk_mini_dev__` 的调试 iframe 中激活,
|
|
17
|
+
* 用户设备上的正式运行环境没有该标记。
|
|
18
|
+
*
|
|
19
|
+
* 无侵入 patch `console.log/debug/info/warn/error`:原样放行(DevTools 不受影响)+
|
|
20
|
+
* 通过 `window.parent.postMessage` 转发给调试台(CSP 的 connect-src 不约束 postMessage,
|
|
21
|
+
* 网络上报由调试台页面代理)。发送全程静默:失败不得回打 console,避免自触发死循环。
|
|
22
|
+
*
|
|
23
|
+
* 激活时机:由 SDK 默认单例初始化时调用(业务 `import '@heybox/hb-sdk'` 即生效);
|
|
24
|
+
* iframe 标记由调试台 `iframe.name` 与 vite dev 注入的无依赖 bootstrap 共同设置。
|
|
25
|
+
* 调试台页面自身(runtime 跑在这里,`[hb-sdk-runtime]` 日志不经过 iframe)另用
|
|
26
|
+
* `installMiniDevConsoleSelfCapture` 接入「日志」页签(source: 'host')。
|
|
27
|
+
*/
|
|
28
|
+
const MINI_DEV_IFRAME_WINDOW_NAME = '__hb_sdk_mini_dev__';
|
|
29
|
+
const MINI_DEV_CONSOLE_EVENT_TYPE = 'hb-sdk:mini-dev-console';
|
|
30
|
+
/** 调试台页面与 iframe bootstrap 共用的已安装标记(window/console 上的属性名)。 */
|
|
31
|
+
const MINI_DEV_CONSOLE_INSTALL_FLAG = '__hb_sdk_mini_dev_console_installed__';
|
|
9
32
|
|
|
10
33
|
var re = {exports: {}};
|
|
11
34
|
|
|
@@ -2792,6 +2815,197 @@ function requireSemver () {
|
|
|
2792
2815
|
|
|
2793
2816
|
var semverExports = requireSemver();
|
|
2794
2817
|
|
|
2818
|
+
const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
|
|
2819
|
+
const MINI_PROGRAM_MESSAGE_VERSION = 2;
|
|
2820
|
+
const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
|
|
2821
|
+
|
|
2822
|
+
const MINI_PROGRAM_PERMISSION_KEYS = [
|
|
2823
|
+
'userInfo',
|
|
2824
|
+
'steamLibrary',
|
|
2825
|
+
'share',
|
|
2826
|
+
'storage',
|
|
2827
|
+
'filesystem',
|
|
2828
|
+
'clipboard',
|
|
2829
|
+
'leaderboard',
|
|
2830
|
+
'network',
|
|
2831
|
+
];
|
|
2832
|
+
const MINI_PROGRAM_PERMISSION_CATALOG = [
|
|
2833
|
+
{
|
|
2834
|
+
key: 'userInfo',
|
|
2835
|
+
name: '用户信息',
|
|
2836
|
+
description: '登录小程序并读取当前用户的授权信息。',
|
|
2837
|
+
access: 'declaration',
|
|
2838
|
+
risk: 'medium',
|
|
2839
|
+
config: {},
|
|
2840
|
+
methods: ['auth.login', 'user.getInfo'],
|
|
2841
|
+
conditions: ['继续执行黑盒登录、用户授权和可信手势规则。'],
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
key: 'steamLibrary',
|
|
2845
|
+
name: 'Steam 游戏库',
|
|
2846
|
+
description: '读取当前用户授权的 Steam 游戏库。',
|
|
2847
|
+
access: 'declaration',
|
|
2848
|
+
risk: 'high',
|
|
2849
|
+
config: {},
|
|
2850
|
+
methods: ['user.getSteamGameList'],
|
|
2851
|
+
conditions: ['继续执行账号绑定和数据可用性规则。'],
|
|
2852
|
+
},
|
|
2853
|
+
{
|
|
2854
|
+
key: 'share',
|
|
2855
|
+
name: '分享',
|
|
2856
|
+
description: '使用小程序分享、分享菜单和截图能力。',
|
|
2857
|
+
access: 'declaration',
|
|
2858
|
+
risk: 'medium',
|
|
2859
|
+
config: {},
|
|
2860
|
+
methods: ['share.copyLink', 'share.showShareMenu', 'share.screenshot'],
|
|
2861
|
+
conditions: ['继续执行分享参数校验和 Host 支持检查。'],
|
|
2862
|
+
},
|
|
2863
|
+
{
|
|
2864
|
+
key: 'storage',
|
|
2865
|
+
name: '键值存储',
|
|
2866
|
+
description: '读写按小程序隔离的简单键值数据。',
|
|
2867
|
+
access: 'declaration',
|
|
2868
|
+
risk: 'medium',
|
|
2869
|
+
config: {},
|
|
2870
|
+
methods: ['storage.getStorage', 'storage.setStorage'],
|
|
2871
|
+
conditions: ['仅用于简单键值存储,不包含文件系统。'],
|
|
2872
|
+
},
|
|
2873
|
+
{
|
|
2874
|
+
key: 'filesystem',
|
|
2875
|
+
name: '文件系统',
|
|
2876
|
+
description: '访问小程序沙盒文件和用户选择的外部文件。',
|
|
2877
|
+
access: 'declaration',
|
|
2878
|
+
risk: 'high',
|
|
2879
|
+
config: {},
|
|
2880
|
+
methods: [
|
|
2881
|
+
'network.download',
|
|
2882
|
+
'files.pickFiles',
|
|
2883
|
+
'files.pickDirectory',
|
|
2884
|
+
'files.saveFile',
|
|
2885
|
+
'file.create',
|
|
2886
|
+
'file.remove',
|
|
2887
|
+
'file.exists',
|
|
2888
|
+
'file.readText',
|
|
2889
|
+
'file.writeText',
|
|
2890
|
+
'file.readBytes',
|
|
2891
|
+
'file.writeBytes',
|
|
2892
|
+
'file.stat',
|
|
2893
|
+
'directory.create',
|
|
2894
|
+
'directory.remove',
|
|
2895
|
+
'directory.exists',
|
|
2896
|
+
'directory.list',
|
|
2897
|
+
],
|
|
2898
|
+
conditions: ['外部文件继续要求有效的用户选择、会话句柄和匹配的读写模式。'],
|
|
2899
|
+
},
|
|
2900
|
+
{
|
|
2901
|
+
key: 'clipboard',
|
|
2902
|
+
name: '剪贴板',
|
|
2903
|
+
description: '向系统剪贴板写入文本。',
|
|
2904
|
+
access: 'declaration',
|
|
2905
|
+
risk: 'medium',
|
|
2906
|
+
config: {},
|
|
2907
|
+
methods: ['device.setClipboard'],
|
|
2908
|
+
conditions: ['继续执行文本长度和 Host 支持限制。'],
|
|
2909
|
+
},
|
|
2910
|
+
{
|
|
2911
|
+
key: 'leaderboard',
|
|
2912
|
+
name: '排行榜',
|
|
2913
|
+
description: '读写小程序云排行榜。',
|
|
2914
|
+
access: 'declaration',
|
|
2915
|
+
risk: 'medium',
|
|
2916
|
+
config: {},
|
|
2917
|
+
methods: [
|
|
2918
|
+
'cloud.leaderboard.submit',
|
|
2919
|
+
'cloud.leaderboard.getList',
|
|
2920
|
+
'cloud.leaderboard.getCurrentUserEntry',
|
|
2921
|
+
'cloud.leaderboard.deleteCurrentUserEntry',
|
|
2922
|
+
'cloud.leaderboard.getInfo',
|
|
2923
|
+
],
|
|
2924
|
+
conditions: ['排行榜必须已创建,用户和资源规则保持不变。'],
|
|
2925
|
+
},
|
|
2926
|
+
{
|
|
2927
|
+
key: 'network',
|
|
2928
|
+
name: '网络',
|
|
2929
|
+
description: '通过 network 模块请求或下载外部资源。',
|
|
2930
|
+
access: 'platform-approval',
|
|
2931
|
+
risk: 'high',
|
|
2932
|
+
config: {
|
|
2933
|
+
useOfficialDomain: {
|
|
2934
|
+
type: 'boolean',
|
|
2935
|
+
required: false,
|
|
2936
|
+
default: false,
|
|
2937
|
+
description: '是否申请访问小黑盒官方域名。',
|
|
2938
|
+
},
|
|
2939
|
+
},
|
|
2940
|
+
methods: ['network.request', 'network.download'],
|
|
2941
|
+
conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
|
|
2942
|
+
},
|
|
2943
|
+
];
|
|
2944
|
+
new Set(MINI_PROGRAM_PERMISSION_KEYS);
|
|
2945
|
+
|
|
2946
|
+
new Set(MINI_PROGRAM_PERMISSION_KEYS);
|
|
2947
|
+
|
|
2948
|
+
const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
|
|
2949
|
+
function parseMiniappPermissions(value, options) {
|
|
2950
|
+
const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
|
|
2951
|
+
if (!options.present) {
|
|
2952
|
+
if (requiresExplicitPermissions(options.sdkVersion)) {
|
|
2953
|
+
throw new Error(`${sourceLabel} 在 @heybox/hb-sdk ${options.sdkVersion} 中必须声明;无权限需求时请配置空对象 {}`);
|
|
2954
|
+
}
|
|
2955
|
+
return { declared: false };
|
|
2956
|
+
}
|
|
2957
|
+
if (!isRecord$1(value)) {
|
|
2958
|
+
throw new Error(`${sourceLabel} 必须是 JSON 对象`);
|
|
2959
|
+
}
|
|
2960
|
+
const knownKeys = new Set(MINIAPP_PERMISSION_KEYS);
|
|
2961
|
+
for (const key of Object.keys(value)) {
|
|
2962
|
+
if (!knownKeys.has(key))
|
|
2963
|
+
throw new Error(`${sourceLabel} 包含未知权限:${key}`);
|
|
2964
|
+
}
|
|
2965
|
+
const permissions = {};
|
|
2966
|
+
for (const key of MINIAPP_PERMISSION_KEYS) {
|
|
2967
|
+
if (!Object.prototype.hasOwnProperty.call(value, key))
|
|
2968
|
+
continue;
|
|
2969
|
+
const declaration = value[key];
|
|
2970
|
+
const itemLabel = `${sourceLabel}.${key}`;
|
|
2971
|
+
if (!isRecord$1(declaration))
|
|
2972
|
+
throw new Error(`${itemLabel} 必须是 JSON 对象`);
|
|
2973
|
+
const definition = MINI_PROGRAM_PERMISSION_CATALOG.find((item) => item.key === key);
|
|
2974
|
+
if (!definition)
|
|
2975
|
+
throw new Error(`权限目录缺少定义:${key}`);
|
|
2976
|
+
const allowedFields = new Set(['enabled', ...Object.keys(definition.config)]);
|
|
2977
|
+
for (const field of Object.keys(declaration)) {
|
|
2978
|
+
if (!allowedFields.has(field))
|
|
2979
|
+
throw new Error(`${itemLabel} 包含未知字段:${field}`);
|
|
2980
|
+
}
|
|
2981
|
+
if (typeof declaration.enabled !== 'boolean')
|
|
2982
|
+
throw new Error(`${itemLabel}.enabled 必须是 boolean`);
|
|
2983
|
+
let useOfficialDomain = false;
|
|
2984
|
+
if (key === 'network') {
|
|
2985
|
+
if (declaration.useOfficialDomain !== undefined && typeof declaration.useOfficialDomain !== 'boolean') {
|
|
2986
|
+
throw new Error(`${itemLabel}.useOfficialDomain 必须是 boolean`);
|
|
2987
|
+
}
|
|
2988
|
+
useOfficialDomain = declaration.useOfficialDomain === true;
|
|
2989
|
+
}
|
|
2990
|
+
if (!declaration.enabled)
|
|
2991
|
+
continue;
|
|
2992
|
+
permissions[key] = key === 'network' ? { enabled: true, useOfficialDomain } : { enabled: true };
|
|
2993
|
+
}
|
|
2994
|
+
return { declared: true, permissions: permissions };
|
|
2995
|
+
}
|
|
2996
|
+
function requiresExplicitPermissions(sdkVersion) {
|
|
2997
|
+
const parsed = semverExports.parse(sdkVersion);
|
|
2998
|
+
if (!parsed)
|
|
2999
|
+
throw new Error(`sdkVersion 必须是合法 SemVer:${sdkVersion}`);
|
|
3000
|
+
return parsed.major > 0 || parsed.minor >= 9;
|
|
3001
|
+
}
|
|
3002
|
+
function getMissingPermissionsWarning(sourceLabel = 'package.json#heybox.permissions') {
|
|
3003
|
+
return `${sourceLabel} 尚未声明。当前按 0.8 兼容行为构建;0.9.0 起将拒绝构建,请尽快补充权限声明(无权限需求时配置 {})。`;
|
|
3004
|
+
}
|
|
3005
|
+
function isRecord$1(value) {
|
|
3006
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3007
|
+
}
|
|
3008
|
+
|
|
2795
3009
|
const MINIAPP_PLATFORM_VALUES = ['android', 'ios', 'ohos', 'windows', 'macos', 'linux'];
|
|
2796
3010
|
function validateMiniappPackageVersionForBuild(version) {
|
|
2797
3011
|
return validateMiniappManifestVersion(version, 'package.json.version');
|
|
@@ -2805,7 +3019,13 @@ function validateMiniappManifestVersion(version, sourceLabel = 'manifest.version
|
|
|
2805
3019
|
}
|
|
2806
3020
|
function renderMiniappManifest(manifest) {
|
|
2807
3021
|
const platforms = validateMiniappPlatforms(manifest.platforms, 'manifest.platforms');
|
|
2808
|
-
|
|
3022
|
+
const output = {
|
|
3023
|
+
version: manifest.version,
|
|
3024
|
+
sdkVersion: manifest.sdkVersion,
|
|
3025
|
+
platforms,
|
|
3026
|
+
...(manifest.permissions === undefined ? {} : { permissions: manifest.permissions }),
|
|
3027
|
+
};
|
|
3028
|
+
return `${JSON.stringify(output, null, 2)}\n`;
|
|
2809
3029
|
}
|
|
2810
3030
|
function validateMiniappPlatforms(platforms, sourceLabel = 'platforms') {
|
|
2811
3031
|
if (!Array.isArray(platforms) || platforms.length === 0) {
|
|
@@ -2860,6 +3080,21 @@ function findNearestPackageJsonPath(startDir) {
|
|
|
2860
3080
|
}
|
|
2861
3081
|
}
|
|
2862
3082
|
function readMiniappVersionFromPackageJson(root) {
|
|
3083
|
+
return readMiniappPackageJson(root, true).version;
|
|
3084
|
+
}
|
|
3085
|
+
function readMiniappPermissionsFromPackageJson(root, sdkVersion) {
|
|
3086
|
+
const { packageJson } = readMiniappPackageJson(root, false);
|
|
3087
|
+
const heybox = packageJson.heybox;
|
|
3088
|
+
if (heybox !== undefined && !isRecord(heybox)) {
|
|
3089
|
+
throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
|
|
3090
|
+
}
|
|
3091
|
+
const present = isRecord(heybox) && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
|
|
3092
|
+
return parseMiniappPermissions(isRecord(heybox) ? heybox.permissions : undefined, {
|
|
3093
|
+
present,
|
|
3094
|
+
sdkVersion,
|
|
3095
|
+
});
|
|
3096
|
+
}
|
|
3097
|
+
function readMiniappPackageJson(root, requireVersion) {
|
|
2863
3098
|
const packageJsonPath = findNearestPackageJsonPath(root);
|
|
2864
3099
|
let content;
|
|
2865
3100
|
try {
|
|
@@ -2875,10 +3110,13 @@ function readMiniappVersionFromPackageJson(root) {
|
|
|
2875
3110
|
catch (error) {
|
|
2876
3111
|
throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
|
|
2877
3112
|
}
|
|
2878
|
-
if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
|
|
3113
|
+
if (requireVersion && (typeof packageJson.version !== 'string' || packageJson.version.trim() === '')) {
|
|
2879
3114
|
throw new Error('@heybox/hb-sdk 提示:package.json.version 必须是非空字符串');
|
|
2880
3115
|
}
|
|
2881
|
-
return packageJson.version.trim();
|
|
3116
|
+
return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
|
|
3117
|
+
}
|
|
3118
|
+
function isRecord(value) {
|
|
3119
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
2882
3120
|
}
|
|
2883
3121
|
function formatReason(error) {
|
|
2884
3122
|
if (error instanceof Error && error.message) {
|
|
@@ -11317,10 +11555,6 @@ function parse(html, options) {
|
|
|
11317
11555
|
return Parser.parse(html, options);
|
|
11318
11556
|
}
|
|
11319
11557
|
|
|
11320
|
-
const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
|
|
11321
|
-
const MINI_PROGRAM_MESSAGE_VERSION = 2;
|
|
11322
|
-
const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
|
|
11323
|
-
|
|
11324
11558
|
const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
11325
11559
|
const RUNTIME_GATE_MARKER = 'data-heybox-runtime-gate';
|
|
11326
11560
|
const RUNTIME_GATE_STYLE_MARKER = 'data-heybox-runtime-gate-style';
|
|
@@ -11643,8 +11877,29 @@ function shouldSkipMiniappPlatformCspFromEnv(env = process.env) {
|
|
|
11643
11877
|
return env[HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV] === VERIFIED_RUNTIME_PERMISSION_CONTEXT && env[HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV] === '1';
|
|
11644
11878
|
}
|
|
11645
11879
|
|
|
11880
|
+
/**
|
|
11881
|
+
* dev serve 时在入口 HTML 最早位置注入无依赖 console 捕获 bootstrap。
|
|
11882
|
+
*
|
|
11883
|
+
* 必须内联完整 patch 逻辑而非等 SDK 模块加载:vite client、业务代码的 console 调用
|
|
11884
|
+
* 都可能早于 SDK 单例初始化(如 [vite] connecting)。捕获条件:
|
|
11885
|
+
* 1. 构建期只有 vite serve 走到本分支(生产构建无此代码,双保险之 define 常量仍注入给 SDK 侧);
|
|
11886
|
+
* 2. 运行期仅调试 iframe(window.name 标记由调试台 iframe.name 与本 bootstrap 设置)激活。
|
|
11887
|
+
* 转发经 window.parent.postMessage(CSP connect-src 不约束 postMessage),失败静默,
|
|
11888
|
+
* 严禁回打 console 造成自触发循环。SDK 侧 installMiniDevConsoleForwarding 安装时
|
|
11889
|
+
* 检测同款 INSTALL_FLAG,不会重复 patch。
|
|
11890
|
+
*/
|
|
11891
|
+
function injectMiniDevConsoleBootstrap(html) {
|
|
11892
|
+
const bootstrap = `<script>(function(){var LEVELS=['log','debug','info','warn','error'];var FLAG='${MINI_DEV_CONSOLE_INSTALL_FLAG}';var TYPE='${MINI_DEV_CONSOLE_EVENT_TYPE}';if(window.name!=='${MINI_DEV_IFRAME_WINDOW_NAME}')window.name='${MINI_DEV_IFRAME_WINDOW_NAME}';if(window[FLAG])return;var patched=false;for(var i=0;i<LEVELS.length;i++)(function(level){var original=console[level];if(typeof original!=='function')return;console[level]=function(){try{parent.postMessage({type:TYPE,detail:{level:level,args:Array.prototype.slice.call(arguments),timestamp:Date.now()}},'*')}catch(e){}return original.apply(this,arguments)};patched=true})(LEVELS[i]);if(patched)window[FLAG]=true})();</script>`;
|
|
11893
|
+
const headIndex = html.indexOf('<head>');
|
|
11894
|
+
if (headIndex < 0) {
|
|
11895
|
+
return html;
|
|
11896
|
+
}
|
|
11897
|
+
const insertAt = headIndex + '<head>'.length;
|
|
11898
|
+
return `${html.slice(0, insertAt)}${bootstrap}${html.slice(insertAt)}`;
|
|
11899
|
+
}
|
|
11646
11900
|
const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
|
|
11647
11901
|
const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
|
|
11902
|
+
const miniDevLoggingConstant = ['__HB_SDK_DEV', 'LOGGING__'].join('_');
|
|
11648
11903
|
function miniappManifest(options) {
|
|
11649
11904
|
const platforms = validateMiniappPlatforms(options?.platforms, 'miniappManifest().platforms');
|
|
11650
11905
|
const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
|
|
@@ -11656,12 +11911,17 @@ function miniappManifest(options) {
|
|
|
11656
11911
|
let priorBuildError;
|
|
11657
11912
|
return {
|
|
11658
11913
|
name: 'heybox-miniapp-manifest',
|
|
11659
|
-
config(config) {
|
|
11914
|
+
config(config, env) {
|
|
11660
11915
|
assertMiniappViteBase(config.base);
|
|
11916
|
+
// command 在本钩子时序早于 configResolved,必须取自 env 命令而非闭包;
|
|
11917
|
+
// 旧调用方(测试等)未传 env 时按 build 处理。
|
|
11918
|
+
const isServe = env?.command === 'serve';
|
|
11661
11919
|
return {
|
|
11662
11920
|
...(config.base === undefined ? { base: './' } : {}),
|
|
11663
11921
|
define: {
|
|
11664
11922
|
[sdkVersionBuildConstant]: JSON.stringify(resolveSdkVersion()),
|
|
11923
|
+
// 仅 vite serve(hb-sdk dev)注入;vite build / hb-sdk build 永不注入,捕获模块被死代码消除。
|
|
11924
|
+
...(isServe ? { [miniDevLoggingConstant]: 'true' } : {}),
|
|
11665
11925
|
},
|
|
11666
11926
|
};
|
|
11667
11927
|
},
|
|
@@ -11683,12 +11943,12 @@ function miniappManifest(options) {
|
|
|
11683
11943
|
}
|
|
11684
11944
|
},
|
|
11685
11945
|
transformIndexHtml(html) {
|
|
11686
|
-
|
|
11946
|
+
const enforced = enforceMiniappHtmlPolicy(html, {
|
|
11687
11947
|
...(command === 'serve' ? { hmrWebSocketUrl } : {}),
|
|
11688
11948
|
skipPlatformCsp,
|
|
11689
11949
|
});
|
|
11690
|
-
|
|
11691
|
-
async closeBundle() {
|
|
11950
|
+
return command === 'serve' ? injectMiniDevConsoleBootstrap(enforced) : enforced;
|
|
11951
|
+
}, async closeBundle() {
|
|
11692
11952
|
// Rollup 在 buildStart/transform 失败后仍会调用 closeBundle。
|
|
11693
11953
|
// 若此时再抛「缺 index.html」等二次错误,会掩盖真实失败原因。
|
|
11694
11954
|
if (priorBuildError) {
|
|
@@ -11696,6 +11956,9 @@ function miniappManifest(options) {
|
|
|
11696
11956
|
}
|
|
11697
11957
|
const version = validateMiniappPackageVersionForBuild(readMiniappVersionFromPackageJson(root));
|
|
11698
11958
|
const sdkVersion = resolveSdkVersion();
|
|
11959
|
+
const parsedPermissions = readMiniappPermissionsFromPackageJson(root, sdkVersion);
|
|
11960
|
+
if (!parsedPermissions.declared)
|
|
11961
|
+
this.warn(getMissingPermissionsWarning());
|
|
11699
11962
|
const outputRoot = path.resolve(root, outDir);
|
|
11700
11963
|
const htmlFiles = collectHtmlFiles(outputRoot);
|
|
11701
11964
|
const unexpectedHtmlFiles = htmlFiles.filter((file) => path.relative(outputRoot, file) !== 'index.html');
|
|
@@ -11711,7 +11974,12 @@ function miniappManifest(options) {
|
|
|
11711
11974
|
writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(readFileSync(indexHtmlPath, 'utf8'), { skipPlatformCsp }));
|
|
11712
11975
|
const manifestPath = path.join(outputRoot, 'manifest.json');
|
|
11713
11976
|
mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
11714
|
-
writeFileSync(manifestPath, renderMiniappManifest({
|
|
11977
|
+
writeFileSync(manifestPath, renderMiniappManifest({
|
|
11978
|
+
version,
|
|
11979
|
+
sdkVersion,
|
|
11980
|
+
platforms,
|
|
11981
|
+
...(parsedPermissions.permissions === undefined ? {} : { permissions: parsedPermissions.permissions }),
|
|
11982
|
+
}));
|
|
11715
11983
|
},
|
|
11716
11984
|
};
|
|
11717
11985
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heybox/hb-sdk",
|
|
3
|
-
"version": "0.8.0
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"./src/index.ts",
|
|
6
6
|
"./src/core/singleton.ts",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"skills": "1.5.23",
|
|
63
63
|
"undici": "^7.28.0",
|
|
64
64
|
"ws": "^8.18.0",
|
|
65
|
-
"@heybox/hb-sdk-protocol": "0.8.0
|
|
65
|
+
"@heybox/hb-sdk-protocol": "0.8.0"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"vite": ">=5"
|
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
"get-port": "^7.1.0",
|
|
98
98
|
"happy-dom": "^19.0.2",
|
|
99
99
|
"lucide-vue-next": "1.0.0",
|
|
100
|
+
"markdown-it": "^14.1.0",
|
|
100
101
|
"open": "^10.2.0",
|
|
101
102
|
"ora": "^5.4.1",
|
|
102
103
|
"picocolors": "^1.1.1",
|
|
@@ -113,12 +114,12 @@
|
|
|
113
114
|
"vite": "^8.0.12",
|
|
114
115
|
"vitest": "^3.2.4",
|
|
115
116
|
"@heybox-domain/heybox-theme": "~0.1.0",
|
|
116
|
-
"@heybox
|
|
117
|
-
"@heybox/hb-sdk-runtime": "~0.8.0
|
|
118
|
-
"@heybox/
|
|
117
|
+
"@heybox/hb-api": "~1.28.2",
|
|
118
|
+
"@heybox/hb-sdk-runtime": "~0.8.0",
|
|
119
|
+
"@heybox/runtime": "~0.2.0",
|
|
119
120
|
"@heybox/runtime-policy": "~0.2.0",
|
|
120
|
-
"@heybox/
|
|
121
|
-
"@heybox/runtime": "~0.2.0"
|
|
121
|
+
"@heybox-domain/heybox-vue3-ui": "~0.1.0",
|
|
122
|
+
"@heybox/runtime-transport-fetch": "~0.2.0"
|
|
122
123
|
},
|
|
123
124
|
"publishConfig": {
|
|
124
125
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -175,18 +176,21 @@
|
|
|
175
176
|
"test:types:browser-dev-host": "vue-tsc -p tsconfig.browser-dev-host.json --noEmit --pretty false",
|
|
176
177
|
"test:types": "pnpm run test:types:characterization && pnpm run test:types:browser-dev-host",
|
|
177
178
|
"test:e2e:browser-dev-host": "pnpm run build:browser-dev-host && NODE_OPTIONS='--conditions=heybox' vitest run --config vitest.browser-dev-host-e2e.config.ts",
|
|
179
|
+
"test:create-template:artifact": "node scripts/test-create-template-artifact.mjs",
|
|
178
180
|
"test:unit:coverage": "NODE_OPTIONS='--conditions=heybox' vitest run --coverage",
|
|
179
181
|
"test:vite": "pnpm run build:hb-sdk-protocol && pnpm run build:hb-api-contract && vitest run --config vitest.vite.config.ts",
|
|
180
182
|
"test:watch": "NODE_OPTIONS='--conditions=heybox' vitest",
|
|
181
183
|
"changelog:draft": "node scripts/changelog-draft.cjs",
|
|
182
184
|
"check:changelog": "node scripts/check-changelog.cjs",
|
|
183
185
|
"release:verify-tarball": "node scripts/skill/verify-tarball-install.mjs",
|
|
184
|
-
"test:release": "node --test scripts/release-family.test.cjs ../../ops/jobs/publish-changed-packages/publish.test.cjs ../../ops/jobs/release-hb-sdk/docs-release-contract.test.cjs",
|
|
186
|
+
"test:release": "node --test scripts/public-changelog.test.mjs scripts/public-changelog-workflow.test.cjs scripts/release-family.test.cjs ../../ops/jobs/publish-changed-packages/publish.test.cjs ../../ops/jobs/release-hb-sdk/docs-release-contract.test.cjs ../../ops/jobs/release-hb-sdk/stable-promote-coordinator.test.cjs",
|
|
185
187
|
"test:compatibility-evidence": "node --test scripts/validate-compatibility-evidence.test.mjs",
|
|
186
188
|
"release:prepare": "node scripts/release-prepare.cjs",
|
|
187
189
|
"release:tag": "node scripts/release-tag.cjs",
|
|
188
190
|
"release:family:dry-run": "node ../../ops/jobs/publish-changed-packages/publish.cjs --dry-run",
|
|
189
191
|
"release:family:promote": "node ../../ops/jobs/publish-changed-packages/publish.cjs --family-action promote",
|
|
190
|
-
"release:family:rollback": "node ../../ops/jobs/publish-changed-packages/publish.cjs --family-action rollback"
|
|
192
|
+
"release:family:rollback": "node ../../ops/jobs/publish-changed-packages/publish.cjs --family-action rollback",
|
|
193
|
+
"release:stable:promote": "node ../../ops/jobs/release-hb-sdk/stable-promote-coordinator.cjs --action promote",
|
|
194
|
+
"release:stable:rollback": "node ../../ops/jobs/release-hb-sdk/stable-promote-coordinator.cjs --action rollback"
|
|
191
195
|
}
|
|
192
196
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -39,20 +39,19 @@ Apply these instructions when writing, reviewing, or debugging code that consume
|
|
|
39
39
|
## Step 4: Implement workshop mini-program code
|
|
40
40
|
|
|
41
41
|
1. Import the root package eagerly; the SDK starts its handshake automatically and capability calls wait for it internally.
|
|
42
|
-
2.
|
|
43
|
-
3.
|
|
44
|
-
4.
|
|
42
|
+
2. Declare protected capabilities in `package.json#heybox.permissions`. `auth.login()` and `user.getInfo()` require `userInfo`; `user.getSteamGameList()` requires `steamLibrary`; none of them implicitly require the public `network` permission.
|
|
43
|
+
3. Use `auth.login({ scopes? })` to obtain `{ code, expiresIn: 300, scopes }`. Identity is always implicit; request only optional scopes the business actually needs.
|
|
44
|
+
4. Send the code only to the developer's backend. That backend follows the backend OpenAPI documentation to exchange it for a token; mini-program code must never exchange application credentials itself.
|
|
45
45
|
5. Handle `HbMiniProgramSDKError` for SDK initialization and capability failures.
|
|
46
46
|
6. Handle `HbMiniProgramNetworkError` separately when HTTP completed but `validateStatus` rejected the status.
|
|
47
47
|
7. Use `getHandshakeState()` for the current persistent handshake state and `onHandshakeStateChange()` for an immediate replay plus future changes. Cancel the returned subscription when the page or component unmounts.
|
|
48
48
|
8. Treat the non-replayed `ready` lifecycle event only as an edge notification. After a duplicate handshake it may repeat, so never use it as state or as the source for enabling a late-mounted control.
|
|
49
49
|
9. Use the default SDK instance exposed by the root package. For gesture-gated controls, initialize from the current handshake state, subscribe to changes, and enable the control only when `status === 'ready'`. Keep calls such as `auth.login()` in the original user-action callback; do not wait for handshake inside that callback.
|
|
50
50
|
10. When authorization UI is required, call `auth.login()` from a trusted user action. Missing gesture returns `USER_GESTURE_REQUIRED`; cancelling, rejecting, or closing returns `AUTHORIZATION_CANCELLED` and does not confirm or change authorization. An already-authorized `auth.login()` request may return a new code silently.
|
|
51
|
-
11. `
|
|
52
|
-
12. Use `share.showShareMenu({
|
|
53
|
-
13.
|
|
54
|
-
14.
|
|
55
|
-
15. Use `network.download()` only with an SDK-created File/Directory target. It is GET-only, does not follow redirects, and exposes local `AbortSignal` / progress callbacks without sending functions over the bridge. Abort is a cancellation intent; a Host commit that already won still resolves successfully.
|
|
51
|
+
11. Use `share.showShareMenu({ post })` or `share.screenshot({ post })` to preset editable community destinations and topics. Pass partition IDs through `topicIds` and topic text without surrounding `#` through `topics`; do not construct the underlying client post protocol.
|
|
52
|
+
12. Use `share.showShareMenu({ extra })` to open the share menu or `share.copyLink({ extra })` to copy and return the mini-program share link. `share.showShareMenu()` always uses the platform `common_share` landing page and does not accept a custom `url`. Read the JSON-compatible page state synchronously with `share.getExtra()` after launch, validate the developer-defined fields, and fall back to the default page when it returns `undefined`.
|
|
53
|
+
13. New PC enables the retained `files` and `network.download()` contract with persistent sandbox storage, single-file/directory pickers, exact File saving, and public-network streaming downloads. Mobile, Web, Browser Dev Host, and legacy PC return `METHOD_FORBIDDEN` and provide no memory/Blob fallback. Call `files.pickFiles()` / `pickDirectory()` / `saveFile()` only from trusted user actions; `saveFile()` accepts only `suggestedName`, `remove()` only deletes sandbox objects, and non-empty directories require `remove({ recursive: true })`.
|
|
54
|
+
14. Use `network.download()` only with an SDK-created File/Directory target. It is GET-only, does not follow redirects, and exposes local `AbortSignal` / progress callbacks without sending functions over the bridge. Abort is a cancellation intent; a Host commit that already won still resolves successfully.
|
|
56
55
|
|
|
57
56
|
## Step 5: Use CLI workflows
|
|
58
57
|
|
|
@@ -68,7 +67,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
|
|
|
68
67
|
10. Use `hb-sdk remote create` to create and bind a mini-program; use `hb-sdk remote bind <mini-program-id>` to bind an existing manageable mini-program.
|
|
69
68
|
11. Use `hb-sdk remote info`, `hb-sdk remote list`, `hb-sdk remote access`, `hb-sdk remote versions`, `hb-sdk remote preview <version>`, and `hb-sdk remote allowlist ...` for remote inspection and preview management.
|
|
70
69
|
12. Use `hb-sdk remote deploy --release-note <text>` to run the project's `scripts.build`, upload, and submit the current project for audit. Do not recommend the removed top-level `hb-sdk deploy` alias.
|
|
71
|
-
13. `hb-sdk dev` and `hb-sdk remote deploy` skip the platform CSP only when the
|
|
70
|
+
13. `hb-sdk dev` and `hb-sdk remote deploy` skip the platform CSP only when the current version declares and the platform approves `network`. `useOfficialDomain` does not participate in CSP skip decisions. Direct `hb-sdk build`, direct Vite build, anonymous or invalid snapshots, and local Dev Context overrides must keep the platform CSP. Runtime Gate, Manifest, and HTML validation always remain active.
|
|
72
71
|
14. After approval, use `hb-sdk remote release <version>` for manual release or `--auto-publish` when an eligible low-risk version should release automatically.
|
|
73
72
|
15. Treat approval, release, and public display as separate states. Do not promise square, search, or recommendation visibility after release.
|
|
74
73
|
16. Use `hb-sdk remote withdraw`, `hb-sdk remote take-down`, `hb-sdk remote reopen`, and square visibility commands only after showing the target and obtaining required confirmation.
|
|
@@ -284,13 +284,11 @@ Reference 由 `@heybox/hb-sdk` 的公开导出与源码注释自动生成,不
|
|
|
284
284
|
| [Protocol API](#public-protocol-entrypoint) | `@heybox/hb-sdk/protocol` 的协议常量、消息类型与 method 契约。 |
|
|
285
285
|
| [Miniapp Publish API](https://open.xiaoheihe.cn/docs/hb_sdk/reference/miniapp-publish/) | `@heybox/hb-sdk/miniapp-publish` 的构建产物发布前的公开校验工具。 |
|
|
286
286
|
| [Vite API](https://open.xiaoheihe.cn/docs/hb_sdk/reference/vite/) | `@heybox/hb-sdk/vite` 的Vite 工坊小程序插件。 |
|
|
287
|
-
| [Host Runtime 集成](https://docs.xiaoheihe.cn/hb_sdk/reference/runtime/) | `@heybox/hb-sdk-runtime` 的 Host Port、Web Host 与 Runtime 集成入口;声明 Reference 在 Runtime package 内生成。 |
|
|
288
287
|
|
|
289
288
|
## 查询建议
|
|
290
289
|
|
|
291
290
|
- 想查业务接入路径:先看 [Guide](recipes.md)。
|
|
292
291
|
- 想查导出符号:从上方对应公开入口进入分类页。
|
|
293
|
-
- 想接入详情页或 Browser Dev Host:先看 [Host Runtime 集成](https://docs.xiaoheihe.cn/hb_sdk/reference/runtime/),再查 Runtime package 的声明 Reference。
|
|
294
292
|
- 想看场景化用法:优先看 Guide / Recipes 页面中的“进一步阅读”。
|
|
295
293
|
|
|
296
294
|
## 统计
|
|
@@ -302,7 +300,7 @@ Reference 由 `@heybox/hb-sdk` 的公开导出与源码注释自动生成,不
|
|
|
302
300
|
| Miniapp Publish API | 0 | 5 | 2 | 0 | 0 |
|
|
303
301
|
| Vite API | 0 | 1 | 5 | 1 | 1 |
|
|
304
302
|
|
|
305
|
-
<!-- Generated by apps/docs/hb-sdk/scripts/generate-api-docs.ts; schemaVersion=
|
|
303
|
+
<!-- Generated by apps/docs/hb-sdk/scripts/generate-api-docs.ts; schemaVersion=3; fingerprint=660a21ad77c32f30dbc7ebb02b053ebce2a7c6e7301cc805a5cdd1a75572fbb2 -->
|
|
306
304
|
|
|
307
305
|
## SDK API
|
|
308
306
|
|