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

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/src/bridge.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { MINI_PROGRAM_MESSAGE_NAMESPACE } from './constants';
2
- import type { UserInfoAuthorization } from './payloads';
1
+ import { MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_OPERATION_PROGRESS_METHOD } from './constants';
2
+ import type { DownloadProgressPayload, UserInfoAuthorization } from './payloads';
3
3
 
4
- export type MiniProgramBridgeMessageType = 'handshake' | 'request' | 'response' | 'event';
4
+ export type MiniProgramBridgeMessageType = 'handshake' | 'request' | 'response' | 'event' | 'cancel';
5
5
  export type MiniProgramEventName =
6
6
  | 'launch'
7
7
  | 'ready'
@@ -56,6 +56,24 @@ export interface MiniProgramBridgeMessage<TPayload = unknown> {
56
56
  payload?: TPayload;
57
57
  error?: MiniProgramBridgeError;
58
58
  }
59
+
60
+ export interface MiniProgramBridgeCancelMessage extends MiniProgramBridgeMessage<never> {
61
+ version: 2;
62
+ type: 'cancel';
63
+ id: string;
64
+ method?: never;
65
+ payload?: never;
66
+ error?: never;
67
+ }
68
+
69
+ export interface MiniProgramBridgeProgressMessage extends MiniProgramBridgeMessage<DownloadProgressPayload> {
70
+ version: 2;
71
+ type: 'event';
72
+ id: string;
73
+ method: typeof MINI_PROGRAM_OPERATION_PROGRESS_METHOD;
74
+ payload: DownloadProgressPayload;
75
+ error?: never;
76
+ }
59
77
  export interface MiniProgramEventPayloadMap {
60
78
  launch: { timestamp: number; url?: string };
61
79
  ready: { timestamp: number };
@@ -3,6 +3,14 @@ import type {
3
3
  CloseResult,
4
4
  CopyLinkPayload,
5
5
  CopyLinkResult,
6
+ DirectoryCreatePayload,
7
+ DirectoryCreateResult,
8
+ DirectoryExistsPayload,
9
+ DirectoryExistsResult,
10
+ DirectoryListPayload,
11
+ DirectoryListResult,
12
+ DirectoryRemovePayload,
13
+ DirectoryRemoveResult,
6
14
  DeleteCurrentUserLeaderboardEntryPayload,
7
15
  DeleteCurrentUserLeaderboardEntryResult,
8
16
  GetCurrentUserLeaderboardEntryPayload,
@@ -21,16 +29,40 @@ import type {
21
29
  GetWindowInfoResult,
22
30
  HideLoadingPayload,
23
31
  HideLoadingResult,
32
+ FileCreatePayload,
33
+ FileCreateResult,
34
+ FileExistsPayload,
35
+ FileExistsResult,
36
+ FileReadBytesPayload,
37
+ FileReadBytesResult,
38
+ FileReadTextPayload,
39
+ FileReadTextResult,
40
+ FileRemovePayload,
41
+ FileRemoveResult,
42
+ FileStatPayload,
43
+ FileStatResult,
44
+ FileWriteBytesPayload,
45
+ FileWriteBytesResult,
46
+ FileWriteTextPayload,
47
+ FileWriteTextResult,
24
48
  LoginPayload,
25
49
  LoginResult,
50
+ NetworkDownloadPayload,
51
+ NetworkDownloadResult,
26
52
  NetworkRequestPayload,
27
53
  NetworkResponsePayload,
28
54
  OpenAppPagePayload,
29
55
  OpenAppPageResult,
56
+ PickDirectoryPayload,
57
+ PickDirectoryResult,
58
+ PickFilesPayload,
59
+ PickFilesResult,
30
60
  ReloadPayload,
31
61
  ReloadResult,
32
62
  ScreenshotPayload,
33
63
  ScreenshotResult,
64
+ SaveFilePayload,
65
+ SaveFileResult,
34
66
  SetClipboardPayload,
35
67
  SetClipboardResult,
36
68
  SetNavigationBarStylePayload,
@@ -47,6 +79,7 @@ import type {
47
79
  VibratePayload,
48
80
  VibrateResult,
49
81
  } from './payloads';
82
+ import type { MiniProgramPermissionRequirement } from './permission-catalog';
50
83
 
51
84
  export const AUTH_LOGIN_METHOD = 'auth.login' as const;
52
85
  export const USER_GET_INFO_METHOD = 'user.getInfo' as const;
@@ -60,6 +93,22 @@ export const VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = 'viewport.setNavigationB
60
93
  export const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage' as const;
61
94
  export const STORAGE_SET_STORAGE_METHOD = 'storage.setStorage' as const;
62
95
  export const NETWORK_REQUEST_METHOD = 'network.request' as const;
96
+ export const NETWORK_DOWNLOAD_METHOD = 'network.download' as const;
97
+ export const FILES_PICK_FILES_METHOD = 'files.pickFiles' as const;
98
+ export const FILES_PICK_DIRECTORY_METHOD = 'files.pickDirectory' as const;
99
+ export const FILES_SAVE_FILE_METHOD = 'files.saveFile' as const;
100
+ export const FILE_CREATE_METHOD = 'file.create' as const;
101
+ export const FILE_REMOVE_METHOD = 'file.remove' as const;
102
+ export const FILE_EXISTS_METHOD = 'file.exists' as const;
103
+ export const FILE_READ_TEXT_METHOD = 'file.readText' as const;
104
+ export const FILE_WRITE_TEXT_METHOD = 'file.writeText' as const;
105
+ export const FILE_READ_BYTES_METHOD = 'file.readBytes' as const;
106
+ export const FILE_WRITE_BYTES_METHOD = 'file.writeBytes' as const;
107
+ export const FILE_STAT_METHOD = 'file.stat' as const;
108
+ export const DIRECTORY_CREATE_METHOD = 'directory.create' as const;
109
+ export const DIRECTORY_REMOVE_METHOD = 'directory.remove' as const;
110
+ export const DIRECTORY_EXISTS_METHOD = 'directory.exists' as const;
111
+ export const DIRECTORY_LIST_METHOD = 'directory.list' as const;
63
112
  export const UI_SHOW_TOAST_METHOD = 'ui.showToast' as const;
64
113
  export const UI_SHOW_LOADING_METHOD = 'ui.showLoading' as const;
65
114
  export const UI_HIDE_LOADING_METHOD = 'ui.hideLoading' as const;
@@ -79,7 +128,22 @@ export type MiniProgramUserMethod = typeof USER_GET_INFO_METHOD | typeof USER_RE
79
128
  export type MiniProgramShareMethod = typeof SHARE_COPY_LINK_METHOD | typeof SHARE_SHOW_SHARE_MENU_METHOD | typeof SHARE_SCREENSHOT_METHOD;
80
129
  export type MiniProgramViewportMethod = typeof VIEWPORT_GET_WINDOW_INFO_METHOD | typeof VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD;
81
130
  export type MiniProgramStorageMethod = typeof STORAGE_GET_STORAGE_METHOD | typeof STORAGE_SET_STORAGE_METHOD;
82
- export type MiniProgramNetworkMethod = typeof NETWORK_REQUEST_METHOD;
131
+ export type MiniProgramNetworkMethod = typeof NETWORK_REQUEST_METHOD | typeof NETWORK_DOWNLOAD_METHOD;
132
+ export type MiniProgramFilesMethod = typeof FILES_PICK_FILES_METHOD | typeof FILES_PICK_DIRECTORY_METHOD | typeof FILES_SAVE_FILE_METHOD;
133
+ export type MiniProgramFileMethod =
134
+ | typeof FILE_CREATE_METHOD
135
+ | typeof FILE_REMOVE_METHOD
136
+ | typeof FILE_EXISTS_METHOD
137
+ | typeof FILE_READ_TEXT_METHOD
138
+ | typeof FILE_WRITE_TEXT_METHOD
139
+ | typeof FILE_READ_BYTES_METHOD
140
+ | typeof FILE_WRITE_BYTES_METHOD
141
+ | typeof FILE_STAT_METHOD;
142
+ export type MiniProgramDirectoryMethod =
143
+ | typeof DIRECTORY_CREATE_METHOD
144
+ | typeof DIRECTORY_REMOVE_METHOD
145
+ | typeof DIRECTORY_EXISTS_METHOD
146
+ | typeof DIRECTORY_LIST_METHOD;
83
147
  export type MiniProgramUiMethod = typeof UI_SHOW_TOAST_METHOD | typeof UI_SHOW_LOADING_METHOD | typeof UI_HIDE_LOADING_METHOD;
84
148
  export type MiniProgramDeviceMethod = typeof DEVICE_VIBRATE_METHOD | typeof DEVICE_SET_CLIPBOARD_METHOD;
85
149
  export type MiniProgramNavigationMethod = typeof NAVIGATION_CLOSE_METHOD | typeof NAVIGATION_RELOAD_METHOD | typeof NAVIGATION_OPEN_APP_PAGE_METHOD;
@@ -96,111 +160,281 @@ export type MiniProgramBridgeMethod =
96
160
  | MiniProgramViewportMethod
97
161
  | MiniProgramStorageMethod
98
162
  | MiniProgramNetworkMethod
163
+ | MiniProgramFilesMethod
164
+ | MiniProgramFileMethod
165
+ | MiniProgramDirectoryMethod
99
166
  | MiniProgramUiMethod
100
167
  | MiniProgramDeviceMethod
101
168
  | MiniProgramNavigationMethod
102
169
  | MiniProgramCloudMethod;
103
- export type MiniProgramCapabilityModule = 'auth' | 'user' | 'share' | 'viewport' | 'storage' | 'network' | 'ui' | 'device' | 'navigation' | 'cloud';
170
+ export type MiniProgramCapabilityModule =
171
+ | 'auth'
172
+ | 'user'
173
+ | 'share'
174
+ | 'viewport'
175
+ | 'storage'
176
+ | 'network'
177
+ | 'files'
178
+ | 'file'
179
+ | 'directory'
180
+ | 'ui'
181
+ | 'device'
182
+ | 'navigation'
183
+ | 'cloud';
104
184
  export type MiniProgramCapabilityRisk = 'low' | 'medium' | 'high';
105
185
 
106
186
  export interface MiniProgramCapabilityDefinition {
107
187
  method: MiniProgramBridgeMethod;
108
188
  module: MiniProgramCapabilityModule;
109
189
  capability: MiniProgramBridgeMethod;
110
- permission: string;
190
+ requirement: MiniProgramPermissionRequirement;
111
191
  risk: MiniProgramCapabilityRisk;
112
192
  }
113
193
 
114
194
  export const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
115
- { method: AUTH_LOGIN_METHOD, module: 'auth', capability: AUTH_LOGIN_METHOD, permission: 'auth.login', risk: 'medium' },
116
- { method: USER_GET_INFO_METHOD, module: 'user', capability: USER_GET_INFO_METHOD, permission: 'user.getInfo', risk: 'medium' },
195
+ {
196
+ method: AUTH_LOGIN_METHOD,
197
+ module: 'auth',
198
+ capability: AUTH_LOGIN_METHOD,
199
+ requirement: { kind: 'all', permissions: ['userInfo'] },
200
+ risk: 'medium',
201
+ },
202
+ {
203
+ method: USER_GET_INFO_METHOD,
204
+ module: 'user',
205
+ capability: USER_GET_INFO_METHOD,
206
+ requirement: { kind: 'all', permissions: ['userInfo'] },
207
+ risk: 'medium',
208
+ },
117
209
  {
118
210
  method: USER_REVOKE_AUTHORIZATION_METHOD,
119
211
  module: 'user',
120
212
  capability: USER_REVOKE_AUTHORIZATION_METHOD,
121
- permission: 'user.revokeAuthorization',
213
+ requirement: { kind: 'none' },
122
214
  risk: 'high',
123
215
  },
124
216
  {
125
217
  method: USER_GET_STEAM_GAME_LIST_METHOD,
126
218
  module: 'user',
127
219
  capability: USER_GET_STEAM_GAME_LIST_METHOD,
128
- permission: 'user.platformAccount.steam',
220
+ requirement: { kind: 'all', permissions: ['steamLibrary'] },
129
221
  risk: 'high',
130
222
  },
131
- { method: SHARE_COPY_LINK_METHOD, module: 'share', capability: SHARE_COPY_LINK_METHOD, permission: 'share.copyLink', risk: 'medium' },
132
- { method: SHARE_SHOW_SHARE_MENU_METHOD, module: 'share', capability: SHARE_SHOW_SHARE_MENU_METHOD, permission: 'share.basic', risk: 'low' },
133
- { method: SHARE_SCREENSHOT_METHOD, module: 'share', capability: SHARE_SCREENSHOT_METHOD, permission: 'share.screenshot', risk: 'medium' },
223
+ {
224
+ method: SHARE_COPY_LINK_METHOD,
225
+ module: 'share',
226
+ capability: SHARE_COPY_LINK_METHOD,
227
+ requirement: { kind: 'all', permissions: ['share'] },
228
+ risk: 'medium',
229
+ },
230
+ {
231
+ method: SHARE_SHOW_SHARE_MENU_METHOD,
232
+ module: 'share',
233
+ capability: SHARE_SHOW_SHARE_MENU_METHOD,
234
+ requirement: { kind: 'all', permissions: ['share'] },
235
+ risk: 'low',
236
+ },
237
+ {
238
+ method: SHARE_SCREENSHOT_METHOD,
239
+ module: 'share',
240
+ capability: SHARE_SCREENSHOT_METHOD,
241
+ requirement: { kind: 'all', permissions: ['share'] },
242
+ risk: 'medium',
243
+ },
134
244
  {
135
245
  method: VIEWPORT_GET_WINDOW_INFO_METHOD,
136
246
  module: 'viewport',
137
247
  capability: VIEWPORT_GET_WINDOW_INFO_METHOD,
138
- permission: 'viewport.windowInfo',
248
+ requirement: { kind: 'none' },
139
249
  risk: 'low',
140
250
  },
141
251
  {
142
252
  method: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
143
253
  module: 'viewport',
144
254
  capability: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
145
- permission: 'viewport.navigationBarStyle',
255
+ requirement: { kind: 'none' },
146
256
  risk: 'low',
147
257
  },
148
- { method: STORAGE_GET_STORAGE_METHOD, module: 'storage', capability: STORAGE_GET_STORAGE_METHOD, permission: 'storage.read', risk: 'low' },
149
- { method: STORAGE_SET_STORAGE_METHOD, module: 'storage', capability: STORAGE_SET_STORAGE_METHOD, permission: 'storage.write', risk: 'medium' },
150
- { method: NETWORK_REQUEST_METHOD, module: 'network', capability: NETWORK_REQUEST_METHOD, permission: 'network.request', risk: 'high' },
151
- { method: UI_SHOW_TOAST_METHOD, module: 'ui', capability: UI_SHOW_TOAST_METHOD, permission: 'ui.toast', risk: 'low' },
152
- { method: UI_SHOW_LOADING_METHOD, module: 'ui', capability: UI_SHOW_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
153
- { method: UI_HIDE_LOADING_METHOD, module: 'ui', capability: UI_HIDE_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
154
- { method: DEVICE_VIBRATE_METHOD, module: 'device', capability: DEVICE_VIBRATE_METHOD, permission: 'device.vibrate', risk: 'low' },
258
+ {
259
+ method: STORAGE_GET_STORAGE_METHOD,
260
+ module: 'storage',
261
+ capability: STORAGE_GET_STORAGE_METHOD,
262
+ requirement: { kind: 'all', permissions: ['storage'] },
263
+ risk: 'low',
264
+ },
265
+ {
266
+ method: STORAGE_SET_STORAGE_METHOD,
267
+ module: 'storage',
268
+ capability: STORAGE_SET_STORAGE_METHOD,
269
+ requirement: { kind: 'all', permissions: ['storage'] },
270
+ risk: 'medium',
271
+ },
272
+ {
273
+ method: NETWORK_REQUEST_METHOD,
274
+ module: 'network',
275
+ capability: NETWORK_REQUEST_METHOD,
276
+ requirement: { kind: 'all', permissions: ['network'] },
277
+ risk: 'high',
278
+ },
279
+ {
280
+ method: NETWORK_DOWNLOAD_METHOD,
281
+ module: 'network',
282
+ capability: NETWORK_DOWNLOAD_METHOD,
283
+ requirement: { kind: 'all', permissions: ['network', 'filesystem'] },
284
+ risk: 'high',
285
+ },
286
+ {
287
+ method: FILES_PICK_FILES_METHOD,
288
+ module: 'files',
289
+ capability: FILES_PICK_FILES_METHOD,
290
+ requirement: { kind: 'all', permissions: ['filesystem'] },
291
+ risk: 'high',
292
+ },
293
+ {
294
+ method: FILES_PICK_DIRECTORY_METHOD,
295
+ module: 'files',
296
+ capability: FILES_PICK_DIRECTORY_METHOD,
297
+ requirement: { kind: 'all', permissions: ['filesystem'] },
298
+ risk: 'high',
299
+ },
300
+ {
301
+ method: FILES_SAVE_FILE_METHOD,
302
+ module: 'files',
303
+ capability: FILES_SAVE_FILE_METHOD,
304
+ requirement: { kind: 'all', permissions: ['filesystem'] },
305
+ risk: 'high',
306
+ },
307
+ {
308
+ method: FILE_CREATE_METHOD,
309
+ module: 'file',
310
+ capability: FILE_CREATE_METHOD,
311
+ requirement: { kind: 'all', permissions: ['filesystem'] },
312
+ risk: 'high',
313
+ },
314
+ {
315
+ method: FILE_REMOVE_METHOD,
316
+ module: 'file',
317
+ capability: FILE_REMOVE_METHOD,
318
+ requirement: { kind: 'all', permissions: ['filesystem'] },
319
+ risk: 'high',
320
+ },
321
+ {
322
+ method: FILE_EXISTS_METHOD,
323
+ module: 'file',
324
+ capability: FILE_EXISTS_METHOD,
325
+ requirement: { kind: 'all', permissions: ['filesystem'] },
326
+ risk: 'high',
327
+ },
328
+ {
329
+ method: FILE_READ_TEXT_METHOD,
330
+ module: 'file',
331
+ capability: FILE_READ_TEXT_METHOD,
332
+ requirement: { kind: 'all', permissions: ['filesystem'] },
333
+ risk: 'high',
334
+ },
335
+ {
336
+ method: FILE_WRITE_TEXT_METHOD,
337
+ module: 'file',
338
+ capability: FILE_WRITE_TEXT_METHOD,
339
+ requirement: { kind: 'all', permissions: ['filesystem'] },
340
+ risk: 'high',
341
+ },
342
+ {
343
+ method: FILE_READ_BYTES_METHOD,
344
+ module: 'file',
345
+ capability: FILE_READ_BYTES_METHOD,
346
+ requirement: { kind: 'all', permissions: ['filesystem'] },
347
+ risk: 'high',
348
+ },
349
+ {
350
+ method: FILE_WRITE_BYTES_METHOD,
351
+ module: 'file',
352
+ capability: FILE_WRITE_BYTES_METHOD,
353
+ requirement: { kind: 'all', permissions: ['filesystem'] },
354
+ risk: 'high',
355
+ },
356
+ { method: FILE_STAT_METHOD, module: 'file', capability: FILE_STAT_METHOD, requirement: { kind: 'all', permissions: ['filesystem'] }, risk: 'high' },
357
+ {
358
+ method: DIRECTORY_CREATE_METHOD,
359
+ module: 'directory',
360
+ capability: DIRECTORY_CREATE_METHOD,
361
+ requirement: { kind: 'all', permissions: ['filesystem'] },
362
+ risk: 'high',
363
+ },
364
+ {
365
+ method: DIRECTORY_REMOVE_METHOD,
366
+ module: 'directory',
367
+ capability: DIRECTORY_REMOVE_METHOD,
368
+ requirement: { kind: 'all', permissions: ['filesystem'] },
369
+ risk: 'high',
370
+ },
371
+ {
372
+ method: DIRECTORY_EXISTS_METHOD,
373
+ module: 'directory',
374
+ capability: DIRECTORY_EXISTS_METHOD,
375
+ requirement: { kind: 'all', permissions: ['filesystem'] },
376
+ risk: 'high',
377
+ },
378
+ {
379
+ method: DIRECTORY_LIST_METHOD,
380
+ module: 'directory',
381
+ capability: DIRECTORY_LIST_METHOD,
382
+ requirement: { kind: 'all', permissions: ['filesystem'] },
383
+ risk: 'high',
384
+ },
385
+ { method: UI_SHOW_TOAST_METHOD, module: 'ui', capability: UI_SHOW_TOAST_METHOD, requirement: { kind: 'none' }, risk: 'low' },
386
+ { method: UI_SHOW_LOADING_METHOD, module: 'ui', capability: UI_SHOW_LOADING_METHOD, requirement: { kind: 'none' }, risk: 'low' },
387
+ { method: UI_HIDE_LOADING_METHOD, module: 'ui', capability: UI_HIDE_LOADING_METHOD, requirement: { kind: 'none' }, risk: 'low' },
388
+ { method: DEVICE_VIBRATE_METHOD, module: 'device', capability: DEVICE_VIBRATE_METHOD, requirement: { kind: 'none' }, risk: 'low' },
155
389
  {
156
390
  method: DEVICE_SET_CLIPBOARD_METHOD,
157
391
  module: 'device',
158
392
  capability: DEVICE_SET_CLIPBOARD_METHOD,
159
- permission: 'device.clipboard.write',
393
+ requirement: { kind: 'all', permissions: ['clipboard'] },
160
394
  risk: 'medium',
161
395
  },
162
- { method: NAVIGATION_CLOSE_METHOD, module: 'navigation', capability: NAVIGATION_CLOSE_METHOD, permission: 'navigation.close', risk: 'medium' },
163
- { method: NAVIGATION_RELOAD_METHOD, module: 'navigation', capability: NAVIGATION_RELOAD_METHOD, permission: 'navigation.reload', risk: 'medium' },
396
+ { method: NAVIGATION_CLOSE_METHOD, module: 'navigation', capability: NAVIGATION_CLOSE_METHOD, requirement: { kind: 'none' }, risk: 'medium' },
397
+ { method: NAVIGATION_RELOAD_METHOD, module: 'navigation', capability: NAVIGATION_RELOAD_METHOD, requirement: { kind: 'none' }, risk: 'medium' },
164
398
  {
165
399
  method: NAVIGATION_OPEN_APP_PAGE_METHOD,
166
400
  module: 'navigation',
167
401
  capability: NAVIGATION_OPEN_APP_PAGE_METHOD,
168
- permission: 'navigation.openAppPage',
402
+ requirement: { kind: 'none' },
169
403
  risk: 'medium',
170
404
  },
171
405
  {
172
406
  method: CLOUD_LEADERBOARD_SUBMIT_METHOD,
173
407
  module: 'cloud',
174
408
  capability: CLOUD_LEADERBOARD_SUBMIT_METHOD,
175
- permission: 'cloud.leaderboard.write',
409
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
176
410
  risk: 'medium',
177
411
  },
178
412
  {
179
413
  method: CLOUD_LEADERBOARD_GET_LIST_METHOD,
180
414
  module: 'cloud',
181
415
  capability: CLOUD_LEADERBOARD_GET_LIST_METHOD,
182
- permission: 'cloud.leaderboard.read',
416
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
183
417
  risk: 'low',
184
418
  },
185
419
  {
186
420
  method: CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD,
187
421
  module: 'cloud',
188
422
  capability: CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD,
189
- permission: 'cloud.leaderboard.currentUserEntry.read',
423
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
190
424
  risk: 'medium',
191
425
  },
192
426
  {
193
427
  method: CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD,
194
428
  module: 'cloud',
195
429
  capability: CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD,
196
- permission: 'cloud.leaderboard.currentUserEntry.delete',
430
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
197
431
  risk: 'medium',
198
432
  },
199
433
  {
200
434
  method: CLOUD_LEADERBOARD_GET_INFO_METHOD,
201
435
  module: 'cloud',
202
436
  capability: CLOUD_LEADERBOARD_GET_INFO_METHOD,
203
- permission: 'cloud.leaderboard.info.read',
437
+ requirement: { kind: 'all', permissions: ['leaderboard'] },
204
438
  risk: 'low',
205
439
  },
206
440
  ] as const satisfies readonly MiniProgramCapabilityDefinition[];
@@ -218,6 +452,22 @@ export interface MiniProgramCapabilityPayloadMap {
218
452
  [STORAGE_GET_STORAGE_METHOD]: GetStoragePayload;
219
453
  [STORAGE_SET_STORAGE_METHOD]: SetStoragePayload;
220
454
  [NETWORK_REQUEST_METHOD]: NetworkRequestPayload;
455
+ [NETWORK_DOWNLOAD_METHOD]: NetworkDownloadPayload;
456
+ [FILES_PICK_FILES_METHOD]: PickFilesPayload;
457
+ [FILES_PICK_DIRECTORY_METHOD]: PickDirectoryPayload;
458
+ [FILES_SAVE_FILE_METHOD]: SaveFilePayload;
459
+ [FILE_CREATE_METHOD]: FileCreatePayload;
460
+ [FILE_REMOVE_METHOD]: FileRemovePayload;
461
+ [FILE_EXISTS_METHOD]: FileExistsPayload;
462
+ [FILE_READ_TEXT_METHOD]: FileReadTextPayload;
463
+ [FILE_WRITE_TEXT_METHOD]: FileWriteTextPayload;
464
+ [FILE_READ_BYTES_METHOD]: FileReadBytesPayload;
465
+ [FILE_WRITE_BYTES_METHOD]: FileWriteBytesPayload;
466
+ [FILE_STAT_METHOD]: FileStatPayload;
467
+ [DIRECTORY_CREATE_METHOD]: DirectoryCreatePayload;
468
+ [DIRECTORY_REMOVE_METHOD]: DirectoryRemovePayload;
469
+ [DIRECTORY_EXISTS_METHOD]: DirectoryExistsPayload;
470
+ [DIRECTORY_LIST_METHOD]: DirectoryListPayload;
221
471
  [UI_SHOW_TOAST_METHOD]: ShowToastPayload;
222
472
  [UI_SHOW_LOADING_METHOD]: ShowLoadingPayload;
223
473
  [UI_HIDE_LOADING_METHOD]: HideLoadingPayload;
@@ -246,6 +496,22 @@ export interface MiniProgramCapabilityResultMap {
246
496
  [STORAGE_GET_STORAGE_METHOD]: GetStorageResult;
247
497
  [STORAGE_SET_STORAGE_METHOD]: void;
248
498
  [NETWORK_REQUEST_METHOD]: NetworkResponsePayload;
499
+ [NETWORK_DOWNLOAD_METHOD]: NetworkDownloadResult;
500
+ [FILES_PICK_FILES_METHOD]: PickFilesResult;
501
+ [FILES_PICK_DIRECTORY_METHOD]: PickDirectoryResult;
502
+ [FILES_SAVE_FILE_METHOD]: SaveFileResult;
503
+ [FILE_CREATE_METHOD]: FileCreateResult;
504
+ [FILE_REMOVE_METHOD]: FileRemoveResult;
505
+ [FILE_EXISTS_METHOD]: FileExistsResult;
506
+ [FILE_READ_TEXT_METHOD]: FileReadTextResult;
507
+ [FILE_WRITE_TEXT_METHOD]: FileWriteTextResult;
508
+ [FILE_READ_BYTES_METHOD]: FileReadBytesResult;
509
+ [FILE_WRITE_BYTES_METHOD]: FileWriteBytesResult;
510
+ [FILE_STAT_METHOD]: FileStatResult;
511
+ [DIRECTORY_CREATE_METHOD]: DirectoryCreateResult;
512
+ [DIRECTORY_REMOVE_METHOD]: DirectoryRemoveResult;
513
+ [DIRECTORY_EXISTS_METHOD]: DirectoryExistsResult;
514
+ [DIRECTORY_LIST_METHOD]: DirectoryListResult;
249
515
  [UI_SHOW_TOAST_METHOD]: ShowToastResult;
250
516
  [UI_SHOW_LOADING_METHOD]: ShowLoadingResult;
251
517
  [UI_HIDE_LOADING_METHOD]: HideLoadingResult;
package/src/constants.ts CHANGED
@@ -5,3 +5,4 @@ export const SDK_HANDSHAKE_METHOD = 'sdk.handshake' as const;
5
5
  export const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe' as const;
6
6
  export const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report' as const;
7
7
  export const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation' as const;
8
+ export const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress' as const;
package/src/guards.ts CHANGED
@@ -1,13 +1,167 @@
1
- import { MINI_PROGRAM_MESSAGE_NAMESPACE } from './constants';
1
+ import { MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_OPERATION_PROGRESS_METHOD, SDK_HANDSHAKE_METHOD } from './constants';
2
2
  import type { MiniProgramBridgeMessage } from './bridge';
3
+ import type {
4
+ DownloadProgressPayload,
5
+ MiniProgramDirectoryDescriptor,
6
+ MiniProgramDirectoryRef,
7
+ MiniProgramFileDescriptor,
8
+ MiniProgramFileRef,
9
+ MiniProgramFileStat,
10
+ MiniProgramFileSystemEntityDescriptor,
11
+ MiniProgramPathRootRef,
12
+ } from './payloads';
3
13
 
4
14
  export function isMiniProgramBridgeMessage(value: unknown): value is MiniProgramBridgeMessage {
5
- if (!value || typeof value !== 'object') return false;
6
- const message = value as Partial<MiniProgramBridgeMessage>;
15
+ if (!isRecord(value)) return false;
16
+ if (value.namespace !== MINI_PROGRAM_MESSAGE_NAMESPACE || (value.version !== 1 && value.version !== 2) || !isNonEmptyString(value.nonce)) {
17
+ return false;
18
+ }
19
+
20
+ if (value.type === 'handshake') {
21
+ return isNonEmptyString(value.id) && value.method === SDK_HANDSHAKE_METHOD && value.error === undefined && isSDKHandshakePayload(value.payload);
22
+ }
23
+ if (value.type === 'request') {
24
+ return isNonEmptyString(value.id) && isNonEmptyString(value.method) && value.error === undefined;
25
+ }
26
+ if (value.type === 'response') {
27
+ return (
28
+ isNonEmptyString(value.id) &&
29
+ (value.method === undefined || isNonEmptyString(value.method)) &&
30
+ (value.error === undefined || isBridgeError(value.error))
31
+ );
32
+ }
33
+ if (value.type === 'event') {
34
+ if (!isNonEmptyString(value.method) || value.error !== undefined) return false;
35
+ if (value.method === MINI_PROGRAM_OPERATION_PROGRESS_METHOD) {
36
+ return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramDownloadProgressPayload(value.payload);
37
+ }
38
+ return value.id === undefined || isNonEmptyString(value.id);
39
+ }
40
+ if (value.type === 'cancel') {
41
+ return (
42
+ value.version === 2 && isNonEmptyString(value.id) && value.method === undefined && value.payload === undefined && value.error === undefined
43
+ );
44
+ }
45
+ return false;
46
+ }
47
+
48
+ export function isMiniProgramRelativePath(value: unknown): value is string {
49
+ if (typeof value !== 'string' || !value || value.startsWith('/') || value.endsWith('/')) {
50
+ return false;
51
+ }
52
+ if (/[\\\u0000-\u001f\u007f]/.test(value)) return false;
53
+ return value.split('/').every((segment) => Boolean(segment) && segment !== '.' && segment !== '..');
54
+ }
55
+
56
+ export function isMiniProgramPathRootRef(value: unknown): value is MiniProgramPathRootRef {
57
+ if (!isRecord(value)) return false;
58
+ if (value.kind === 'sandbox') return hasOnlyKeys(value, ['kind']);
59
+ return value.kind === 'directory' && isNonEmptyString(value.handleId) && hasOnlyKeys(value, ['kind', 'handleId']);
60
+ }
61
+
62
+ export function isMiniProgramFileRef(value: unknown): value is MiniProgramFileRef {
63
+ if (!isRecord(value) || value.kind !== 'file') return false;
64
+ if (isNonEmptyString(value.handleId)) {
65
+ return hasOnlyKeys(value, ['kind', 'handleId']);
66
+ }
67
+ return (
68
+ isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath'])
69
+ );
70
+ }
71
+
72
+ export function isMiniProgramDirectoryRef(value: unknown): value is MiniProgramDirectoryRef {
73
+ if (!isRecord(value) || value.kind !== 'directory') return false;
74
+ if (isNonEmptyString(value.handleId)) {
75
+ return hasOnlyKeys(value, ['kind', 'handleId']);
76
+ }
7
77
  return (
8
- message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
9
- (message.version === 1 || message.version === 2) &&
10
- typeof message.nonce === 'string' &&
11
- typeof message.type === 'string'
78
+ isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath'])
12
79
  );
13
80
  }
81
+
82
+ export function isMiniProgramFileDescriptor(value: unknown): value is MiniProgramFileDescriptor {
83
+ return (
84
+ isRecord(value) &&
85
+ value.kind === 'file' &&
86
+ isNonEmptyString(value.name) &&
87
+ isFileMode(value.mode) &&
88
+ isMiniProgramFileRef(value.ref) &&
89
+ hasOnlyKeys(value, ['kind', 'name', 'mode', 'ref'])
90
+ );
91
+ }
92
+
93
+ export function isMiniProgramDirectoryDescriptor(value: unknown): value is MiniProgramDirectoryDescriptor {
94
+ return (
95
+ isRecord(value) &&
96
+ value.kind === 'directory' &&
97
+ isNonEmptyString(value.name) &&
98
+ isFileMode(value.mode) &&
99
+ isMiniProgramDirectoryRef(value.ref) &&
100
+ hasOnlyKeys(value, ['kind', 'name', 'mode', 'ref'])
101
+ );
102
+ }
103
+
104
+ export function isMiniProgramFileSystemEntityDescriptor(value: unknown): value is MiniProgramFileSystemEntityDescriptor {
105
+ return isMiniProgramFileDescriptor(value) || isMiniProgramDirectoryDescriptor(value);
106
+ }
107
+
108
+ export function isMiniProgramByteArray(value: unknown): value is Uint8Array {
109
+ return value instanceof Uint8Array && value.buffer instanceof ArrayBuffer;
110
+ }
111
+
112
+ export function isMiniProgramFileStat(value: unknown): value is MiniProgramFileStat {
113
+ return (
114
+ isRecord(value) &&
115
+ value.kind === 'file' &&
116
+ isNonNegativeSafeInteger(value.size) &&
117
+ (value.modifiedAt === undefined || isNonNegativeFiniteNumber(value.modifiedAt)) &&
118
+ (value.createdAt === undefined || isNonNegativeFiniteNumber(value.createdAt)) &&
119
+ hasOnlyKeys(value, ['kind', 'size', 'modifiedAt', 'createdAt'])
120
+ );
121
+ }
122
+
123
+ export function isMiniProgramDownloadProgressPayload(value: unknown): value is DownloadProgressPayload {
124
+ if (
125
+ !isRecord(value) ||
126
+ !isNonNegativeSafeInteger(value.loaded) ||
127
+ typeof value.lengthComputable !== 'boolean' ||
128
+ !hasOnlyKeys(value, ['loaded', 'total', 'lengthComputable'])
129
+ ) {
130
+ return false;
131
+ }
132
+ if (!value.lengthComputable) return value.total === undefined;
133
+ return isNonNegativeSafeInteger(value.total) && value.loaded <= value.total;
134
+ }
135
+
136
+ function isSDKHandshakePayload(value: unknown) {
137
+ return isRecord(value) && isNonEmptyString(value.href) && typeof value.userAgent === 'string' && isNonEmptyString(value.sdkVersion);
138
+ }
139
+
140
+ function isBridgeError(value: unknown) {
141
+ return isRecord(value) && isNonEmptyString(value.code) && typeof value.message === 'string';
142
+ }
143
+
144
+ function isFileMode(value: unknown) {
145
+ return value === 'read' || value === 'readwrite';
146
+ }
147
+
148
+ function isNonNegativeSafeInteger(value: unknown): value is number {
149
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
150
+ }
151
+
152
+ function isNonNegativeFiniteNumber(value: unknown): value is number {
153
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0;
154
+ }
155
+
156
+ function isNonEmptyString(value: unknown): value is string {
157
+ return typeof value === 'string' && value.length > 0;
158
+ }
159
+
160
+ function hasOnlyKeys(value: Record<string, unknown>, allowedKeys: readonly string[]) {
161
+ const allowed = new Set(allowedKeys);
162
+ return Object.keys(value).every((key) => allowed.has(key));
163
+ }
164
+
165
+ function isRecord(value: unknown): value is Record<string, unknown> {
166
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
167
+ }