@heybox/hb-sdk-protocol 0.8.3-alpha.2 → 0.8.3-alpha.4

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/dist/index.esm.js CHANGED
@@ -39,6 +39,7 @@ const USER_GET_STEAM_GAME_LIST_METHOD = 'user.getSteamGameList';
39
39
  const SHARE_COPY_LINK_METHOD = 'share.copyLink';
40
40
  const SHARE_SHOW_SHARE_MENU_METHOD = 'share.showShareMenu';
41
41
  const SHARE_SCREENSHOT_METHOD = 'share.screenshot';
42
+ const VIEWPORT_SET_DISPLAY_METHOD = 'viewport.setDisplay';
42
43
  const VIEWPORT_GET_WINDOW_INFO_METHOD = 'viewport.getWindowInfo';
43
44
  const VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = 'viewport.setNavigationBarStyle';
44
45
  const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage';
@@ -162,6 +163,13 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
162
163
  requirement: { kind: 'none' },
163
164
  risk: 'low',
164
165
  },
166
+ {
167
+ method: VIEWPORT_SET_DISPLAY_METHOD,
168
+ module: 'viewport',
169
+ capability: VIEWPORT_SET_DISPLAY_METHOD,
170
+ requirement: { kind: 'none' },
171
+ risk: 'low',
172
+ },
165
173
  {
166
174
  method: STORAGE_GET_STORAGE_METHOD,
167
175
  module: 'storage',
@@ -437,7 +445,7 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
437
445
  * @see [parseMiniProgramRuntimePermissions](/reference/symbols/protocol/functions/parseMiniProgramRuntimePermissions) Runtime 权限快照解析器。
438
446
  */
439
447
  function isMiniProgramBridgeMessage(value) {
440
- if (!isRecord$2(value))
448
+ if (!isRecord$3(value))
441
449
  return false;
442
450
  if (value.namespace !== MINI_PROGRAM_MESSAGE_NAMESPACE || (value.version !== 1 && value.version !== 2) || !isNonEmptyString$1(value.nonce)) {
443
451
  return false;
@@ -587,7 +595,7 @@ function isMiniProgramRelativePath(value) {
587
595
  * @see [DirectoryHandle](/reference/symbols/root/interfaces/DirectoryHandle) 可作为 derived path root 的目录代理。
588
596
  */
589
597
  function isMiniProgramPathRootRef(value) {
590
- if (!isRecord$2(value))
598
+ if (!isRecord$3(value))
591
599
  return false;
592
600
  if (value.kind === 'sandbox')
593
601
  return hasOnlyKeys(value, ['kind']);
@@ -653,7 +661,7 @@ function isMiniProgramPathRootRef(value) {
653
661
  * @see [FileHandle](/reference/symbols/root/interfaces/FileHandle) 使用文件引用的公开 I/O 代理。
654
662
  */
655
663
  function isMiniProgramFileRef(value) {
656
- if (!isRecord$2(value) || value.kind !== 'file')
664
+ if (!isRecord$3(value) || value.kind !== 'file')
657
665
  return false;
658
666
  if (isNonEmptyString$1(value.handleId)) {
659
667
  return hasOnlyKeys(value, ['kind', 'handleId']);
@@ -720,7 +728,7 @@ function isMiniProgramFileRef(value) {
720
728
  * @see [DirectoryHandle](/reference/symbols/root/interfaces/DirectoryHandle) 使用目录引用的公开路径操作代理。
721
729
  */
722
730
  function isMiniProgramDirectoryRef(value) {
723
- if (!isRecord$2(value) || value.kind !== 'directory')
731
+ if (!isRecord$3(value) || value.kind !== 'directory')
724
732
  return false;
725
733
  if (isNonEmptyString$1(value.handleId)) {
726
734
  return hasOnlyKeys(value, ['kind', 'handleId']);
@@ -794,7 +802,7 @@ function isMiniProgramDirectoryRef(value) {
794
802
  * @see [SaveFileResult](/reference/symbols/protocol/types/SaveFileResult) save picker 的 direct-ref 文件结果。
795
803
  */
796
804
  function isMiniProgramFileDescriptor(value) {
797
- return (isRecord$2(value) &&
805
+ return (isRecord$3(value) &&
798
806
  value.kind === 'file' &&
799
807
  isNonEmptyString$1(value.name) &&
800
808
  isFileMode(value.mode) &&
@@ -864,7 +872,7 @@ function isMiniProgramFileDescriptor(value) {
864
872
  * @see [PickDirectoryResult](/reference/symbols/protocol/types/PickDirectoryResult) picker 的 direct-ref 返回契约。
865
873
  */
866
874
  function isMiniProgramDirectoryDescriptor(value) {
867
- return (isRecord$2(value) &&
875
+ return (isRecord$3(value) &&
868
876
  value.kind === 'directory' &&
869
877
  isNonEmptyString$1(value.name) &&
870
878
  isFileMode(value.mode) &&
@@ -1043,7 +1051,7 @@ function isMiniProgramByteArray(value) {
1043
1051
  * @see [FileHandle](/reference/symbols/root/interfaces/FileHandle) 提供 `stat()` 的当前 session 文件代理。
1044
1052
  */
1045
1053
  function isMiniProgramFileStat(value) {
1046
- return (isRecord$2(value) &&
1054
+ return (isRecord$3(value) &&
1047
1055
  value.kind === 'file' &&
1048
1056
  isNonNegativeSafeInteger(value.size) &&
1049
1057
  (value.modifiedAt === undefined || isNonNegativeFiniteNumber(value.modifiedAt)) &&
@@ -1103,7 +1111,7 @@ function isMiniProgramFileStat(value) {
1103
1111
  * @see [isMiniProgramBridgeMessage](/reference/symbols/protocol/functions/isMiniProgramBridgeMessage) operation progress envelope 的最低校验。
1104
1112
  */
1105
1113
  function isMiniProgramDownloadProgressPayload(value) {
1106
- if (!isRecord$2(value) ||
1114
+ if (!isRecord$3(value) ||
1107
1115
  !isNonNegativeSafeInteger(value.loaded) ||
1108
1116
  typeof value.lengthComputable !== 'boolean' ||
1109
1117
  !hasOnlyKeys(value, ['loaded', 'total', 'lengthComputable'])) {
@@ -1114,7 +1122,7 @@ function isMiniProgramDownloadProgressPayload(value) {
1114
1122
  return isNonNegativeSafeInteger(value.total) && value.loaded <= value.total;
1115
1123
  }
1116
1124
  function isMiniProgramCompanionPrepareProgress(value) {
1117
- if (!isRecord$2(value))
1125
+ if (!isRecord$3(value))
1118
1126
  return false;
1119
1127
  if (value.phase === 'downloading') {
1120
1128
  return (isNonNegativeSafeInteger(value.loaded) &&
@@ -1132,10 +1140,10 @@ function isMiniProgramOperationProgressPayload(value) {
1132
1140
  return isMiniProgramDownloadProgressPayload(value) || isMiniProgramCompanionPrepareProgress(value);
1133
1141
  }
1134
1142
  function isSDKHandshakePayload(value) {
1135
- return isRecord$2(value) && isNonEmptyString$1(value.href) && typeof value.userAgent === 'string' && isNonEmptyString$1(value.sdkVersion);
1143
+ return isRecord$3(value) && isNonEmptyString$1(value.href) && typeof value.userAgent === 'string' && isNonEmptyString$1(value.sdkVersion);
1136
1144
  }
1137
1145
  function isBridgeError(value) {
1138
- return isRecord$2(value) && isNonEmptyString$1(value.code) && typeof value.message === 'string';
1146
+ return isRecord$3(value) && isNonEmptyString$1(value.code) && typeof value.message === 'string';
1139
1147
  }
1140
1148
  function isFileMode(value) {
1141
1149
  return value === 'read' || value === 'readwrite';
@@ -1153,156 +1161,10 @@ function hasOnlyKeys(value, allowedKeys) {
1153
1161
  const allowed = new Set(allowedKeys);
1154
1162
  return Object.keys(value).every((key) => allowed.has(key));
1155
1163
  }
1156
- function isRecord$2(value) {
1164
+ function isRecord$3(value) {
1157
1165
  return typeof value === 'object' && value !== null && !Array.isArray(value);
1158
1166
  }
1159
1167
 
1160
- /** 由 scripts/generate-native-host-contract.mjs 生成,请勿手改。 */
1161
- const MINI_PROGRAM_NATIVE_HOST_PROTOCOL_VERSION = 1;
1162
- const MINI_PROGRAM_NATIVE_HOST_CONTRACT_REVISION = 1;
1163
- const MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES = 65536;
1164
- const MINI_PROGRAM_NATIVE_OPERATIONS = {
1165
- "system": [
1166
- "describe"
1167
- ],
1168
- "network": [
1169
- "open",
1170
- "read",
1171
- "release",
1172
- "transfer"
1173
- ],
1174
- "files": [
1175
- "create",
1176
- "remove",
1177
- "exists",
1178
- "openRead",
1179
- "openWrite",
1180
- "read",
1181
- "release",
1182
- "write",
1183
- "stat",
1184
- "list",
1185
- "pickFiles",
1186
- "pickDirectory",
1187
- "saveFile"
1188
- ]
1189
- };
1190
- const MINI_PROGRAM_NATIVE_HOST_DESCRIPTION = {
1191
- "protocolVersion": 1,
1192
- "contractRevision": 1,
1193
- "operations": {
1194
- "system": [
1195
- "describe"
1196
- ],
1197
- "network": [
1198
- "open",
1199
- "read",
1200
- "release",
1201
- "transfer"
1202
- ],
1203
- "files": [
1204
- "create",
1205
- "remove",
1206
- "exists",
1207
- "openRead",
1208
- "openWrite",
1209
- "read",
1210
- "release",
1211
- "write",
1212
- "stat",
1213
- "list",
1214
- "pickFiles",
1215
- "pickDirectory",
1216
- "saveFile"
1217
- ]
1218
- }
1219
- };
1220
-
1221
- /** Android WebMessageListener object 与 iOS WKScriptMessageHandler 共用名称。 */
1222
- const MINI_PROGRAM_NATIVE_HOST_OBJECT = 'hbMiniProgramHost';
1223
- /** Native 通过主文档 CustomEvent 回送 progress/result/error。 */
1224
- const MINI_PROGRAM_NATIVE_HOST_MESSAGE_EVENT = 'heybox:miniprogram-native-host-message';
1225
- function isMiniProgramNativeHostMessage(value) {
1226
- if (!isRecord$1(value) || !isNonEmptyString(value.requestId))
1227
- return false;
1228
- if (value.type === 'progress')
1229
- return Object.prototype.hasOwnProperty.call(value, 'payload');
1230
- if (value.type === 'result')
1231
- return !Object.prototype.hasOwnProperty.call(value, 'error');
1232
- if (value.type !== 'error' || !isRecord$1(value.error))
1233
- return false;
1234
- return isNonEmptyString(value.error.code) && isNonEmptyString(value.error.message);
1235
- }
1236
- function isMiniProgramNativeHostDescription(value) {
1237
- if (!isRecord$1(value) ||
1238
- !isPositiveSafeInteger(value.protocolVersion) ||
1239
- !isPositiveSafeInteger(value.contractRevision) ||
1240
- !isRecord$1(value.operations))
1241
- return false;
1242
- const operations = value.operations;
1243
- if (!isOperationList(operations.system) ||
1244
- !isOperationList(operations.network) ||
1245
- !isOperationList(operations.files))
1246
- return false;
1247
- return operations.system.includes('describe');
1248
- }
1249
- function isMiniProgramNativeBinaryChunk(value) {
1250
- return (isRecord$1(value) &&
1251
- isNonEmptyString(value.resourceId) &&
1252
- typeof value.data === 'string' &&
1253
- Number.isSafeInteger(value.byteLength) &&
1254
- Number(value.byteLength) >= 0 &&
1255
- Number(value.byteLength) <= MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES &&
1256
- typeof value.eof === 'boolean' &&
1257
- (Number(value.byteLength) > 0 || value.eof));
1258
- }
1259
- function isRecord$1(value) {
1260
- return value !== null && typeof value === 'object' && !Array.isArray(value);
1261
- }
1262
- function isNonEmptyString(value) {
1263
- return typeof value === 'string' && value.length > 0;
1264
- }
1265
- function isPositiveSafeInteger(value) {
1266
- return Number.isSafeInteger(value) && Number(value) > 0;
1267
- }
1268
- function isOperationList(value) {
1269
- return (Array.isArray(value) &&
1270
- value.every(operation => isNonEmptyString(operation) && operation === operation.trim()) &&
1271
- new Set(value).size === value.length);
1272
- }
1273
-
1274
- /** 当前用户信息与登录能力支持的完整 scope 目录(canonical 顺序)。 */
1275
- const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile', 'steam_account'];
1276
- /** Companion alias 的跨构建、Runtime 与 Host 规范。 */
1277
- const COMPANION_ALIAS_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
1278
- /** Companion Host 可跨 bridge 保留的稳定领域错误码。 */
1279
- const COMPANION_ERROR_CODES = [
1280
- 'COMPANION_UNSUPPORTED',
1281
- 'COMPANION_PREVIEW_UNSUPPORTED',
1282
- 'COMPANION_NOT_DECLARED',
1283
- 'COMPANION_TARGET_UNSUPPORTED',
1284
- 'COMPANION_NOT_PREPARED',
1285
- 'COMPANION_PREPARATION_CANCELLED',
1286
- 'COMPANION_DOWNLOAD_FAILED',
1287
- 'COMPANION_DESCRIPTOR_UNAVAILABLE',
1288
- 'COMPANION_ARCHIVE_INVALID',
1289
- 'COMPANION_INTEGRITY_FAILED',
1290
- 'COMPANION_ENTRYPOINT_INVALID',
1291
- 'COMPANION_USER_CANCELLED',
1292
- 'COMPANION_ELEVATION_DENIED',
1293
- 'COMPANION_OS_BLOCKED',
1294
- 'COMPANION_LAUNCH_FAILED',
1295
- 'COMPANION_SESSION_VERSION_MISMATCH',
1296
- 'COMPANION_SESSION_OWNERSHIP_LOST',
1297
- 'COMPANION_SESSION_EXITED',
1298
- 'COMPANION_PIPE_CLOSED',
1299
- 'COMPANION_OUTPUT_LIMIT',
1300
- 'COMPANION_PROCESS_CRASHED',
1301
- 'COMPANION_ATTACHMENT_NOT_FOUND',
1302
- 'COMPANION_NOTIFICATION_UNAVAILABLE',
1303
- 'COMPANION_TERMINATE_FAILED',
1304
- ];
1305
-
1306
1168
  const MINI_PROGRAM_PERMISSION_KEYS = [
1307
1169
  'userInfo',
1308
1170
  'steamLibrary',
@@ -1456,6 +1318,7 @@ const MINI_PROGRAM_NO_DECLARATION_METHODS = [
1456
1318
  'ui.hideLoading',
1457
1319
  'viewport.getWindowInfo',
1458
1320
  'viewport.setNavigationBarStyle',
1321
+ 'viewport.setDisplay',
1459
1322
  'device.vibrate',
1460
1323
  'navigation.close',
1461
1324
  'navigation.reload',
@@ -1596,7 +1459,7 @@ function isManagedMiniProgramRuntimePermissionKey(key) {
1596
1459
  * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
1597
1460
  */
1598
1461
  function parseMiniProgramRuntimePermissions(snapshot) {
1599
- if (!isRecord(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
1462
+ if (!isRecord$2(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
1600
1463
  return { valid: false, permissions: {} };
1601
1464
  }
1602
1465
  if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
@@ -1605,7 +1468,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
1605
1468
  const seenKeys = new Set();
1606
1469
  const permissions = {};
1607
1470
  for (const rawEntry of snapshot.entries) {
1608
- if (!isRecord(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
1471
+ if (!isRecord$2(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
1609
1472
  return { valid: false, permissions: {} };
1610
1473
  }
1611
1474
  const inputKey = rawEntry.key.trim();
@@ -1621,7 +1484,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
1621
1484
  }
1622
1485
  if (key === 'network') {
1623
1486
  const config = rawEntry.config;
1624
- if (!isRecord(config) || typeof config.useOfficialDomain !== 'boolean') {
1487
+ if (!isRecord$2(config) || typeof config.useOfficialDomain !== 'boolean') {
1625
1488
  return { valid: false, permissions: {} };
1626
1489
  }
1627
1490
  permissions[key] = {
@@ -1631,7 +1494,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
1631
1494
  };
1632
1495
  continue;
1633
1496
  }
1634
- if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
1497
+ if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord$2(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
1635
1498
  return { valid: false, permissions: {} };
1636
1499
  }
1637
1500
  permissions[key] = {
@@ -1642,8 +1505,264 @@ function parseMiniProgramRuntimePermissions(snapshot) {
1642
1505
  }
1643
1506
  return { valid: true, permissions };
1644
1507
  }
1645
- function isRecord(value) {
1508
+ function isRecord$2(value) {
1646
1509
  return typeof value === 'object' && value !== null && !Array.isArray(value);
1647
1510
  }
1648
1511
 
1649
- export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, COMPANION_ALIAS_PATTERN, COMPANION_CANCEL_PREPARATION_METHOD, COMPANION_ERROR_CODES, COMPANION_GET_ACTIVE_SESSION_METHOD, COMPANION_GET_INFO_METHOD, COMPANION_GET_PREPARATION_STATUS_METHOD, COMPANION_LAUNCH_METHOD, COMPANION_OPEN_ATTACHMENT_METHOD, COMPANION_PREPARE_METHOD, COMPANION_SESSION_ACK_OUTPUT_METHOD, COMPANION_SESSION_CLOSE_STDIN_METHOD, COMPANION_SESSION_EXIT_EVENT, COMPANION_SESSION_OUTPUT_EVENT, COMPANION_SESSION_OWNERSHIP_LOST_EVENT, COMPANION_SESSION_TERMINATE_METHOD, COMPANION_SESSION_WRITE_METHOD, COMPANION_SHOW_NOTIFICATION_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, DIRECTORY_CREATE_METHOD, DIRECTORY_EXISTS_METHOD, DIRECTORY_LIST_METHOD, DIRECTORY_REMOVE_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_PICK_FILES_METHOD, FILES_SAVE_FILE_METHOD, FILE_CREATE_METHOD, FILE_EXISTS_METHOD, FILE_READ_BYTES_METHOD, FILE_READ_TEXT_METHOD, FILE_REMOVE_METHOD, FILE_STAT_METHOD, FILE_WRITE_BYTES_METHOD, FILE_WRITE_TEXT_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES, MINI_PROGRAM_NATIVE_HOST_CONTRACT_REVISION, MINI_PROGRAM_NATIVE_HOST_DESCRIPTION, MINI_PROGRAM_NATIVE_HOST_MESSAGE_EVENT, MINI_PROGRAM_NATIVE_HOST_OBJECT, MINI_PROGRAM_NATIVE_HOST_PROTOCOL_VERSION, MINI_PROGRAM_NATIVE_OPERATIONS, MINI_PROGRAM_NO_DECLARATION_METHODS, MINI_PROGRAM_OPERATION_PROGRESS_METHOD, MINI_PROGRAM_PERMISSION_CATALOG, MINI_PROGRAM_PERMISSION_KEYS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_DOWNLOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_COPY_LINK_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isMiniProgramByteArray, isMiniProgramCompanionPrepareProgress, isMiniProgramDirectoryDescriptor, isMiniProgramDirectoryRef, isMiniProgramDownloadProgressPayload, isMiniProgramFileDescriptor, isMiniProgramFileRef, isMiniProgramFileStat, isMiniProgramFileSystemEntityDescriptor, isMiniProgramNativeBinaryChunk, isMiniProgramNativeHostDescription, isMiniProgramNativeHostMessage, isMiniProgramOperationProgressPayload, isMiniProgramPathRootRef, isMiniProgramPermissionKey, isMiniProgramRelativePath, parseMiniProgramRuntimePermissions };
1512
+ /** 仅供开发工具和 Host 使用;新增权限必须单独评估,不能从平台审批目录自动推导。 */
1513
+ const LOCAL_DEV_GRANT_PERMISSION_KEYS = ['network', 'companion'];
1514
+ /**
1515
+ * 严格解析本地 grant。任何未知字段、重复权限或非法配置都拒绝整份输入。
1516
+ * 只校验数据合同;票据、身份、摘要、过期时间和 CLI lease 必须由 Host 另行验证。
1517
+ */
1518
+ function parseMiniProgramLocalDevGrant(value) {
1519
+ if (!hasExactFields(value, ['schema_version', 'revision', 'entries']) ||
1520
+ value.schema_version !== 1 ||
1521
+ typeof value.revision !== 'number' ||
1522
+ !Number.isSafeInteger(value.revision) ||
1523
+ value.revision < 0 ||
1524
+ !Array.isArray(value.entries) ||
1525
+ value.entries.length > LOCAL_DEV_GRANT_PERMISSION_KEYS.length)
1526
+ return { valid: false };
1527
+ const entries = [];
1528
+ const seen = new Set();
1529
+ for (const entry of value.entries) {
1530
+ if (!hasExactFields(entry, ['key', 'status', 'config']) || entry.status !== 'enabled')
1531
+ return { valid: false };
1532
+ if (typeof entry.key !== 'string' || seen.has(entry.key))
1533
+ return { valid: false };
1534
+ seen.add(entry.key);
1535
+ if (entry.key === 'network') {
1536
+ if (!hasExactFields(entry.config, ['useOfficialDomain']) || entry.config.useOfficialDomain !== false)
1537
+ return { valid: false };
1538
+ entries.push({ key: 'network', status: 'enabled', config: { useOfficialDomain: false } });
1539
+ }
1540
+ else if (entry.key === 'companion') {
1541
+ if (!hasExactFields(entry.config, []))
1542
+ return { valid: false };
1543
+ entries.push({ key: 'companion', status: 'enabled', config: {} });
1544
+ }
1545
+ else {
1546
+ return { valid: false };
1547
+ }
1548
+ }
1549
+ entries.sort((a, b) => LOCAL_DEV_GRANT_PERMISSION_KEYS.indexOf(a.key) - LOCAL_DEV_GRANT_PERMISSION_KEYS.indexOf(b.key));
1550
+ return { valid: true, grant: { schema_version: 1, revision: value.revision, entries } };
1551
+ }
1552
+ /**
1553
+ * 从已校验声明生成批准缺口。Companion 默认不符合资格,由 CLI 确认平台、产物与摘要后显式加入。
1554
+ * 空 entries 可保留 revision,不能作为存在临时权限的判断依据。
1555
+ */
1556
+ function createMiniProgramLocalDevGrant(options) {
1557
+ if (!Number.isSafeInteger(options.revision) || options.revision < 0)
1558
+ throw new Error('本地调试权限 revision 必须是非负安全整数');
1559
+ const approvals = parseMiniProgramRuntimePermissions(options.runtimePermissions);
1560
+ const eligible = new Set(options.eligiblePermissionKeys ?? ['network']);
1561
+ const entries = [];
1562
+ for (const key of LOCAL_DEV_GRANT_PERMISSION_KEYS) {
1563
+ if (!eligible.has(key) || options.declaredPermissions[key]?.enabled !== true)
1564
+ continue;
1565
+ if (approvals.valid && approvals.permissions[key]?.status === 'enabled')
1566
+ continue;
1567
+ entries.push(key === 'network'
1568
+ ? { key, status: 'enabled', config: { useOfficialDomain: false } }
1569
+ : { key, status: 'enabled', config: {} });
1570
+ }
1571
+ return { schema_version: 1, revision: options.revision, entries };
1572
+ }
1573
+ /**
1574
+ * 线上基线先与本地声明求交,再补齐临时权限,返回与输入脱离的普通 Runtime 快照。
1575
+ * 调用方只可在当前 Dev Session 已验证且用户接受后传入 grant;本函数不证明其可信来源。
1576
+ * 非法 grant 整体降权到基线,已批准配置不会被临时配置覆盖。
1577
+ */
1578
+ function composeLocalDevRuntimePermissions(options) {
1579
+ const baseline = parseMiniProgramRuntimePermissions(options.runtimePermissions);
1580
+ const parsed = parseMiniProgramLocalDevGrant(options.localDevGrant);
1581
+ const permissions = baseline.valid ? baseline.permissions : {};
1582
+ for (const key of MINI_PROGRAM_PERMISSION_KEYS) {
1583
+ if (options.declaredPermissions[key]?.enabled !== true) {
1584
+ delete permissions[key];
1585
+ }
1586
+ else if (key === 'network' && permissions.network) {
1587
+ permissions.network.config.useOfficialDomain = permissions.network.status === 'enabled'
1588
+ && permissions.network.config.useOfficialDomain === true
1589
+ && options.declaredPermissions.network?.useOfficialDomain === true;
1590
+ }
1591
+ }
1592
+ const temporaryPermissionKeys = [];
1593
+ if (parsed.valid) {
1594
+ for (const entry of parsed.grant.entries) {
1595
+ if (options.declaredPermissions[entry.key]?.enabled !== true || permissions[entry.key]?.status === 'enabled')
1596
+ continue;
1597
+ permissions[entry.key] = entry;
1598
+ temporaryPermissionKeys.push(entry.key);
1599
+ }
1600
+ }
1601
+ const revision = isRecord$1(options.runtimePermissions) && typeof options.runtimePermissions.revision === 'number'
1602
+ && Number.isSafeInteger(options.runtimePermissions.revision) && options.runtimePermissions.revision >= 0
1603
+ ? options.runtimePermissions.revision : undefined;
1604
+ return {
1605
+ runtimePermissions: {
1606
+ schema_version: 1,
1607
+ ...(revision === undefined ? {} : { revision }),
1608
+ entries: MINI_PROGRAM_PERMISSION_KEYS.flatMap((key) => permissions[key] ? [permissions[key]] : []),
1609
+ },
1610
+ temporaryPermissionKeys,
1611
+ grantValid: parsed.valid,
1612
+ };
1613
+ }
1614
+ function isRecord$1(value) {
1615
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
1616
+ }
1617
+ function hasExactFields(value, fields) {
1618
+ return isRecord$1(value) && Object.keys(value).length === fields.length
1619
+ && fields.every((field) => Object.prototype.hasOwnProperty.call(value, field));
1620
+ }
1621
+
1622
+ /** 由 scripts/generate-native-host-contract.mjs 生成,请勿手改。 */
1623
+ const MINI_PROGRAM_NATIVE_HOST_PROTOCOL_VERSION = 1;
1624
+ const MINI_PROGRAM_NATIVE_HOST_CONTRACT_REVISION = 1;
1625
+ const MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES = 65536;
1626
+ const MINI_PROGRAM_NATIVE_OPERATIONS = {
1627
+ "system": [
1628
+ "describe"
1629
+ ],
1630
+ "network": [
1631
+ "open",
1632
+ "read",
1633
+ "release",
1634
+ "transfer"
1635
+ ],
1636
+ "files": [
1637
+ "create",
1638
+ "remove",
1639
+ "exists",
1640
+ "openRead",
1641
+ "openWrite",
1642
+ "read",
1643
+ "release",
1644
+ "write",
1645
+ "stat",
1646
+ "list",
1647
+ "pickFiles",
1648
+ "pickDirectory",
1649
+ "saveFile"
1650
+ ]
1651
+ };
1652
+ const MINI_PROGRAM_NATIVE_HOST_DESCRIPTION = {
1653
+ "protocolVersion": 1,
1654
+ "contractRevision": 1,
1655
+ "operations": {
1656
+ "system": [
1657
+ "describe"
1658
+ ],
1659
+ "network": [
1660
+ "open",
1661
+ "read",
1662
+ "release",
1663
+ "transfer"
1664
+ ],
1665
+ "files": [
1666
+ "create",
1667
+ "remove",
1668
+ "exists",
1669
+ "openRead",
1670
+ "openWrite",
1671
+ "read",
1672
+ "release",
1673
+ "write",
1674
+ "stat",
1675
+ "list",
1676
+ "pickFiles",
1677
+ "pickDirectory",
1678
+ "saveFile"
1679
+ ]
1680
+ }
1681
+ };
1682
+
1683
+ /** Android WebMessageListener object 与 iOS WKScriptMessageHandler 共用名称。 */
1684
+ const MINI_PROGRAM_NATIVE_HOST_OBJECT = 'hbMiniProgramHost';
1685
+ /** Native 通过主文档 CustomEvent 回送 progress/result/error。 */
1686
+ const MINI_PROGRAM_NATIVE_HOST_MESSAGE_EVENT = 'heybox:miniprogram-native-host-message';
1687
+ function isMiniProgramNativeHostMessage(value) {
1688
+ if (!isRecord(value) || !isNonEmptyString(value.requestId))
1689
+ return false;
1690
+ if (value.type === 'progress')
1691
+ return Object.prototype.hasOwnProperty.call(value, 'payload');
1692
+ if (value.type === 'result')
1693
+ return !Object.prototype.hasOwnProperty.call(value, 'error');
1694
+ if (value.type !== 'error' || !isRecord(value.error))
1695
+ return false;
1696
+ return isNonEmptyString(value.error.code) && isNonEmptyString(value.error.message);
1697
+ }
1698
+ function isMiniProgramNativeHostDescription(value) {
1699
+ if (!isRecord(value) ||
1700
+ !isPositiveSafeInteger(value.protocolVersion) ||
1701
+ !isPositiveSafeInteger(value.contractRevision) ||
1702
+ !isRecord(value.operations))
1703
+ return false;
1704
+ const operations = value.operations;
1705
+ if (!isOperationList(operations.system) ||
1706
+ !isOperationList(operations.network) ||
1707
+ !isOperationList(operations.files))
1708
+ return false;
1709
+ return operations.system.includes('describe');
1710
+ }
1711
+ function isMiniProgramNativeBinaryChunk(value) {
1712
+ return (isRecord(value) &&
1713
+ isNonEmptyString(value.resourceId) &&
1714
+ typeof value.data === 'string' &&
1715
+ Number.isSafeInteger(value.byteLength) &&
1716
+ Number(value.byteLength) >= 0 &&
1717
+ Number(value.byteLength) <= MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES &&
1718
+ typeof value.eof === 'boolean' &&
1719
+ (Number(value.byteLength) > 0 || value.eof));
1720
+ }
1721
+ function isRecord(value) {
1722
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
1723
+ }
1724
+ function isNonEmptyString(value) {
1725
+ return typeof value === 'string' && value.length > 0;
1726
+ }
1727
+ function isPositiveSafeInteger(value) {
1728
+ return Number.isSafeInteger(value) && Number(value) > 0;
1729
+ }
1730
+ function isOperationList(value) {
1731
+ return (Array.isArray(value) &&
1732
+ value.every(operation => isNonEmptyString(operation) && operation === operation.trim()) &&
1733
+ new Set(value).size === value.length);
1734
+ }
1735
+
1736
+ /** 当前用户信息与登录能力支持的完整 scope 目录(canonical 顺序)。 */
1737
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile', 'steam_account'];
1738
+ /** Companion alias 的跨构建、Runtime 与 Host 规范。 */
1739
+ const COMPANION_ALIAS_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
1740
+ /** Companion Host 可跨 bridge 保留的稳定领域错误码。 */
1741
+ const COMPANION_ERROR_CODES = [
1742
+ 'COMPANION_UNSUPPORTED',
1743
+ 'COMPANION_PREVIEW_UNSUPPORTED',
1744
+ 'COMPANION_NOT_DECLARED',
1745
+ 'COMPANION_TARGET_UNSUPPORTED',
1746
+ 'COMPANION_NOT_PREPARED',
1747
+ 'COMPANION_PREPARATION_CANCELLED',
1748
+ 'COMPANION_DOWNLOAD_FAILED',
1749
+ 'COMPANION_DESCRIPTOR_UNAVAILABLE',
1750
+ 'COMPANION_ARCHIVE_INVALID',
1751
+ 'COMPANION_INTEGRITY_FAILED',
1752
+ 'COMPANION_ENTRYPOINT_INVALID',
1753
+ 'COMPANION_USER_CANCELLED',
1754
+ 'COMPANION_ELEVATION_DENIED',
1755
+ 'COMPANION_OS_BLOCKED',
1756
+ 'COMPANION_LAUNCH_FAILED',
1757
+ 'COMPANION_SESSION_VERSION_MISMATCH',
1758
+ 'COMPANION_SESSION_OWNERSHIP_LOST',
1759
+ 'COMPANION_SESSION_EXITED',
1760
+ 'COMPANION_PIPE_CLOSED',
1761
+ 'COMPANION_OUTPUT_LIMIT',
1762
+ 'COMPANION_PROCESS_CRASHED',
1763
+ 'COMPANION_ATTACHMENT_NOT_FOUND',
1764
+ 'COMPANION_NOTIFICATION_UNAVAILABLE',
1765
+ 'COMPANION_TERMINATE_FAILED',
1766
+ ];
1767
+
1768
+ export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, COMPANION_ALIAS_PATTERN, COMPANION_CANCEL_PREPARATION_METHOD, COMPANION_ERROR_CODES, COMPANION_GET_ACTIVE_SESSION_METHOD, COMPANION_GET_INFO_METHOD, COMPANION_GET_PREPARATION_STATUS_METHOD, COMPANION_LAUNCH_METHOD, COMPANION_OPEN_ATTACHMENT_METHOD, COMPANION_PREPARE_METHOD, COMPANION_SESSION_ACK_OUTPUT_METHOD, COMPANION_SESSION_CLOSE_STDIN_METHOD, COMPANION_SESSION_EXIT_EVENT, COMPANION_SESSION_OUTPUT_EVENT, COMPANION_SESSION_OWNERSHIP_LOST_EVENT, COMPANION_SESSION_TERMINATE_METHOD, COMPANION_SESSION_WRITE_METHOD, COMPANION_SHOW_NOTIFICATION_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, DIRECTORY_CREATE_METHOD, DIRECTORY_EXISTS_METHOD, DIRECTORY_LIST_METHOD, DIRECTORY_REMOVE_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_PICK_FILES_METHOD, FILES_SAVE_FILE_METHOD, FILE_CREATE_METHOD, FILE_EXISTS_METHOD, FILE_READ_BYTES_METHOD, FILE_READ_TEXT_METHOD, FILE_REMOVE_METHOD, FILE_STAT_METHOD, FILE_WRITE_BYTES_METHOD, FILE_WRITE_TEXT_METHOD, LOCAL_DEV_GRANT_PERMISSION_KEYS, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NATIVE_CHUNK_MAX_BYTES, MINI_PROGRAM_NATIVE_HOST_CONTRACT_REVISION, MINI_PROGRAM_NATIVE_HOST_DESCRIPTION, MINI_PROGRAM_NATIVE_HOST_MESSAGE_EVENT, MINI_PROGRAM_NATIVE_HOST_OBJECT, MINI_PROGRAM_NATIVE_HOST_PROTOCOL_VERSION, MINI_PROGRAM_NATIVE_OPERATIONS, MINI_PROGRAM_NO_DECLARATION_METHODS, MINI_PROGRAM_OPERATION_PROGRESS_METHOD, MINI_PROGRAM_PERMISSION_CATALOG, MINI_PROGRAM_PERMISSION_KEYS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_DOWNLOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_COPY_LINK_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_DISPLAY_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, composeLocalDevRuntimePermissions, createMiniProgramLocalDevGrant, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isMiniProgramByteArray, isMiniProgramCompanionPrepareProgress, isMiniProgramDirectoryDescriptor, isMiniProgramDirectoryRef, isMiniProgramDownloadProgressPayload, isMiniProgramFileDescriptor, isMiniProgramFileRef, isMiniProgramFileStat, isMiniProgramFileSystemEntityDescriptor, isMiniProgramNativeBinaryChunk, isMiniProgramNativeHostDescription, isMiniProgramNativeHostMessage, isMiniProgramOperationProgressPayload, isMiniProgramPathRootRef, isMiniProgramPermissionKey, isMiniProgramRelativePath, parseMiniProgramLocalDevGrant, parseMiniProgramRuntimePermissions };
@@ -1,5 +1,5 @@
1
1
  {
2
- "hash": "411af8cb9f6bffc9a10c7b1bdf8eda6f777d25e52e34b8b2e72eb9ab0b2ee095",
2
+ "hash": "6a5978e344f22fd060ff55f77a1248a7c161cd8fbf5be2b8c73eddd308e8fe78",
3
3
  "permissions": [
4
4
  {
5
5
  "key": "userInfo",
@@ -177,6 +177,7 @@
177
177
  "ui.hideLoading",
178
178
  "viewport.getWindowInfo",
179
179
  "viewport.setNavigationBarStyle",
180
+ "viewport.setDisplay",
180
181
  "device.vibrate",
181
182
  "navigation.close",
182
183
  "navigation.reload",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk-protocol",
3
- "version": "0.8.3-alpha.2",
3
+ "version": "0.8.3-alpha.4",
4
4
  "description": "Heybox mini-program iframe bridge wire contracts.",
5
5
  "sideEffects": false,
6
6
  "exports": {
package/src/bridge.ts CHANGED
@@ -18,6 +18,8 @@ import type { MiniProgramCapabilityProgress, MiniProgramProgressMethod } from '.
18
18
  export type MiniProgramBridgeMessageType = 'handshake' | 'request' | 'response' | 'event' | 'cancel';
19
19
  export type MiniProgramEventName =
20
20
  | 'launch'
21
+ | 'viewport_change'
22
+ | 'display_change'
21
23
  | 'ready'
22
24
  | 'show'
23
25
  | 'hide'
@@ -123,6 +125,12 @@ export interface MiniProgramBridgeProgressMessage<
123
125
  error?: never;
124
126
  }
125
127
  export interface MiniProgramEventPayloadMap {
128
+ /** 展示状态实际变化后通知;不回放初始状态,不支持或失败时不通知。 */
129
+ display_change: import('./payloads').MiniProgramDisplayState & {
130
+ /** api 为开发者调用;user 为用户点击宿主退出全屏按钮。同目标合并时保留首次发起来源。旧宿主可能不提供。 */
131
+ source?: 'api' | 'user';
132
+ };
133
+ viewport_change: import('./payloads').MiniProgramWindowInfoResult;
126
134
  launch: { timestamp: number; url?: string };
127
135
  ready: { timestamp: number };
128
136
  show: { timestamp: number; source?: string };