@heybox/hb-sdk 0.8.1-alpha.1 → 0.8.1-alpha.3

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +32 -3
  3. package/dist/cli-chunks/{build-kMLIWqWY.cjs → build-B5Sbi8Sq.cjs} +13 -9
  4. package/dist/cli-chunks/{context-CzFFRcL4.cjs → context-DuxaBL3Y.cjs} +2 -2
  5. package/dist/cli-chunks/{create-0ow6gA9w.cjs → create-CIfZrg3F.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-CPBPdpyu.cjs → dev-CFubP5kW.cjs} +10 -9
  7. package/dist/cli-chunks/{doctor-DQ8ctFKC.cjs → doctor-IPKn3PBn.cjs} +1 -1
  8. package/dist/cli-chunks/{index-Buner4kE.cjs → index-DCJN-V1y.cjs} +15 -15
  9. package/dist/cli-chunks/{index-RDcIrvwi.cjs → index-KHhdZ8eZ.cjs} +2 -2
  10. package/dist/cli-chunks/{index.esm-qwrdRuy-.cjs → index.esm-8hgZlNF8.cjs} +7 -7
  11. package/dist/cli-chunks/{login-DoduAO_f.cjs → login-CoB9jXxC.cjs} +2 -2
  12. package/dist/cli-chunks/{project-vite-B-sK-qup.cjs → project-vite-DMxdOWsU.cjs} +1 -1
  13. package/dist/cli-chunks/{remote-CF_SRmnj.cjs → remote-D4ZcngLn.cjs} +14 -10
  14. package/dist/cli-chunks/{runtime-gate-FseEYZze.cjs → runtime-gate-BWb8QIcX.cjs} +0 -107
  15. package/dist/cli-chunks/{runtime-permission-env-DdQtxdut.cjs → runtime-permission-env-XAZFauvZ.cjs} +125 -9
  16. package/dist/cli-chunks/{session-DHbw2Xgh.cjs → session-BnoHxzFq.cjs} +1 -1
  17. package/dist/cli-chunks/{skill-6IVv12JW.cjs → skill-CDEJtATn.cjs} +2 -2
  18. package/dist/cli-chunks/{version-TXwWxKvv.cjs → version-BGzCIQhE.cjs} +1 -1
  19. package/dist/cli.cjs +1 -1
  20. package/dist/devtools/browser-dev-host/assets/browser-dev-host-DzEst9n7.js +99 -0
  21. package/dist/devtools/browser-dev-host/assets/{index-C5MZZDa5.js → index-B-NHlLsr.js} +2 -2
  22. package/dist/devtools/browser-dev-host/index.html +1 -1
  23. package/dist/index.cjs.js +83 -2
  24. package/dist/index.esm.js +83 -3
  25. package/dist/templates/vanilla-vite-js/README.md.ejs +1 -1
  26. package/dist/templates/vanilla-vite-js/package.json.ejs +1 -0
  27. package/dist/templates/vanilla-vite-js/vite.config.js +1 -1
  28. package/dist/vite.cjs.js +19 -10
  29. package/dist/vite.esm.js +19 -10
  30. package/package.json +7 -7
  31. package/skill/SKILL.md +5 -2
  32. package/skill/references/api-protocol.md +8 -4
  33. package/skill/references/api-root.md +114 -12
  34. package/skill/references/cli.md +2 -2
  35. package/skill/references/examples.md +9 -1
  36. package/skill/references/recipes.md +1 -0
  37. package/skill/references/safety-boundaries.md +1 -1
  38. package/skill/skill.json +5 -5
  39. package/types/core/client.d.ts +7 -1
  40. package/types/core/sdk.d.ts +3 -0
  41. package/types/core/singleton.d.ts +3 -0
  42. package/types/index.d.ts +3 -1
  43. package/types/miniapp-manifest/node.d.ts +2 -0
  44. package/types/miniapp-manifest/schema.d.ts +1 -0
  45. package/types/modules/environment/index.d.ts +70 -0
  46. package/types/protocol.d.ts +1 -1
  47. package/types/vite/index.d.ts +1 -4
  48. package/dist/devtools/browser-dev-host/assets/browser-dev-host-TzYf9L6C.js +0 -99
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#f4f5f7" />
7
7
  <title>小程序工坊调试台</title>
8
- <script type="module" crossorigin src="/assets/index-C5MZZDa5.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-B-NHlLsr.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/workbench-state-BwV7bm4n.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/index-P-ra4m1y.css">
11
11
  </head>
package/dist/index.cjs.js CHANGED
@@ -799,7 +799,50 @@ function createMessageId() {
799
799
  /** 构建时替换为当前发布包的实际版本。 */
800
800
  const HB_SDK_VERSION = typeof undefined === 'string'
801
801
  ? undefined
802
- : '0.8.1-alpha.1';
802
+ : '0.8.1-alpha.3';
803
+
804
+ const RUNTIME_MODES = new Set(['production', 'preview', 'development', 'unknown']);
805
+ const OPERATING_SYSTEM_NAMES = new Set(['android', 'ios', 'ohos', 'windows', 'macos', 'linux', 'unknown']);
806
+ /** 创建环境信息模块。 */
807
+ function createEnvironmentModule(reader) {
808
+ return {
809
+ getInfo: () => reader.getEnvironmentInfo(),
810
+ getInfoSync: () => reader.getEnvironmentInfoSync(),
811
+ };
812
+ }
813
+ /** 将不可信 wire 值逐字段降级为固定、深度冻结的公开快照。 */
814
+ function normalizeMiniProgramEnvironmentInfo(value) {
815
+ const root = readRecord$1(value);
816
+ const runtime = readRecord$1(root?.runtime);
817
+ const host = readRecord$1(root?.host);
818
+ const miniProgram = readRecord$1(root?.miniProgram);
819
+ const operatingSystem = readRecord$1(root?.operatingSystem);
820
+ return Object.freeze({
821
+ runtime: Object.freeze({
822
+ mode: RUNTIME_MODES.has(runtime?.mode) ? runtime?.mode : 'unknown',
823
+ }),
824
+ host: Object.freeze({
825
+ appVersion: readOptionalString(host?.appVersion),
826
+ }),
827
+ miniProgram: Object.freeze({
828
+ id: readOptionalString(miniProgram?.id),
829
+ version: readOptionalString(miniProgram?.version),
830
+ }),
831
+ operatingSystem: Object.freeze({
832
+ name: OPERATING_SYSTEM_NAMES.has(operatingSystem?.name)
833
+ ? operatingSystem?.name
834
+ : 'unknown',
835
+ version: readOptionalString(operatingSystem?.version),
836
+ }),
837
+ sdk: Object.freeze({ version: HB_SDK_VERSION }),
838
+ });
839
+ }
840
+ function readOptionalString(value) {
841
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
842
+ }
843
+ function readRecord$1(value) {
844
+ return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
845
+ }
803
846
 
804
847
  const DEFAULT_TIMEOUT = 10000;
805
848
  const HANDSHAKE_RETRY_INTERVAL = 250;
@@ -831,6 +874,7 @@ class MiniProgramBridgeClient {
831
874
  destroyed = false;
832
875
  runtimeUnavailable = false;
833
876
  runtimeUnavailableError;
877
+ environmentInfo;
834
878
  constructor(options = {}) {
835
879
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
836
880
  this.selfWindow = options.selfWindow || getGlobalWindow();
@@ -857,6 +901,21 @@ class MiniProgramBridgeClient {
857
901
  onHandshakeStateChange(handler) {
858
902
  return this.handshakeState.subscribe(handler);
859
903
  }
904
+ /** 等待握手后读取当前实例的环境快照。 */
905
+ async getEnvironmentInfo() {
906
+ await this.waitForHandshake();
907
+ return this.getEnvironmentInfoSync();
908
+ }
909
+ /** 同步读取握手期间缓存的环境快照。 */
910
+ getEnvironmentInfoSync() {
911
+ const state = this.handshakeState.getState();
912
+ if (state.status === 'failed')
913
+ throw state.error;
914
+ if (state.status !== 'ready' || !this.environmentInfo) {
915
+ throw createSDKError('ENVIRONMENT_NOT_READY', '环境信息将在 SDK ready 后可用');
916
+ }
917
+ return this.environmentInfo;
918
+ }
860
919
  /** 注册小程序事件监听。 */
861
920
  on(eventName, handler) {
862
921
  return this.eventBus.on(eventName, handler);
@@ -1109,7 +1168,10 @@ class MiniProgramBridgeClient {
1109
1168
  if (eventName === 'unload') {
1110
1169
  this.markRuntimeUnavailable();
1111
1170
  }
1112
- else if (eventName === 'ready' && !this.runtimeUnavailable) {
1171
+ else if (eventName === 'ready' && !this.runtimeUnavailable && this.handshakeState.getState().status !== 'failed') {
1172
+ if (!this.environmentInfo) {
1173
+ this.environmentInfo = normalizeMiniProgramEnvironmentInfo(undefined);
1174
+ }
1113
1175
  this.resolveHandshakeOnce();
1114
1176
  }
1115
1177
  else if (eventName === 'show' && !this.runtimeUnavailable) {
@@ -1118,6 +1180,12 @@ class MiniProgramBridgeClient {
1118
1180
  this.eventBus.emit(eventName, message.payload);
1119
1181
  }
1120
1182
  handleResponse(message) {
1183
+ if (message.method === SDK_HANDSHAKE_METHOD && message.error === undefined) {
1184
+ if (!this.environmentInfo) {
1185
+ this.environmentInfo = normalizeMiniProgramEnvironmentInfo(readRecord(message.payload)?.environment);
1186
+ }
1187
+ return;
1188
+ }
1121
1189
  if (!message.id) {
1122
1190
  return;
1123
1191
  }
@@ -1237,6 +1305,9 @@ class MiniProgramBridgeClient {
1237
1305
  this.pendingRequests.clear();
1238
1306
  }
1239
1307
  }
1308
+ function readRecord(value) {
1309
+ return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
1310
+ }
1240
1311
  function waitForHandshakeOrAbort(handshake, signal, createAbortError, getTerminalError) {
1241
1312
  if (!signal)
1242
1313
  return handshake;
@@ -3691,6 +3762,8 @@ class MiniProgramSDK {
3691
3762
  navigation;
3692
3763
  /** 云端数据相关开放能力。 */
3693
3764
  cloud;
3765
+ /** 当前实例的环境信息。 */
3766
+ environment;
3694
3767
  constructor(options) {
3695
3768
  const launchHref = (options?.selfWindow ?? getGlobalWindow())?.location.href;
3696
3769
  this.client = new MiniProgramBridgeClient(options);
@@ -3705,6 +3778,7 @@ class MiniProgramSDK {
3705
3778
  this.device = createDeviceModule(this.client);
3706
3779
  this.navigation = createNavigationModule(this.client);
3707
3780
  this.cloud = createCloudModule(this.client);
3781
+ this.environment = createEnvironmentModule(this.client);
3708
3782
  }
3709
3783
  /** 获取当前握手状态。 */
3710
3784
  getHandshakeState() {
@@ -4003,6 +4077,11 @@ const cloud = {
4003
4077
  getInfo: (options) => getDefaultSDK().cloud.leaderboard.getInfo(options),
4004
4078
  },
4005
4079
  };
4080
+ /** 默认 SDK 实例的 environment 模块。 */
4081
+ const environment = {
4082
+ getInfo: () => getDefaultSDK().environment.getInfo(),
4083
+ getInfoSync: () => getDefaultSDK().environment.getInfoSync(),
4084
+ };
4006
4085
 
4007
4086
  const hbSDK = {
4008
4087
  getHandshakeState,
@@ -4018,6 +4097,7 @@ const hbSDK = {
4018
4097
  network,
4019
4098
  ui,
4020
4099
  device,
4100
+ environment,
4021
4101
  navigation,
4022
4102
  cloud,
4023
4103
  };
@@ -4029,6 +4109,7 @@ exports.auth = auth;
4029
4109
  exports.cloud = cloud;
4030
4110
  exports.default = hbSDK;
4031
4111
  exports.device = device;
4112
+ exports.environment = environment;
4032
4113
  exports.files = files;
4033
4114
  exports.getHandshakeState = getHandshakeState;
4034
4115
  exports.navigation = navigation;
package/dist/index.esm.js CHANGED
@@ -795,7 +795,50 @@ function createMessageId() {
795
795
  /** 构建时替换为当前发布包的实际版本。 */
796
796
  const HB_SDK_VERSION = typeof undefined === 'string'
797
797
  ? undefined
798
- : '0.8.1-alpha.1';
798
+ : '0.8.1-alpha.3';
799
+
800
+ const RUNTIME_MODES = new Set(['production', 'preview', 'development', 'unknown']);
801
+ const OPERATING_SYSTEM_NAMES = new Set(['android', 'ios', 'ohos', 'windows', 'macos', 'linux', 'unknown']);
802
+ /** 创建环境信息模块。 */
803
+ function createEnvironmentModule(reader) {
804
+ return {
805
+ getInfo: () => reader.getEnvironmentInfo(),
806
+ getInfoSync: () => reader.getEnvironmentInfoSync(),
807
+ };
808
+ }
809
+ /** 将不可信 wire 值逐字段降级为固定、深度冻结的公开快照。 */
810
+ function normalizeMiniProgramEnvironmentInfo(value) {
811
+ const root = readRecord$1(value);
812
+ const runtime = readRecord$1(root?.runtime);
813
+ const host = readRecord$1(root?.host);
814
+ const miniProgram = readRecord$1(root?.miniProgram);
815
+ const operatingSystem = readRecord$1(root?.operatingSystem);
816
+ return Object.freeze({
817
+ runtime: Object.freeze({
818
+ mode: RUNTIME_MODES.has(runtime?.mode) ? runtime?.mode : 'unknown',
819
+ }),
820
+ host: Object.freeze({
821
+ appVersion: readOptionalString(host?.appVersion),
822
+ }),
823
+ miniProgram: Object.freeze({
824
+ id: readOptionalString(miniProgram?.id),
825
+ version: readOptionalString(miniProgram?.version),
826
+ }),
827
+ operatingSystem: Object.freeze({
828
+ name: OPERATING_SYSTEM_NAMES.has(operatingSystem?.name)
829
+ ? operatingSystem?.name
830
+ : 'unknown',
831
+ version: readOptionalString(operatingSystem?.version),
832
+ }),
833
+ sdk: Object.freeze({ version: HB_SDK_VERSION }),
834
+ });
835
+ }
836
+ function readOptionalString(value) {
837
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
838
+ }
839
+ function readRecord$1(value) {
840
+ return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
841
+ }
799
842
 
800
843
  const DEFAULT_TIMEOUT = 10000;
801
844
  const HANDSHAKE_RETRY_INTERVAL = 250;
@@ -827,6 +870,7 @@ class MiniProgramBridgeClient {
827
870
  destroyed = false;
828
871
  runtimeUnavailable = false;
829
872
  runtimeUnavailableError;
873
+ environmentInfo;
830
874
  constructor(options = {}) {
831
875
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
832
876
  this.selfWindow = options.selfWindow || getGlobalWindow();
@@ -853,6 +897,21 @@ class MiniProgramBridgeClient {
853
897
  onHandshakeStateChange(handler) {
854
898
  return this.handshakeState.subscribe(handler);
855
899
  }
900
+ /** 等待握手后读取当前实例的环境快照。 */
901
+ async getEnvironmentInfo() {
902
+ await this.waitForHandshake();
903
+ return this.getEnvironmentInfoSync();
904
+ }
905
+ /** 同步读取握手期间缓存的环境快照。 */
906
+ getEnvironmentInfoSync() {
907
+ const state = this.handshakeState.getState();
908
+ if (state.status === 'failed')
909
+ throw state.error;
910
+ if (state.status !== 'ready' || !this.environmentInfo) {
911
+ throw createSDKError('ENVIRONMENT_NOT_READY', '环境信息将在 SDK ready 后可用');
912
+ }
913
+ return this.environmentInfo;
914
+ }
856
915
  /** 注册小程序事件监听。 */
857
916
  on(eventName, handler) {
858
917
  return this.eventBus.on(eventName, handler);
@@ -1105,7 +1164,10 @@ class MiniProgramBridgeClient {
1105
1164
  if (eventName === 'unload') {
1106
1165
  this.markRuntimeUnavailable();
1107
1166
  }
1108
- else if (eventName === 'ready' && !this.runtimeUnavailable) {
1167
+ else if (eventName === 'ready' && !this.runtimeUnavailable && this.handshakeState.getState().status !== 'failed') {
1168
+ if (!this.environmentInfo) {
1169
+ this.environmentInfo = normalizeMiniProgramEnvironmentInfo(undefined);
1170
+ }
1109
1171
  this.resolveHandshakeOnce();
1110
1172
  }
1111
1173
  else if (eventName === 'show' && !this.runtimeUnavailable) {
@@ -1114,6 +1176,12 @@ class MiniProgramBridgeClient {
1114
1176
  this.eventBus.emit(eventName, message.payload);
1115
1177
  }
1116
1178
  handleResponse(message) {
1179
+ if (message.method === SDK_HANDSHAKE_METHOD && message.error === undefined) {
1180
+ if (!this.environmentInfo) {
1181
+ this.environmentInfo = normalizeMiniProgramEnvironmentInfo(readRecord(message.payload)?.environment);
1182
+ }
1183
+ return;
1184
+ }
1117
1185
  if (!message.id) {
1118
1186
  return;
1119
1187
  }
@@ -1233,6 +1301,9 @@ class MiniProgramBridgeClient {
1233
1301
  this.pendingRequests.clear();
1234
1302
  }
1235
1303
  }
1304
+ function readRecord(value) {
1305
+ return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
1306
+ }
1236
1307
  function waitForHandshakeOrAbort(handshake, signal, createAbortError, getTerminalError) {
1237
1308
  if (!signal)
1238
1309
  return handshake;
@@ -3687,6 +3758,8 @@ class MiniProgramSDK {
3687
3758
  navigation;
3688
3759
  /** 云端数据相关开放能力。 */
3689
3760
  cloud;
3761
+ /** 当前实例的环境信息。 */
3762
+ environment;
3690
3763
  constructor(options) {
3691
3764
  const launchHref = (options?.selfWindow ?? getGlobalWindow())?.location.href;
3692
3765
  this.client = new MiniProgramBridgeClient(options);
@@ -3701,6 +3774,7 @@ class MiniProgramSDK {
3701
3774
  this.device = createDeviceModule(this.client);
3702
3775
  this.navigation = createNavigationModule(this.client);
3703
3776
  this.cloud = createCloudModule(this.client);
3777
+ this.environment = createEnvironmentModule(this.client);
3704
3778
  }
3705
3779
  /** 获取当前握手状态。 */
3706
3780
  getHandshakeState() {
@@ -3999,6 +4073,11 @@ const cloud = {
3999
4073
  getInfo: (options) => getDefaultSDK().cloud.leaderboard.getInfo(options),
4000
4074
  },
4001
4075
  };
4076
+ /** 默认 SDK 实例的 environment 模块。 */
4077
+ const environment = {
4078
+ getInfo: () => getDefaultSDK().environment.getInfo(),
4079
+ getInfoSync: () => getDefaultSDK().environment.getInfoSync(),
4080
+ };
4002
4081
 
4003
4082
  const hbSDK = {
4004
4083
  getHandshakeState,
@@ -4014,8 +4093,9 @@ const hbSDK = {
4014
4093
  network,
4015
4094
  ui,
4016
4095
  device,
4096
+ environment,
4017
4097
  navigation,
4018
4098
  cloud,
4019
4099
  };
4020
4100
 
4021
- export { HbMiniProgramNetworkError, HbMiniProgramSDKError, USER_INFO_AUTHORIZATION_SCOPES, auth, cloud, hbSDK as default, device, files, getHandshakeState, navigation, network, off, on, onHandshakeStateChange, share, storage, ui, user, viewport };
4101
+ export { HbMiniProgramNetworkError, HbMiniProgramSDKError, USER_INFO_AUTHORIZATION_SCOPES, auth, cloud, hbSDK as default, device, environment, files, getHandshakeState, navigation, network, off, on, onHandshakeStateChange, share, storage, ui, user, viewport };
@@ -9,6 +9,6 @@ npm run build
9
9
  npm run deploy -- --release-note "更新说明"
10
10
  ```
11
11
 
12
- `vite.config.js` 默认声明 `android`、`ios`、`ohos`。发布前请在每个声明的平台完成真机验收;需要支持桌面平台时,由项目自行加入并验收。
12
+ `package.json#heybox.platforms` 默认声明 `android`、`ios`、`ohos`。发布前请在每个声明的平台完成真机验收;需要支持桌面平台时,由项目自行加入并验收。
13
13
 
14
14
  更多内容见 [CLI 指南](https://docs.xiaoheihe.cn/hb_sdk/guide/cli) 和 [SDK 文档](https://docs.xiaoheihe.cn/hb_sdk/)。
@@ -5,6 +5,7 @@
5
5
  "type": "module",
6
6
  "heybox": {
7
7
  "miniProgramId": "",
8
+ "platforms": ["android", "ios", "ohos"],
8
9
  "permissions": {}
9
10
  },
10
11
  "scripts": {
@@ -3,5 +3,5 @@ import { defineConfig } from 'vite';
3
3
 
4
4
  export default defineConfig({
5
5
  base: './',
6
- plugins: [miniappManifest({ platforms: ['android', 'ios', 'ohos'] })],
6
+ plugins: [miniappManifest()],
7
7
  });
package/dist/vite.cjs.js CHANGED
@@ -8,7 +8,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
8
8
  /** 构建时替换为当前发布包的实际版本。 */
9
9
  const HB_SDK_VERSION = typeof undefined === 'string'
10
10
  ? undefined
11
- : '0.8.1-alpha.1';
11
+ : '0.8.1-alpha.3';
12
12
 
13
13
  /**
14
14
  * iframe 与调试台页面的开发期 console 捕获转发。
@@ -3085,14 +3085,16 @@ function findNearestPackageJsonPath(startDir) {
3085
3085
  function readMiniappVersionFromPackageJson(root) {
3086
3086
  return readMiniappPackageJson(root, true).version;
3087
3087
  }
3088
+ function readMiniappPlatformsFromPackageJson(root) {
3089
+ const { packageJson } = readMiniappPackageJson(root, false);
3090
+ const heybox = readMiniappHeyboxConfig(packageJson);
3091
+ return validateMiniappPlatforms(heybox?.platforms, 'package.json#heybox.platforms');
3092
+ }
3088
3093
  function readMiniappPermissionsFromPackageJson(root, sdkVersion) {
3089
3094
  const { packageJson } = readMiniappPackageJson(root, false);
3090
- const heybox = packageJson.heybox;
3091
- if (heybox !== undefined && !isRecord(heybox)) {
3092
- throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
3093
- }
3094
- const present = isRecord(heybox) && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
3095
- return parseMiniappPermissions(isRecord(heybox) ? heybox.permissions : undefined, {
3095
+ const heybox = readMiniappHeyboxConfig(packageJson);
3096
+ const present = heybox !== undefined && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
3097
+ return parseMiniappPermissions(heybox?.permissions, {
3096
3098
  present,
3097
3099
  sdkVersion,
3098
3100
  });
@@ -3118,6 +3120,12 @@ function readMiniappPackageJson(root, requireVersion) {
3118
3120
  }
3119
3121
  return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
3120
3122
  }
3123
+ function readMiniappHeyboxConfig(packageJson) {
3124
+ if (packageJson.heybox !== undefined && !isRecord(packageJson.heybox)) {
3125
+ throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
3126
+ }
3127
+ return packageJson.heybox;
3128
+ }
3121
3129
  function isRecord(value) {
3122
3130
  return typeof value === 'object' && value !== null && !Array.isArray(value);
3123
3131
  }
@@ -11903,8 +11911,7 @@ function injectMiniDevConsoleBootstrap(html) {
11903
11911
  const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
11904
11912
  const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
11905
11913
  const miniDevLoggingConstant = ['__HB_SDK_DEV', 'LOGGING__'].join('_');
11906
- function miniappManifest(options) {
11907
- const platforms = validateMiniappPlatforms(options?.platforms, 'miniappManifest().platforms');
11914
+ function miniappManifest() {
11908
11915
  const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
11909
11916
  let root = process.cwd();
11910
11917
  let outDir = 'dist';
@@ -11951,7 +11958,8 @@ function miniappManifest(options) {
11951
11958
  skipPlatformCsp,
11952
11959
  });
11953
11960
  return command === 'serve' ? injectMiniDevConsoleBootstrap(enforced) : enforced;
11954
- }, async closeBundle() {
11961
+ },
11962
+ async closeBundle() {
11955
11963
  // Rollup 在 buildStart/transform 失败后仍会调用 closeBundle。
11956
11964
  // 若此时再抛「缺 index.html」等二次错误,会掩盖真实失败原因。
11957
11965
  if (priorBuildError) {
@@ -11959,6 +11967,7 @@ function miniappManifest(options) {
11959
11967
  }
11960
11968
  const version = validateMiniappPackageVersionForBuild(readMiniappVersionFromPackageJson(root));
11961
11969
  const sdkVersion = resolveSdkVersion();
11970
+ const platforms = readMiniappPlatformsFromPackageJson(root);
11962
11971
  const parsedPermissions = readMiniappPermissionsFromPackageJson(root, sdkVersion);
11963
11972
  if (!parsedPermissions.declared)
11964
11973
  this.warn(getMissingPermissionsWarning());
package/dist/vite.esm.js CHANGED
@@ -5,7 +5,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
5
5
  /** 构建时替换为当前发布包的实际版本。 */
6
6
  const HB_SDK_VERSION = typeof undefined === 'string'
7
7
  ? undefined
8
- : '0.8.1-alpha.1';
8
+ : '0.8.1-alpha.3';
9
9
 
10
10
  /**
11
11
  * iframe 与调试台页面的开发期 console 捕获转发。
@@ -3082,14 +3082,16 @@ function findNearestPackageJsonPath(startDir) {
3082
3082
  function readMiniappVersionFromPackageJson(root) {
3083
3083
  return readMiniappPackageJson(root, true).version;
3084
3084
  }
3085
+ function readMiniappPlatformsFromPackageJson(root) {
3086
+ const { packageJson } = readMiniappPackageJson(root, false);
3087
+ const heybox = readMiniappHeyboxConfig(packageJson);
3088
+ return validateMiniappPlatforms(heybox?.platforms, 'package.json#heybox.platforms');
3089
+ }
3085
3090
  function readMiniappPermissionsFromPackageJson(root, sdkVersion) {
3086
3091
  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, {
3092
+ const heybox = readMiniappHeyboxConfig(packageJson);
3093
+ const present = heybox !== undefined && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
3094
+ return parseMiniappPermissions(heybox?.permissions, {
3093
3095
  present,
3094
3096
  sdkVersion,
3095
3097
  });
@@ -3115,6 +3117,12 @@ function readMiniappPackageJson(root, requireVersion) {
3115
3117
  }
3116
3118
  return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
3117
3119
  }
3120
+ function readMiniappHeyboxConfig(packageJson) {
3121
+ if (packageJson.heybox !== undefined && !isRecord(packageJson.heybox)) {
3122
+ throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
3123
+ }
3124
+ return packageJson.heybox;
3125
+ }
3118
3126
  function isRecord(value) {
3119
3127
  return typeof value === 'object' && value !== null && !Array.isArray(value);
3120
3128
  }
@@ -11900,8 +11908,7 @@ function injectMiniDevConsoleBootstrap(html) {
11900
11908
  const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
11901
11909
  const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
11902
11910
  const miniDevLoggingConstant = ['__HB_SDK_DEV', 'LOGGING__'].join('_');
11903
- function miniappManifest(options) {
11904
- const platforms = validateMiniappPlatforms(options?.platforms, 'miniappManifest().platforms');
11911
+ function miniappManifest() {
11905
11912
  const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
11906
11913
  let root = process.cwd();
11907
11914
  let outDir = 'dist';
@@ -11948,7 +11955,8 @@ function miniappManifest(options) {
11948
11955
  skipPlatformCsp,
11949
11956
  });
11950
11957
  return command === 'serve' ? injectMiniDevConsoleBootstrap(enforced) : enforced;
11951
- }, async closeBundle() {
11958
+ },
11959
+ async closeBundle() {
11952
11960
  // Rollup 在 buildStart/transform 失败后仍会调用 closeBundle。
11953
11961
  // 若此时再抛「缺 index.html」等二次错误,会掩盖真实失败原因。
11954
11962
  if (priorBuildError) {
@@ -11956,6 +11964,7 @@ function miniappManifest(options) {
11956
11964
  }
11957
11965
  const version = validateMiniappPackageVersionForBuild(readMiniappVersionFromPackageJson(root));
11958
11966
  const sdkVersion = resolveSdkVersion();
11967
+ const platforms = readMiniappPlatformsFromPackageJson(root);
11959
11968
  const parsedPermissions = readMiniappPermissionsFromPackageJson(root, sdkVersion);
11960
11969
  if (!parsedPermissions.declared)
11961
11970
  this.warn(getMissingPermissionsWarning());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk",
3
- "version": "0.8.1-alpha.1",
3
+ "version": "0.8.1-alpha.3",
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.1-alpha.1"
65
+ "@heybox/hb-sdk-protocol": "0.8.1-alpha.3"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "vite": ">=5"
@@ -113,13 +113,13 @@
113
113
  "vue-tsc": "^3.3.7",
114
114
  "vite": "^8.0.12",
115
115
  "vitest": "^3.2.4",
116
- "@heybox/hb-api": "~1.28.2",
116
+ "@heybox-domain/heybox-theme": "~0.1.0",
117
117
  "@heybox-domain/heybox-vue3-ui": "~0.1.0",
118
- "@heybox/hb-sdk-runtime": "~0.8.1-alpha.1",
119
- "@heybox/runtime-policy": "~0.2.0",
120
- "@heybox/runtime-transport-fetch": "~0.2.0",
118
+ "@heybox/hb-sdk-runtime": "~0.8.1-alpha.3",
119
+ "@heybox/hb-api": "~1.28.2",
121
120
  "@heybox/runtime": "~0.2.0",
122
- "@heybox-domain/heybox-theme": "~0.1.0"
121
+ "@heybox/runtime-transport-fetch": "~0.2.0",
122
+ "@heybox/runtime-policy": "~0.2.0"
123
123
  },
124
124
  "publishConfig": {
125
125
  "registry": "https://registry.npmjs.org/",
package/skill/SKILL.md CHANGED
@@ -52,6 +52,8 @@ Apply these instructions when writing, reviewing, or debugging code that consume
52
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
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
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.
55
+ 15. Use `environment.getInfo()` for the immutable runtime, Host App, canonical Mini-program, operating-system, and SDK version snapshot. It waits for the handshake automatically. Use `environment.getInfoSync()` only after `getHandshakeState().status === 'ready'` or inside a ready-state subscription; before that it throws `ENVIRONMENT_NOT_READY`.
56
+ 16. Treat missing environment strings as `null` and unknown enum values as `unknown`. Only `sdk.version` is SemVer; do not compare the other opaque version strings or use any environment field for authentication, authorization, or risk control.
55
57
 
56
58
  ## Step 5: Use CLI workflows
57
59
 
@@ -59,7 +61,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
59
61
  2. Use `hb-sdk dev` for Browser Mock and Mobile App debugging. Browser debugging can start without CLI login, project binding, or a remote Dev Context; capabilities that need those inputs fail explicitly. Mobile uses the single QR entry with the `open_inapp` and `heybox://` `openWindow` wrapper around a LAN short URL, then opens `heybox-mini-dev://sandbox` with the complete launch context.
60
62
  3. The debugging page does not edit permissions. Treat the validated remote permission snapshot as canonical Runtime input. Use `--port`, `--browser-dev-host-port`, and `--no-open` to control local endpoints and browser opening. Select a Mobile network interface the device can reach. `launch.json` is a LAN discovery document, not authentication, encryption, signing, or HMAC protection.
61
63
  4. Use `hb-sdk build [--env <name>] [--verbose]` as the recommended production build entry. It directly owns the Vite build, always cleans and writes `dist/`, and works without CLI login, project binding, or network access.
62
- 5. Keep `miniappManifest()` explicitly enabled in `vite.config.ts`; `hb-sdk build` must fail when the required Manifest or Runtime gate output is missing.
64
+ 5. Declare the actual supported platforms in `package.json#heybox.platforms` and keep the no-argument `miniappManifest()` explicitly enabled in `vite.config.ts`; `hb-sdk build` must fail when the declaration, Manifest, or Runtime gate output is missing or inconsistent.
63
65
  6. Keep project typechecking in `scripts.build`, for example `vue-tsc --noEmit && hb-sdk build`; `hb-sdk build` does not run typechecking or invoke `scripts.build` itself.
64
66
  7. Existing projects may continue to use `vite build`; do not auto-migrate them. Do not invent `--mode`, `--json`, config, or output-directory flags for `hb-sdk build`.
65
67
  8. Use `hb-sdk login`, `hb-sdk login status`, and `hb-sdk login clear` for remote management, publishing, Mobile debugging, and optional Browser Mock Host `heybox-session` requests. Browser debugging itself can start without CLI login. Mini-program code must still call `auth.login()`; the debug page only confirms authorization. Do not paste CLI credentials into page JavaScript. Phone debugging continues to use the App login.
@@ -88,13 +90,14 @@ For workshop mini-program business code:
88
90
  7. Do not use `network.request()` to reach platform-reserved runtime auth or OpenAPI internal paths.
89
91
  8. Do not expose credentials or describe internal Host authorization state machines and routes in app-facing guidance.
90
92
  9. Do not invent string paths, File System Access API handles, Blob downloads, uploads, Range/resume, external deletion, move, append, or persistent external grants. Public file operations use only SDK-created handles; deletion is limited to SDK sandbox handles.
93
+ 10. Do not treat `environment.*` as a device-fingerprint or trusted backend signal. It intentionally excludes account data, device identifiers, model, UA, CPU, and memory; use `viewport.getWindowInfo()` for screen geometry.
91
94
 
92
95
  For CLI and local development:
93
96
 
94
97
  1. Do not print, persist in templates, or pass through pkey, cookies, tokens, or private credentials.
95
98
  2. Do not skip `auth.login()` in mini-program code. Browser Mock may reuse the Node `hb-sdk login` session for Host network requests, but the page must still call `auth.login()` and handle the authorization dialog. Never paste CLI credentials into page JavaScript.
96
99
  3. Use the built-in local debugging page instead of creating another browser Mock.
97
- 4. Keep the Vite `miniappManifest()` plugin enabled.
100
+ 4. Keep target platforms in `package.json#heybox.platforms` and the no-argument Vite `miniappManifest()` plugin enabled. Do not configure platforms in Vite or maintain a second platform list.
98
101
  5. Do not suggest changing or resetting permissions in the `hb-sdk dev` debugging page; that UI does not exist. Diagnose permission behavior from the remote snapshot and capability result.
99
102
  6. Treat browser Mock results as development feedback only. Validate permissions, identity flows, and user interactions again in a real Heybox client before publishing.
100
103
  7. The Browser Dev Host offers iPhone 16 Pro Max (`440 x 956`) and Pixel 9 Pro (`410 x 914`) presets. Switching a preset must preserve the iframe, Runtime session, and page state. Authorization/action dialogs, Toast, Loading, and vibration feedback render inside the preview. Use the upper-right QR popover as the only Mobile QR entry.
@@ -176,7 +176,10 @@ export type {
176
176
  MiniProgramNetworkMethod,
177
177
  MiniProgramNetworkParams,
178
178
  MiniProgramNetworkRequestMethod,
179
+ MiniProgramOperatingSystemName,
179
180
  MiniProgramRuntimePermissionEntry,
181
+ MiniProgramRuntimeEnvironmentInfo,
182
+ MiniProgramRuntimeMode,
180
183
  MiniProgramRuntimePermissionsSnapshot,
181
184
  MiniProgramRuntimePermissionStatus,
182
185
  MiniProgramSafeArea,
@@ -215,6 +218,7 @@ export type {
215
218
  SaveFilePayload,
216
219
  SaveFileResult,
217
220
  SDKHandshakePayload,
221
+ SDKHandshakeResult,
218
222
  SetClipboardPayload,
219
223
  SetClipboardResult,
220
224
  SetNavigationBarStylePayload,
@@ -295,12 +299,12 @@ Reference 由 `@heybox/hb-sdk` 的公开导出与源码注释自动生成,不
295
299
 
296
300
  | 导出面 | Classes | Functions | Interfaces | Types | Constants |
297
301
  | --- | ---: | ---: | ---: | ---: | ---: |
298
- | Root API | 2 | 4 | 65 | 60 | 1 |
299
- | Protocol API | 0 | 13 | 56 | 90 | 47 |
302
+ | Root API | 2 | 4 | 67 | 62 | 2 |
303
+ | Protocol API | 0 | 13 | 58 | 90 | 47 |
300
304
  | Miniapp Publish API | 0 | 5 | 2 | 0 | 0 |
301
- | Vite API | 0 | 1 | 5 | 1 | 1 |
305
+ | Vite API | 0 | 1 | 4 | 1 | 1 |
302
306
 
303
- <!-- Generated by apps/docs/hb-sdk/scripts/generate-api-docs.ts; schemaVersion=4; fingerprint=f9457e0ad4a2e5f69896c7b05a8563ae5171df141d86cf81aa6fe1b4aca6b280 -->
307
+ <!-- Generated by apps/docs/hb-sdk/scripts/generate-api-docs.ts; schemaVersion=4; fingerprint=a8018ebd23e4d885efbe08f622a6cf4780dd152d5f90cc4a78d2eb7e15eca2e2 -->
304
308
 
305
309
  ## SDK API
306
310