@heybox/hb-sdk-protocol 0.8.0-alpha → 0.8.0-alpha.12

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
@@ -10,6 +10,22 @@ const VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = 'viewport.setNavigationBarStyle
10
10
  const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage';
11
11
  const STORAGE_SET_STORAGE_METHOD = 'storage.setStorage';
12
12
  const NETWORK_REQUEST_METHOD = 'network.request';
13
+ const NETWORK_DOWNLOAD_METHOD = 'network.download';
14
+ const FILES_PICK_FILES_METHOD = 'files.pickFiles';
15
+ const FILES_PICK_DIRECTORY_METHOD = 'files.pickDirectory';
16
+ const FILES_SAVE_FILE_METHOD = 'files.saveFile';
17
+ const FILE_CREATE_METHOD = 'file.create';
18
+ const FILE_REMOVE_METHOD = 'file.remove';
19
+ const FILE_EXISTS_METHOD = 'file.exists';
20
+ const FILE_READ_TEXT_METHOD = 'file.readText';
21
+ const FILE_WRITE_TEXT_METHOD = 'file.writeText';
22
+ const FILE_READ_BYTES_METHOD = 'file.readBytes';
23
+ const FILE_WRITE_BYTES_METHOD = 'file.writeBytes';
24
+ const FILE_STAT_METHOD = 'file.stat';
25
+ const DIRECTORY_CREATE_METHOD = 'directory.create';
26
+ const DIRECTORY_REMOVE_METHOD = 'directory.remove';
27
+ const DIRECTORY_EXISTS_METHOD = 'directory.exists';
28
+ const DIRECTORY_LIST_METHOD = 'directory.list';
13
29
  const UI_SHOW_TOAST_METHOD = 'ui.showToast';
14
30
  const UI_SHOW_LOADING_METHOD = 'ui.showLoading';
15
31
  const UI_HIDE_LOADING_METHOD = 'ui.hideLoading';
@@ -24,95 +40,249 @@ const CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.getCu
24
40
  const CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.deleteCurrentUserEntry';
25
41
  const CLOUD_LEADERBOARD_GET_INFO_METHOD = 'cloud.leaderboard.getInfo';
26
42
  const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
27
- { method: AUTH_LOGIN_METHOD, module: 'auth', capability: AUTH_LOGIN_METHOD, permission: 'auth.login', risk: 'medium' },
28
- { method: USER_GET_INFO_METHOD, module: 'user', capability: USER_GET_INFO_METHOD, permission: 'user.getInfo', risk: 'medium' },
43
+ {
44
+ method: AUTH_LOGIN_METHOD,
45
+ module: 'auth',
46
+ capability: AUTH_LOGIN_METHOD,
47
+ requirement: { kind: 'all', permissions: ['userInfo'] },
48
+ risk: 'medium',
49
+ },
50
+ {
51
+ method: USER_GET_INFO_METHOD,
52
+ module: 'user',
53
+ capability: USER_GET_INFO_METHOD,
54
+ requirement: { kind: 'all', permissions: ['userInfo'] },
55
+ risk: 'medium',
56
+ },
29
57
  {
30
58
  method: USER_REVOKE_AUTHORIZATION_METHOD,
31
59
  module: 'user',
32
60
  capability: USER_REVOKE_AUTHORIZATION_METHOD,
33
- permission: 'user.revokeAuthorization',
61
+ requirement: { kind: 'none' },
34
62
  risk: 'high',
35
63
  },
36
64
  {
37
65
  method: USER_GET_STEAM_GAME_LIST_METHOD,
38
66
  module: 'user',
39
67
  capability: USER_GET_STEAM_GAME_LIST_METHOD,
40
- permission: 'user.platformAccount.steam',
68
+ requirement: { kind: 'all', permissions: ['steamLibrary'] },
41
69
  risk: 'high',
42
70
  },
43
- { method: SHARE_COPY_LINK_METHOD, module: 'share', capability: SHARE_COPY_LINK_METHOD, permission: 'share.copyLink', risk: 'medium' },
44
- { method: SHARE_SHOW_SHARE_MENU_METHOD, module: 'share', capability: SHARE_SHOW_SHARE_MENU_METHOD, permission: 'share.basic', risk: 'low' },
45
- { method: SHARE_SCREENSHOT_METHOD, module: 'share', capability: SHARE_SCREENSHOT_METHOD, permission: 'share.screenshot', risk: 'medium' },
71
+ {
72
+ method: SHARE_COPY_LINK_METHOD,
73
+ module: 'share',
74
+ capability: SHARE_COPY_LINK_METHOD,
75
+ requirement: { kind: 'all', permissions: ['share'] },
76
+ risk: 'medium',
77
+ },
78
+ {
79
+ method: SHARE_SHOW_SHARE_MENU_METHOD,
80
+ module: 'share',
81
+ capability: SHARE_SHOW_SHARE_MENU_METHOD,
82
+ requirement: { kind: 'all', permissions: ['share'] },
83
+ risk: 'low',
84
+ },
85
+ {
86
+ method: SHARE_SCREENSHOT_METHOD,
87
+ module: 'share',
88
+ capability: SHARE_SCREENSHOT_METHOD,
89
+ requirement: { kind: 'all', permissions: ['share'] },
90
+ risk: 'medium',
91
+ },
46
92
  {
47
93
  method: VIEWPORT_GET_WINDOW_INFO_METHOD,
48
94
  module: 'viewport',
49
95
  capability: VIEWPORT_GET_WINDOW_INFO_METHOD,
50
- permission: 'viewport.windowInfo',
96
+ requirement: { kind: 'none' },
51
97
  risk: 'low',
52
98
  },
53
99
  {
54
100
  method: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
55
101
  module: 'viewport',
56
102
  capability: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
57
- permission: 'viewport.navigationBarStyle',
103
+ requirement: { kind: 'none' },
58
104
  risk: 'low',
59
105
  },
60
- { method: STORAGE_GET_STORAGE_METHOD, module: 'storage', capability: STORAGE_GET_STORAGE_METHOD, permission: 'storage.read', risk: 'low' },
61
- { method: STORAGE_SET_STORAGE_METHOD, module: 'storage', capability: STORAGE_SET_STORAGE_METHOD, permission: 'storage.write', risk: 'medium' },
62
- { method: NETWORK_REQUEST_METHOD, module: 'network', capability: NETWORK_REQUEST_METHOD, permission: 'network.request', risk: 'high' },
63
- { method: UI_SHOW_TOAST_METHOD, module: 'ui', capability: UI_SHOW_TOAST_METHOD, permission: 'ui.toast', risk: 'low' },
64
- { method: UI_SHOW_LOADING_METHOD, module: 'ui', capability: UI_SHOW_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
65
- { method: UI_HIDE_LOADING_METHOD, module: 'ui', capability: UI_HIDE_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
66
- { method: DEVICE_VIBRATE_METHOD, module: 'device', capability: DEVICE_VIBRATE_METHOD, permission: 'device.vibrate', risk: 'low' },
106
+ {
107
+ method: STORAGE_GET_STORAGE_METHOD,
108
+ module: 'storage',
109
+ capability: STORAGE_GET_STORAGE_METHOD,
110
+ requirement: { kind: 'all', permissions: ['storage'] },
111
+ risk: 'low',
112
+ },
113
+ {
114
+ method: STORAGE_SET_STORAGE_METHOD,
115
+ module: 'storage',
116
+ capability: STORAGE_SET_STORAGE_METHOD,
117
+ requirement: { kind: 'all', permissions: ['storage'] },
118
+ risk: 'medium',
119
+ },
120
+ {
121
+ method: NETWORK_REQUEST_METHOD,
122
+ module: 'network',
123
+ capability: NETWORK_REQUEST_METHOD,
124
+ requirement: { kind: 'all', permissions: ['network'] },
125
+ risk: 'high',
126
+ },
127
+ {
128
+ method: NETWORK_DOWNLOAD_METHOD,
129
+ module: 'network',
130
+ capability: NETWORK_DOWNLOAD_METHOD,
131
+ requirement: { kind: 'all', permissions: ['network', 'filesystem'] },
132
+ risk: 'high',
133
+ },
134
+ {
135
+ method: FILES_PICK_FILES_METHOD,
136
+ module: 'files',
137
+ capability: FILES_PICK_FILES_METHOD,
138
+ requirement: { kind: 'all', permissions: ['filesystem'] },
139
+ risk: 'high',
140
+ },
141
+ {
142
+ method: FILES_PICK_DIRECTORY_METHOD,
143
+ module: 'files',
144
+ capability: FILES_PICK_DIRECTORY_METHOD,
145
+ requirement: { kind: 'all', permissions: ['filesystem'] },
146
+ risk: 'high',
147
+ },
148
+ {
149
+ method: FILES_SAVE_FILE_METHOD,
150
+ module: 'files',
151
+ capability: FILES_SAVE_FILE_METHOD,
152
+ requirement: { kind: 'all', permissions: ['filesystem'] },
153
+ risk: 'high',
154
+ },
155
+ {
156
+ method: FILE_CREATE_METHOD,
157
+ module: 'file',
158
+ capability: FILE_CREATE_METHOD,
159
+ requirement: { kind: 'all', permissions: ['filesystem'] },
160
+ risk: 'high',
161
+ },
162
+ {
163
+ method: FILE_REMOVE_METHOD,
164
+ module: 'file',
165
+ capability: FILE_REMOVE_METHOD,
166
+ requirement: { kind: 'all', permissions: ['filesystem'] },
167
+ risk: 'high',
168
+ },
169
+ {
170
+ method: FILE_EXISTS_METHOD,
171
+ module: 'file',
172
+ capability: FILE_EXISTS_METHOD,
173
+ requirement: { kind: 'all', permissions: ['filesystem'] },
174
+ risk: 'high',
175
+ },
176
+ {
177
+ method: FILE_READ_TEXT_METHOD,
178
+ module: 'file',
179
+ capability: FILE_READ_TEXT_METHOD,
180
+ requirement: { kind: 'all', permissions: ['filesystem'] },
181
+ risk: 'high',
182
+ },
183
+ {
184
+ method: FILE_WRITE_TEXT_METHOD,
185
+ module: 'file',
186
+ capability: FILE_WRITE_TEXT_METHOD,
187
+ requirement: { kind: 'all', permissions: ['filesystem'] },
188
+ risk: 'high',
189
+ },
190
+ {
191
+ method: FILE_READ_BYTES_METHOD,
192
+ module: 'file',
193
+ capability: FILE_READ_BYTES_METHOD,
194
+ requirement: { kind: 'all', permissions: ['filesystem'] },
195
+ risk: 'high',
196
+ },
197
+ {
198
+ method: FILE_WRITE_BYTES_METHOD,
199
+ module: 'file',
200
+ capability: FILE_WRITE_BYTES_METHOD,
201
+ requirement: { kind: 'all', permissions: ['filesystem'] },
202
+ risk: 'high',
203
+ },
204
+ { method: FILE_STAT_METHOD, module: 'file', capability: FILE_STAT_METHOD, requirement: { kind: 'all', permissions: ['filesystem'] }, risk: 'high' },
205
+ {
206
+ method: DIRECTORY_CREATE_METHOD,
207
+ module: 'directory',
208
+ capability: DIRECTORY_CREATE_METHOD,
209
+ requirement: { kind: 'all', permissions: ['filesystem'] },
210
+ risk: 'high',
211
+ },
212
+ {
213
+ method: DIRECTORY_REMOVE_METHOD,
214
+ module: 'directory',
215
+ capability: DIRECTORY_REMOVE_METHOD,
216
+ requirement: { kind: 'all', permissions: ['filesystem'] },
217
+ risk: 'high',
218
+ },
219
+ {
220
+ method: DIRECTORY_EXISTS_METHOD,
221
+ module: 'directory',
222
+ capability: DIRECTORY_EXISTS_METHOD,
223
+ requirement: { kind: 'all', permissions: ['filesystem'] },
224
+ risk: 'high',
225
+ },
226
+ {
227
+ method: DIRECTORY_LIST_METHOD,
228
+ module: 'directory',
229
+ capability: DIRECTORY_LIST_METHOD,
230
+ requirement: { kind: 'all', permissions: ['filesystem'] },
231
+ risk: 'high',
232
+ },
233
+ { method: UI_SHOW_TOAST_METHOD, module: 'ui', capability: UI_SHOW_TOAST_METHOD, requirement: { kind: 'none' }, risk: 'low' },
234
+ { method: UI_SHOW_LOADING_METHOD, module: 'ui', capability: UI_SHOW_LOADING_METHOD, requirement: { kind: 'none' }, risk: 'low' },
235
+ { method: UI_HIDE_LOADING_METHOD, module: 'ui', capability: UI_HIDE_LOADING_METHOD, requirement: { kind: 'none' }, risk: 'low' },
236
+ { method: DEVICE_VIBRATE_METHOD, module: 'device', capability: DEVICE_VIBRATE_METHOD, requirement: { kind: 'none' }, risk: 'low' },
67
237
  {
68
238
  method: DEVICE_SET_CLIPBOARD_METHOD,
69
239
  module: 'device',
70
240
  capability: DEVICE_SET_CLIPBOARD_METHOD,
71
- permission: 'device.clipboard.write',
241
+ requirement: { kind: 'all', permissions: ['clipboard'] },
72
242
  risk: 'medium',
73
243
  },
74
- { method: NAVIGATION_CLOSE_METHOD, module: 'navigation', capability: NAVIGATION_CLOSE_METHOD, permission: 'navigation.close', risk: 'medium' },
75
- { method: NAVIGATION_RELOAD_METHOD, module: 'navigation', capability: NAVIGATION_RELOAD_METHOD, permission: 'navigation.reload', risk: 'medium' },
244
+ { method: NAVIGATION_CLOSE_METHOD, module: 'navigation', capability: NAVIGATION_CLOSE_METHOD, requirement: { kind: 'none' }, risk: 'medium' },
245
+ { method: NAVIGATION_RELOAD_METHOD, module: 'navigation', capability: NAVIGATION_RELOAD_METHOD, requirement: { kind: 'none' }, risk: 'medium' },
76
246
  {
77
247
  method: NAVIGATION_OPEN_APP_PAGE_METHOD,
78
248
  module: 'navigation',
79
249
  capability: NAVIGATION_OPEN_APP_PAGE_METHOD,
80
- permission: 'navigation.openAppPage',
250
+ requirement: { kind: 'none' },
81
251
  risk: 'medium',
82
252
  },
83
253
  {
84
254
  method: CLOUD_LEADERBOARD_SUBMIT_METHOD,
85
255
  module: 'cloud',
86
256
  capability: CLOUD_LEADERBOARD_SUBMIT_METHOD,
87
- permission: 'cloud.leaderboard.write',
257
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
88
258
  risk: 'medium',
89
259
  },
90
260
  {
91
261
  method: CLOUD_LEADERBOARD_GET_LIST_METHOD,
92
262
  module: 'cloud',
93
263
  capability: CLOUD_LEADERBOARD_GET_LIST_METHOD,
94
- permission: 'cloud.leaderboard.read',
264
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
95
265
  risk: 'low',
96
266
  },
97
267
  {
98
268
  method: CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD,
99
269
  module: 'cloud',
100
270
  capability: CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD,
101
- permission: 'cloud.leaderboard.currentUserEntry.read',
271
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
102
272
  risk: 'medium',
103
273
  },
104
274
  {
105
275
  method: CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD,
106
276
  module: 'cloud',
107
277
  capability: CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD,
108
- permission: 'cloud.leaderboard.currentUserEntry.delete',
278
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
109
279
  risk: 'medium',
110
280
  },
111
281
  {
112
282
  method: CLOUD_LEADERBOARD_GET_INFO_METHOD,
113
283
  module: 'cloud',
114
284
  capability: CLOUD_LEADERBOARD_GET_INFO_METHOD,
115
- permission: 'cloud.leaderboard.info.read',
285
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
116
286
  risk: 'low',
117
287
  },
118
288
  ];
@@ -124,21 +294,279 @@ const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
124
294
  const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
125
295
  const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
126
296
  const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
297
+ const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress';
127
298
 
128
299
  function isMiniProgramBridgeMessage(value) {
129
- if (!value || typeof value !== 'object')
300
+ if (!isRecord$1(value))
130
301
  return false;
131
- const message = value;
132
- return (message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
133
- (message.version === 1 || message.version === 2) &&
134
- typeof message.nonce === 'string' &&
135
- typeof message.type === 'string');
302
+ if (value.namespace !== MINI_PROGRAM_MESSAGE_NAMESPACE || (value.version !== 1 && value.version !== 2) || !isNonEmptyString(value.nonce)) {
303
+ return false;
304
+ }
305
+ if (value.type === 'handshake') {
306
+ return isNonEmptyString(value.id) && value.method === SDK_HANDSHAKE_METHOD && value.error === undefined && isSDKHandshakePayload(value.payload);
307
+ }
308
+ if (value.type === 'request') {
309
+ return isNonEmptyString(value.id) && isNonEmptyString(value.method) && value.error === undefined;
310
+ }
311
+ if (value.type === 'response') {
312
+ return (isNonEmptyString(value.id) &&
313
+ (value.method === undefined || isNonEmptyString(value.method)) &&
314
+ (value.error === undefined || isBridgeError(value.error)));
315
+ }
316
+ if (value.type === 'event') {
317
+ if (!isNonEmptyString(value.method) || value.error !== undefined)
318
+ return false;
319
+ if (value.method === MINI_PROGRAM_OPERATION_PROGRESS_METHOD) {
320
+ return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramDownloadProgressPayload(value.payload);
321
+ }
322
+ return value.id === undefined || isNonEmptyString(value.id);
323
+ }
324
+ if (value.type === 'cancel') {
325
+ return (value.version === 2 && isNonEmptyString(value.id) && value.method === undefined && value.payload === undefined && value.error === undefined);
326
+ }
327
+ return false;
328
+ }
329
+ function isMiniProgramRelativePath(value) {
330
+ if (typeof value !== 'string' || !value || value.startsWith('/') || value.endsWith('/')) {
331
+ return false;
332
+ }
333
+ if (/[\\\u0000-\u001f\u007f]/.test(value))
334
+ return false;
335
+ return value.split('/').every((segment) => Boolean(segment) && segment !== '.' && segment !== '..');
336
+ }
337
+ function isMiniProgramPathRootRef(value) {
338
+ if (!isRecord$1(value))
339
+ return false;
340
+ if (value.kind === 'sandbox')
341
+ return hasOnlyKeys(value, ['kind']);
342
+ return value.kind === 'directory' && isNonEmptyString(value.handleId) && hasOnlyKeys(value, ['kind', 'handleId']);
343
+ }
344
+ function isMiniProgramFileRef(value) {
345
+ if (!isRecord$1(value) || value.kind !== 'file')
346
+ return false;
347
+ if (isNonEmptyString(value.handleId)) {
348
+ return hasOnlyKeys(value, ['kind', 'handleId']);
349
+ }
350
+ return (isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
351
+ }
352
+ function isMiniProgramDirectoryRef(value) {
353
+ if (!isRecord$1(value) || value.kind !== 'directory')
354
+ return false;
355
+ if (isNonEmptyString(value.handleId)) {
356
+ return hasOnlyKeys(value, ['kind', 'handleId']);
357
+ }
358
+ return (isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
359
+ }
360
+ function isMiniProgramFileDescriptor(value) {
361
+ return (isRecord$1(value) &&
362
+ value.kind === 'file' &&
363
+ isNonEmptyString(value.name) &&
364
+ isFileMode(value.mode) &&
365
+ isMiniProgramFileRef(value.ref) &&
366
+ hasOnlyKeys(value, ['kind', 'name', 'mode', 'ref']));
367
+ }
368
+ function isMiniProgramDirectoryDescriptor(value) {
369
+ return (isRecord$1(value) &&
370
+ value.kind === 'directory' &&
371
+ isNonEmptyString(value.name) &&
372
+ isFileMode(value.mode) &&
373
+ isMiniProgramDirectoryRef(value.ref) &&
374
+ hasOnlyKeys(value, ['kind', 'name', 'mode', 'ref']));
375
+ }
376
+ function isMiniProgramFileSystemEntityDescriptor(value) {
377
+ return isMiniProgramFileDescriptor(value) || isMiniProgramDirectoryDescriptor(value);
378
+ }
379
+ function isMiniProgramByteArray(value) {
380
+ return value instanceof Uint8Array && value.buffer instanceof ArrayBuffer;
381
+ }
382
+ function isMiniProgramFileStat(value) {
383
+ return (isRecord$1(value) &&
384
+ value.kind === 'file' &&
385
+ isNonNegativeSafeInteger(value.size) &&
386
+ (value.modifiedAt === undefined || isNonNegativeFiniteNumber(value.modifiedAt)) &&
387
+ (value.createdAt === undefined || isNonNegativeFiniteNumber(value.createdAt)) &&
388
+ hasOnlyKeys(value, ['kind', 'size', 'modifiedAt', 'createdAt']));
389
+ }
390
+ function isMiniProgramDownloadProgressPayload(value) {
391
+ if (!isRecord$1(value) ||
392
+ !isNonNegativeSafeInteger(value.loaded) ||
393
+ typeof value.lengthComputable !== 'boolean' ||
394
+ !hasOnlyKeys(value, ['loaded', 'total', 'lengthComputable'])) {
395
+ return false;
396
+ }
397
+ if (!value.lengthComputable)
398
+ return value.total === undefined;
399
+ return isNonNegativeSafeInteger(value.total) && value.loaded <= value.total;
400
+ }
401
+ function isSDKHandshakePayload(value) {
402
+ return isRecord$1(value) && isNonEmptyString(value.href) && typeof value.userAgent === 'string' && isNonEmptyString(value.sdkVersion);
403
+ }
404
+ function isBridgeError(value) {
405
+ return isRecord$1(value) && isNonEmptyString(value.code) && typeof value.message === 'string';
406
+ }
407
+ function isFileMode(value) {
408
+ return value === 'read' || value === 'readwrite';
409
+ }
410
+ function isNonNegativeSafeInteger(value) {
411
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
412
+ }
413
+ function isNonNegativeFiniteNumber(value) {
414
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0;
415
+ }
416
+ function isNonEmptyString(value) {
417
+ return typeof value === 'string' && value.length > 0;
418
+ }
419
+ function hasOnlyKeys(value, allowedKeys) {
420
+ const allowed = new Set(allowedKeys);
421
+ return Object.keys(value).every((key) => allowed.has(key));
422
+ }
423
+ function isRecord$1(value) {
424
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
136
425
  }
137
426
 
138
427
  /** 当前用户信息与登录能力支持的完整 scope 目录。 */
139
428
  const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
140
429
 
141
- const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
430
+ const MINI_PROGRAM_PERMISSION_KEYS = [
431
+ 'userInfo',
432
+ 'steamLibrary',
433
+ 'share',
434
+ 'storage',
435
+ 'filesystem',
436
+ 'clipboard',
437
+ 'leaderboard',
438
+ 'network',
439
+ ];
440
+ const MINI_PROGRAM_PERMISSION_CATALOG = [
441
+ {
442
+ key: 'userInfo',
443
+ name: '用户信息',
444
+ description: '登录小程序并读取当前用户的授权信息。',
445
+ access: 'declaration',
446
+ risk: 'medium',
447
+ config: {},
448
+ methods: ['auth.login', 'user.getInfo'],
449
+ conditions: ['继续执行黑盒登录、用户授权和可信手势规则。'],
450
+ },
451
+ {
452
+ key: 'steamLibrary',
453
+ name: 'Steam 游戏库',
454
+ description: '读取当前用户授权的 Steam 游戏库。',
455
+ access: 'declaration',
456
+ risk: 'high',
457
+ config: {},
458
+ methods: ['user.getSteamGameList'],
459
+ conditions: ['继续执行账号绑定和数据可用性规则。'],
460
+ },
461
+ {
462
+ key: 'share',
463
+ name: '分享',
464
+ description: '使用小程序分享、分享菜单和截图能力。',
465
+ access: 'declaration',
466
+ risk: 'medium',
467
+ config: {},
468
+ methods: ['share.copyLink', 'share.showShareMenu', 'share.screenshot'],
469
+ conditions: ['继续执行分享参数校验和 Host 支持检查。'],
470
+ },
471
+ {
472
+ key: 'storage',
473
+ name: '键值存储',
474
+ description: '读写按小程序隔离的简单键值数据。',
475
+ access: 'declaration',
476
+ risk: 'medium',
477
+ config: {},
478
+ methods: ['storage.getStorage', 'storage.setStorage'],
479
+ conditions: ['仅用于简单键值存储,不包含文件系统。'],
480
+ },
481
+ {
482
+ key: 'filesystem',
483
+ name: '文件系统',
484
+ description: '访问小程序沙盒文件和用户选择的外部文件。',
485
+ access: 'declaration',
486
+ risk: 'high',
487
+ config: {},
488
+ methods: [
489
+ 'network.download',
490
+ 'files.pickFiles',
491
+ 'files.pickDirectory',
492
+ 'files.saveFile',
493
+ 'file.create',
494
+ 'file.remove',
495
+ 'file.exists',
496
+ 'file.readText',
497
+ 'file.writeText',
498
+ 'file.readBytes',
499
+ 'file.writeBytes',
500
+ 'file.stat',
501
+ 'directory.create',
502
+ 'directory.remove',
503
+ 'directory.exists',
504
+ 'directory.list',
505
+ ],
506
+ conditions: ['外部文件继续要求有效的用户选择、会话句柄和匹配的读写模式。'],
507
+ },
508
+ {
509
+ key: 'clipboard',
510
+ name: '剪贴板',
511
+ description: '向系统剪贴板写入文本。',
512
+ access: 'declaration',
513
+ risk: 'medium',
514
+ config: {},
515
+ methods: ['device.setClipboard'],
516
+ conditions: ['继续执行文本长度和 Host 支持限制。'],
517
+ },
518
+ {
519
+ key: 'leaderboard',
520
+ name: '排行榜',
521
+ description: '读写小程序云排行榜。',
522
+ access: 'declaration',
523
+ risk: 'medium',
524
+ config: {},
525
+ methods: [
526
+ 'cloud.leaderboard.submit',
527
+ 'cloud.leaderboard.getList',
528
+ 'cloud.leaderboard.getCurrentUserEntry',
529
+ 'cloud.leaderboard.deleteCurrentUserEntry',
530
+ 'cloud.leaderboard.getInfo',
531
+ ],
532
+ conditions: ['排行榜必须已创建,用户和资源规则保持不变。'],
533
+ },
534
+ {
535
+ key: 'network',
536
+ name: '网络',
537
+ description: '通过 network 模块请求或下载外部资源。',
538
+ access: 'platform-approval',
539
+ risk: 'high',
540
+ config: {
541
+ useOfficialDomain: {
542
+ type: 'boolean',
543
+ required: false,
544
+ default: false,
545
+ description: '是否申请访问小黑盒官方域名。',
546
+ },
547
+ },
548
+ methods: ['network.request', 'network.download'],
549
+ conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
550
+ },
551
+ ];
552
+ const MINI_PROGRAM_NO_DECLARATION_METHODS = [
553
+ 'user.revokeAuthorization',
554
+ 'ui.showToast',
555
+ 'ui.showLoading',
556
+ 'ui.hideLoading',
557
+ 'viewport.getWindowInfo',
558
+ 'viewport.setNavigationBarStyle',
559
+ 'device.vibrate',
560
+ 'navigation.close',
561
+ 'navigation.reload',
562
+ 'navigation.openAppPage',
563
+ ];
564
+ const PERMISSION_KEY_SET = new Set(MINI_PROGRAM_PERMISSION_KEYS);
565
+ function isMiniProgramPermissionKey(key) {
566
+ return PERMISSION_KEY_SET.has(key);
567
+ }
568
+
569
+ const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(MINI_PROGRAM_PERMISSION_KEYS);
142
570
  function isManagedMiniProgramRuntimePermissionKey(key) {
143
571
  return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
144
572
  }
@@ -155,20 +583,36 @@ function parseMiniProgramRuntimePermissions(snapshot) {
155
583
  if (!isRecord(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
156
584
  return { valid: false, permissions: {} };
157
585
  }
158
- const key = rawEntry.key.trim();
159
- if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled') || !isRecord(rawEntry.config)) {
586
+ const inputKey = rawEntry.key.trim();
587
+ const key = inputKey === 'network.request' ? 'network' : inputKey;
588
+ if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled')) {
160
589
  return { valid: false, permissions: {} };
161
590
  }
162
591
  seenKeys.add(key);
163
- if (!isManagedMiniProgramRuntimePermissionKey(key))
592
+ if (!isManagedMiniProgramRuntimePermissionKey(key)) {
593
+ if (!isRecord(rawEntry.config))
594
+ return { valid: false, permissions: {} };
595
+ continue;
596
+ }
597
+ if (key === 'network') {
598
+ const config = rawEntry.config;
599
+ if (!isRecord(config) || typeof config.useOfficialDomain !== 'boolean') {
600
+ return { valid: false, permissions: {} };
601
+ }
602
+ permissions[key] = {
603
+ key,
604
+ status: rawEntry.status,
605
+ config: { useOfficialDomain: config.useOfficialDomain },
606
+ };
164
607
  continue;
165
- if (key === 'network.request' && typeof rawEntry.config.useOfficialDomain !== 'boolean') {
608
+ }
609
+ if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
166
610
  return { valid: false, permissions: {} };
167
611
  }
168
612
  permissions[key] = {
169
613
  key,
170
614
  status: rawEntry.status,
171
- config: { useOfficialDomain: rawEntry.config.useOfficialDomain },
615
+ config: {},
172
616
  };
173
617
  }
174
618
  return { valid: true, permissions };
@@ -177,4 +621,4 @@ function isRecord(value) {
177
621
  return typeof value === 'object' && value !== null && !Array.isArray(value);
178
622
  }
179
623
 
180
- 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, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_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, parseMiniProgramRuntimePermissions };
624
+ 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, 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_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, isMiniProgramDirectoryDescriptor, isMiniProgramDirectoryRef, isMiniProgramDownloadProgressPayload, isMiniProgramFileDescriptor, isMiniProgramFileRef, isMiniProgramFileStat, isMiniProgramFileSystemEntityDescriptor, isMiniProgramPathRootRef, isMiniProgramPermissionKey, isMiniProgramRelativePath, parseMiniProgramRuntimePermissions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk-protocol",
3
- "version": "0.8.0-alpha",
3
+ "version": "0.8.0-alpha.12",
4
4
  "description": "Heybox mini-program iframe bridge wire contracts.",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -40,6 +40,9 @@
40
40
  "test:types": "tsc -p tsconfig.dts.json --noEmit --pretty false",
41
41
  "clean": "rimraf ./dist && rimraf ./types",
42
42
  "check:boundary": "node scripts/check-boundary.cjs",
43
+ "gen:permission-catalog": "pnpm run build:lib && node scripts/generate-permission-catalog.mjs",
44
+ "check:permission-catalog": "pnpm run build:lib && node scripts/generate-permission-catalog.mjs --check",
45
+ "pretest:unit": "pnpm run build:types",
43
46
  "test:unit": "NODE_OPTIONS='--conditions=heybox' vitest run",
44
47
  "test:watch": "NODE_OPTIONS='--conditions=heybox' vitest"
45
48
  }