@heybox/hb-sdk 0.6.6 → 0.6.7-alpha.1

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/README.md CHANGED
@@ -158,7 +158,7 @@ await share.screenshot({
158
158
  });
159
159
  ```
160
160
 
161
- 截图分享支持多个预置分区;分区与话题仍由用户在客户端发帖页中确认和修改,SDK 不会直接发布内容。
161
+ 截图分享支持多个预置分区;分区与话题仍由用户在客户端发帖页中确认和修改,SDK 不会直接发布内容。通过截图分享进入社区发帖流程时,客户端会自动把帖子关联到当前小程序,开发者无需配置额外来源字段。
162
162
 
163
163
  ### 基础 UI
164
164
 
@@ -5,8 +5,8 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
7
7
  var runtimeGate = require('./runtime-gate--rPXjiG6.cjs');
8
- var index = require('./index-DAJGwzpN.cjs');
9
- var projectVite = require('./project-vite-RXpbNaQD.cjs');
8
+ var index = require('./index-CZ1l6xci.cjs');
9
+ var projectVite = require('./project-vite-BGAleOVW.cjs');
10
10
  require('node:async_hooks');
11
11
  require('node:module');
12
12
  require('path');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var session = require('./session-4SxzY4w1.cjs');
3
+ var session = require('./session-BbDd1r6M.cjs');
4
4
  var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
5
5
  var fs$1 = require('node:fs');
6
6
  var fs = require('node:fs/promises');
@@ -5,7 +5,7 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var require$$0 = require('fs');
7
7
  var require$$1 = require('path');
8
- var index = require('./index-DAJGwzpN.cjs');
8
+ var index = require('./index-CZ1l6xci.cjs');
9
9
  require('node:module');
10
10
  require('os');
11
11
  require('readline');
@@ -6,15 +6,15 @@ var path = require('node:path');
6
6
  var net = require('node:net');
7
7
  var promises = require('node:dns/promises');
8
8
  var node_http = require('node:http');
9
- var context = require('./context-B2Y0Du9z.cjs');
9
+ var context = require('./context-CfrdSQSg.cjs');
10
10
  var node_crypto = require('node:crypto');
11
11
  var undici = require('undici');
12
12
  var browser = require('./browser-RAy8e8cV.cjs');
13
- var index = require('./index-DAJGwzpN.cjs');
14
- var projectVite = require('./project-vite-RXpbNaQD.cjs');
13
+ var index = require('./index-CZ1l6xci.cjs');
14
+ var projectVite = require('./project-vite-BGAleOVW.cjs');
15
15
  var fs$1 = require('node:fs/promises');
16
16
  var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
17
- require('./session-4SxzY4w1.cjs');
17
+ require('./session-BbDd1r6M.cjs');
18
18
  require('fs');
19
19
  require('constants');
20
20
  require('stream');
@@ -1170,7 +1170,7 @@ function createHeyboxProtocol(payload) {
1170
1170
  /** 构建时替换为当前发布包的实际版本。 */
1171
1171
  const HB_SDK_VERSION = typeof undefined === 'string'
1172
1172
  ? undefined
1173
- : '0.6.6';
1173
+ : '0.6.7-alpha.1';
1174
1174
 
1175
1175
  class DevPermissionOverrideStoreError extends Error {
1176
1176
  code;
@@ -4,7 +4,7 @@ var fs$1 = require('node:fs');
4
4
  var fs = require('node:fs/promises');
5
5
  var os = require('node:os');
6
6
  var path = require('node:path');
7
- var index = require('./index-DAJGwzpN.cjs');
7
+ var index = require('./index-CZ1l6xci.cjs');
8
8
  require('node:module');
9
9
  require('path');
10
10
  require('os');
@@ -234,19 +234,19 @@ function requireArgument () {
234
234
 
235
235
  var command = {};
236
236
 
237
- const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DAJGwzpN.cjs', document.baseURI).href)));
237
+ const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CZ1l6xci.cjs', document.baseURI).href)));
238
238
  function __require$4() { return require$5("node:events"); }
239
239
 
240
- const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DAJGwzpN.cjs', document.baseURI).href)));
240
+ const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CZ1l6xci.cjs', document.baseURI).href)));
241
241
  function __require$3() { return require$4("node:child_process"); }
242
242
 
243
- const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DAJGwzpN.cjs', document.baseURI).href)));
243
+ const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CZ1l6xci.cjs', document.baseURI).href)));
244
244
  function __require$2() { return require$3("node:path"); }
245
245
 
246
- const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DAJGwzpN.cjs', document.baseURI).href)));
246
+ const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CZ1l6xci.cjs', document.baseURI).href)));
247
247
  function __require$1() { return require$2("node:fs"); }
248
248
 
249
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DAJGwzpN.cjs', document.baseURI).href)));
249
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CZ1l6xci.cjs', document.baseURI).href)));
250
250
  function __require() { return require$1("node:process"); }
251
251
 
252
252
  var help = {};
@@ -13347,7 +13347,7 @@ function getPathname(pathWithQuery) {
13347
13347
  }
13348
13348
 
13349
13349
  const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
13350
- const BUILT_CLI_VERSION = '0.6.6';
13350
+ const BUILT_CLI_VERSION = '0.6.7-alpha.1';
13351
13351
  const PACKAGE_JSON_CANDIDATES = [
13352
13352
  path.resolve(__dirname, '..', '..', 'package.json'),
13353
13353
  path.resolve(__dirname, '..', 'package.json'),
@@ -13680,35 +13680,35 @@ function createCommandLoggerResolver(options) {
13680
13680
  };
13681
13681
  }
13682
13682
  const defaultClearLoginStatus = async (...args) => {
13683
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-DseHvHCN.cjs'); });
13683
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-B2kXjmcM.cjs'); });
13684
13684
  return clearLoginStatus(...args);
13685
13685
  };
13686
13686
  const defaultLoginToHeybox = async (...args) => {
13687
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-DseHvHCN.cjs'); });
13687
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-B2kXjmcM.cjs'); });
13688
13688
  return loginToHeybox(...args);
13689
13689
  };
13690
13690
  const defaultPrintLoginStatus = async (...args) => {
13691
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-DseHvHCN.cjs'); });
13691
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-B2kXjmcM.cjs'); });
13692
13692
  return printLoginStatus(...args);
13693
13693
  };
13694
13694
  const defaultRunBuildCommand = async (...args) => {
13695
- const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-egxk9rgs.cjs'); });
13695
+ const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-cBQK_qq-.cjs'); });
13696
13696
  return runBuildCommand(...args);
13697
13697
  };
13698
13698
  const defaultRunCreateCommand = async (...args) => {
13699
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-DPm5Sp-d.cjs'); });
13699
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-mp5nBLFJ.cjs'); });
13700
13700
  return runCreateCommand(...args);
13701
13701
  };
13702
13702
  const defaultRunDevCommand = async (...args) => {
13703
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-CEqWxCnf.cjs'); });
13703
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-CSuSpwJC.cjs'); });
13704
13704
  return runDevCommand(...args);
13705
13705
  };
13706
13706
  const defaultRunDoctorCommand = async (...args) => {
13707
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DqNzGi3s.cjs'); });
13707
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-nEv6ikeF.cjs'); });
13708
13708
  return runDoctorCommand(...args);
13709
13709
  };
13710
13710
  const defaultRunRemoteCommand = async (...args) => {
13711
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-Cko4-pSc.cjs'); });
13711
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-B5byhdC7.cjs'); });
13712
13712
  return runRemoteCommand(...args);
13713
13713
  };
13714
13714
  function resolveStandaloneLogger(options, verbose) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index$2 = require('./index-DAJGwzpN.cjs');
3
+ var index$2 = require('./index-CZ1l6xci.cjs');
4
4
  var require$$0$2 = require('fs');
5
5
  var require$$2$1 = require('crypto');
6
6
  var require$$1$2 = require('path');
@@ -3,9 +3,9 @@
3
3
  var promises = require('node:readline/promises');
4
4
  var node_crypto = require('node:crypto');
5
5
  var node_http = require('node:http');
6
- var session = require('./session-4SxzY4w1.cjs');
6
+ var session = require('./session-BbDd1r6M.cjs');
7
7
  var browser = require('./browser-RAy8e8cV.cjs');
8
- var index = require('./index-DAJGwzpN.cjs');
8
+ var index = require('./index-CZ1l6xci.cjs');
9
9
  require('node:path');
10
10
  require('fs');
11
11
  require('constants');
@@ -5,7 +5,7 @@ var fs$1 = require('node:fs/promises');
5
5
  var node_module = require('node:module');
6
6
  var path = require('node:path');
7
7
  var node_url = require('node:url');
8
- var index = require('./index-DAJGwzpN.cjs');
8
+ var index = require('./index-CZ1l6xci.cjs');
9
9
 
10
10
  function findProjectRoot(startDir) {
11
11
  let current = path.resolve(startDir);
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  var promises = require('node:readline/promises');
4
- var index = require('./index-DAJGwzpN.cjs');
5
- var session = require('./session-4SxzY4w1.cjs');
4
+ var index = require('./index-CZ1l6xci.cjs');
5
+ var session = require('./session-BbDd1r6M.cjs');
6
6
  var childProcess = require('node:child_process');
7
7
  var fs = require('node:fs');
8
8
  var fs$1 = require('node:fs/promises');
9
9
  var path = require('node:path');
10
10
  var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
11
11
  var runtimeGate = require('./runtime-gate--rPXjiG6.cjs');
12
- var context = require('./context-B2Y0Du9z.cjs');
12
+ var context = require('./context-CfrdSQSg.cjs');
13
13
  require('node:module');
14
14
  require('path');
15
15
  require('os');
@@ -192,7 +192,7 @@ async function createDefaultCosClient(uploadToken) {
192
192
  };
193
193
  }
194
194
  async function loadCosConstructor() {
195
- const cosModule = await Promise.resolve().then(function () { return require('./index-CSc_4vi-.cjs'); }).then(function (n) { return n.index; });
195
+ const cosModule = await Promise.resolve().then(function () { return require('./index-CgUdrl3g.cjs'); }).then(function (n) { return n.index; });
196
196
  return cosModule.default;
197
197
  }
198
198
  function formatSize(bytes) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DAJGwzpN.cjs');
3
+ var index = require('./index-CZ1l6xci.cjs');
4
4
  var node_crypto = require('node:crypto');
5
5
  var path = require('node:path');
6
6
  var require$$0$2 = require('fs');
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./cli-chunks/index-DAJGwzpN.cjs');
3
+ var index = require('./cli-chunks/index-CZ1l6xci.cjs');
4
4
  require('node:module');
5
5
  require('node:fs');
6
6
  require('node:fs/promises');
@@ -3707,25 +3707,61 @@ function stringifyMiniProgramRuntimeJsonData(data, options) {
3707
3707
  }
3708
3708
 
3709
3709
  const LEADERBOARD_KEY_RE = /^[A-Za-z0-9_-]{1,64}$/;
3710
+ const DEFAULT_LEADERBOARD_KEY = 'default';
3710
3711
  const DEFAULT_LEADERBOARD_LIST_LIMIT = 20;
3711
3712
  const MAX_LEADERBOARD_LIST_LIMIT = 100;
3712
3713
  const MAX_LEADERBOARD_EXTRA_BYTES = 2048;
3713
3714
  const MAX_LEADERBOARD_SAFE_SCORE = Number.MAX_SAFE_INTEGER;
3714
- /** 提交当前用户排行榜分数。 */
3715
- async function submitMiniProgramRuntimeLeaderboardEntry(payload, options) {
3716
- const request = readLeaderboardPayload(payload, 'cloud.leaderboard.submit', 'submit');
3715
+ const LEADERBOARD_READ_CACHE_TTL_MS = 5 * 60 * 1000;
3716
+ const MAX_LEADERBOARD_LIST_CACHE_ENTRIES = 250;
3717
+ const MAX_LEADERBOARD_CACHE_BUCKETS = 3;
3718
+ /** 创建一组共享读缓存的排行榜 handler。 */
3719
+ function createMiniProgramRuntimeLeaderboardHandlers(options) {
3720
+ const store = createLeaderboardReadStore();
3721
+ return {
3722
+ async submit(payload) {
3723
+ const request = readLeaderboardPayload(payload, 'cloud.leaderboard.submit', 'submit');
3724
+ const bucketKey = createLeaderboardBucketKey(options, request.key);
3725
+ return submitLeaderboardEntry(request, options, () => store.invalidateMutableReads(bucketKey));
3726
+ },
3727
+ async getList(payload) {
3728
+ const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getList', 'list');
3729
+ const bucketKey = createLeaderboardBucketKey(options, request.key);
3730
+ const cacheKey = createLeaderboardCacheKey('list', request.limit, request.cursor ?? null);
3731
+ return store.read(bucketKey, 'list', cacheKey, () => requestLeaderboardList(request, options));
3732
+ },
3733
+ async getCurrentUserEntry(payload) {
3734
+ const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getCurrentUserEntry', 'keyOnly');
3735
+ const userId = await readCurrentUserId(options.platformAdapter);
3736
+ const bucketKey = createLeaderboardBucketKey(options, request.key);
3737
+ const cacheKey = createLeaderboardCacheKey('current', userId);
3738
+ return store.read(bucketKey, 'current', cacheKey, () => requestCurrentUserLeaderboardEntry(request, userId, options));
3739
+ },
3740
+ async deleteCurrentUserEntry(payload) {
3741
+ const request = readLeaderboardPayload(payload, 'cloud.leaderboard.deleteCurrentUserEntry', 'keyOnly');
3742
+ const bucketKey = createLeaderboardBucketKey(options, request.key);
3743
+ return deleteCurrentUserLeaderboardEntry(request, options, () => store.invalidateMutableReads(bucketKey));
3744
+ },
3745
+ async getInfo(payload) {
3746
+ const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getInfo', 'keyOnly');
3747
+ const bucketKey = createLeaderboardBucketKey(options, request.key);
3748
+ const cacheKey = createLeaderboardCacheKey('info');
3749
+ return store.read(bucketKey, 'info', cacheKey, () => requestLeaderboardInfo(request, options));
3750
+ },
3751
+ };
3752
+ }
3753
+ async function submitLeaderboardEntry(request, options, onAdapterSuccess) {
3717
3754
  const userId = await readCurrentUserId(options.platformAdapter);
3718
3755
  const entry = await options.platformAdapter.cloud.leaderboard.submit({
3719
3756
  ...request,
3720
3757
  miniProgramId: options.identity?.miniProgramId,
3721
3758
  userId,
3722
3759
  });
3760
+ onAdapterSuccess?.();
3723
3761
  assertLeaderboardEntry(entry, 'cloud.leaderboard.submit');
3724
3762
  return entry;
3725
3763
  }
3726
- /** 读取排行榜列表。 */
3727
- async function getMiniProgramRuntimeLeaderboardList(payload, options) {
3728
- const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getList', 'list');
3764
+ async function requestLeaderboardList(request, options) {
3729
3765
  const result = await options.platformAdapter.cloud.leaderboard.getList({
3730
3766
  ...request,
3731
3767
  miniProgramId: options.identity?.miniProgramId,
@@ -3743,10 +3779,7 @@ async function getMiniProgramRuntimeLeaderboardList(payload, options) {
3743
3779
  }
3744
3780
  return result;
3745
3781
  }
3746
- /** 读取当前用户在排行榜中的记录。 */
3747
- async function getMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options) {
3748
- const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getCurrentUserEntry', 'keyOnly');
3749
- const userId = await readCurrentUserId(options.platformAdapter);
3782
+ async function requestCurrentUserLeaderboardEntry(request, userId, options) {
3750
3783
  const entry = await options.platformAdapter.cloud.leaderboard.getCurrentUserEntry({
3751
3784
  ...request,
3752
3785
  miniProgramId: options.identity?.miniProgramId,
@@ -3757,24 +3790,21 @@ async function getMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options
3757
3790
  }
3758
3791
  return entry;
3759
3792
  }
3760
- /** 删除当前用户在排行榜中的记录。 */
3761
- async function deleteMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, options) {
3762
- const request = readLeaderboardPayload(payload, 'cloud.leaderboard.deleteCurrentUserEntry', 'keyOnly');
3793
+ async function deleteCurrentUserLeaderboardEntry(request, options, onAdapterSuccess) {
3763
3794
  const userId = await readCurrentUserId(options.platformAdapter);
3764
3795
  const result = await options.platformAdapter.cloud.leaderboard.deleteCurrentUserEntry({
3765
3796
  ...request,
3766
3797
  miniProgramId: options.identity?.miniProgramId,
3767
3798
  userId,
3768
3799
  });
3800
+ onAdapterSuccess?.();
3769
3801
  assertMiniProgramRuntimeRecord(result, 'cloud.leaderboard.deleteCurrentUserEntry 返回值必须是对象');
3770
3802
  if (typeof result.deleted !== 'boolean') {
3771
3803
  throw createMiniProgramRuntimeBridgeError('INVALID_RESPONSE', 'cloud.leaderboard.deleteCurrentUserEntry 返回的 deleted 必须是布尔值');
3772
3804
  }
3773
3805
  return result;
3774
3806
  }
3775
- /** 读取排行榜基础信息。 */
3776
- async function getMiniProgramRuntimeLeaderboardInfo(payload, options) {
3777
- const request = readLeaderboardPayload(payload, 'cloud.leaderboard.getInfo', 'keyOnly');
3807
+ async function requestLeaderboardInfo(request, options) {
3778
3808
  const info = await options.platformAdapter.cloud.leaderboard.getInfo({
3779
3809
  ...request,
3780
3810
  miniProgramId: options.identity?.miniProgramId,
@@ -3791,6 +3821,138 @@ async function getMiniProgramRuntimeLeaderboardInfo(payload, options) {
3791
3821
  }
3792
3822
  return info;
3793
3823
  }
3824
+ function createLeaderboardReadStore() {
3825
+ const buckets = new Map();
3826
+ const inflight = new Map();
3827
+ function getOrCreateBucket(bucketKey) {
3828
+ const bucket = buckets.get(bucketKey);
3829
+ if (bucket) {
3830
+ return bucket;
3831
+ }
3832
+ pruneExpiredBuckets();
3833
+ if (buckets.size >= MAX_LEADERBOARD_CACHE_BUCKETS) {
3834
+ return undefined;
3835
+ }
3836
+ const nextBucket = {
3837
+ generation: 0,
3838
+ caches: {
3839
+ list: new Map(),
3840
+ current: new Map(),
3841
+ info: new Map(),
3842
+ },
3843
+ };
3844
+ buckets.set(bucketKey, nextBucket);
3845
+ return nextBucket;
3846
+ }
3847
+ function read(bucketKey, kind, cacheKey, request) {
3848
+ const bucket = getOrCreateBucket(bucketKey);
3849
+ const cache = bucket?.caches[kind];
3850
+ const cached = cache?.get(cacheKey);
3851
+ if (cached && cached.expiresAt > Date.now()) {
3852
+ return Promise.resolve(cached.value);
3853
+ }
3854
+ cache?.delete(cacheKey);
3855
+ const inflightKey = createLeaderboardInflightKey(bucketKey, cacheKey);
3856
+ const existingInflight = inflight.get(inflightKey);
3857
+ if (existingInflight) {
3858
+ return existingInflight.promise;
3859
+ }
3860
+ const requestGeneration = bucket?.generation;
3861
+ const promise = request()
3862
+ .then((result) => {
3863
+ if (bucket && cache && bucket.generation === requestGeneration) {
3864
+ if (kind === 'list') {
3865
+ if (cache.size >= MAX_LEADERBOARD_LIST_CACHE_ENTRIES) {
3866
+ cache.delete(cache.keys().next().value);
3867
+ }
3868
+ }
3869
+ else {
3870
+ cache.clear();
3871
+ }
3872
+ cache.set(cacheKey, {
3873
+ expiresAt: Date.now() + LEADERBOARD_READ_CACHE_TTL_MS,
3874
+ value: result,
3875
+ });
3876
+ }
3877
+ return result;
3878
+ })
3879
+ .finally(() => {
3880
+ if (inflight.get(inflightKey)?.promise === promise) {
3881
+ inflight.delete(inflightKey);
3882
+ }
3883
+ if (bucket) {
3884
+ removeEmptyBucket(bucketKey, bucket);
3885
+ }
3886
+ });
3887
+ inflight.set(inflightKey, { bucketKey, promise });
3888
+ return promise;
3889
+ }
3890
+ function invalidateMutableReads(bucketKey) {
3891
+ invalidateInflight(bucketKey);
3892
+ const bucket = buckets.get(bucketKey);
3893
+ if (!bucket) {
3894
+ return;
3895
+ }
3896
+ bucket.generation += 1;
3897
+ bucket.caches.list.clear();
3898
+ bucket.caches.current.clear();
3899
+ }
3900
+ function invalidateInflight(bucketKey) {
3901
+ inflight.forEach((entry, inflightKey) => {
3902
+ if (entry.bucketKey === bucketKey) {
3903
+ inflight.delete(inflightKey);
3904
+ }
3905
+ });
3906
+ }
3907
+ function pruneExpiredBuckets() {
3908
+ const now = Date.now();
3909
+ for (const [bucketKey, bucket] of buckets) {
3910
+ removeExpiredCacheEntries(bucket, now);
3911
+ if (isBucketEmpty(bucketKey, bucket)) {
3912
+ buckets.delete(bucketKey);
3913
+ }
3914
+ }
3915
+ }
3916
+ function removeEmptyBucket(bucketKey, bucket) {
3917
+ removeExpiredCacheEntries(bucket, Date.now());
3918
+ if (buckets.get(bucketKey) === bucket && isBucketEmpty(bucketKey, bucket)) {
3919
+ buckets.delete(bucketKey);
3920
+ }
3921
+ }
3922
+ function removeExpiredCacheEntries(bucket, now) {
3923
+ Object.values(bucket.caches).forEach((cache) => {
3924
+ cache.forEach((entry, cacheKey) => {
3925
+ if (entry.expiresAt <= now) {
3926
+ cache.delete(cacheKey);
3927
+ }
3928
+ });
3929
+ });
3930
+ }
3931
+ function isBucketEmpty(bucketKey, bucket) {
3932
+ return !hasInflight(bucketKey) && Object.values(bucket.caches).every(cache => cache.size === 0);
3933
+ }
3934
+ function hasInflight(bucketKey) {
3935
+ for (const entry of inflight.values()) {
3936
+ if (entry.bucketKey === bucketKey) {
3937
+ return true;
3938
+ }
3939
+ }
3940
+ return false;
3941
+ }
3942
+ return {
3943
+ read,
3944
+ invalidateMutableReads,
3945
+ };
3946
+ }
3947
+ function createLeaderboardBucketKey(options, key) {
3948
+ return JSON.stringify([options.identity?.miniProgramId ?? null, key ?? DEFAULT_LEADERBOARD_KEY]);
3949
+ }
3950
+ function createLeaderboardCacheKey(kind, ...parts) {
3951
+ return JSON.stringify([kind, ...parts]);
3952
+ }
3953
+ function createLeaderboardInflightKey(bucketKey, cacheKey) {
3954
+ return JSON.stringify([bucketKey, cacheKey]);
3955
+ }
3794
3956
  function readLeaderboardPayload(payload, methodName, shape) {
3795
3957
  if (payload === undefined && shape !== 'submit') {
3796
3958
  return shape === 'list' ? { limit: DEFAULT_LEADERBOARD_LIST_LIMIT } : {};
@@ -4379,15 +4541,17 @@ async function isMiniProgramShareDevelopmentRuntime(platformAdapter) {
4379
4541
  }
4380
4542
 
4381
4543
  /** 截图并唤起分享。 */
4382
- function shareMiniProgramRuntimeScreenshot(payload, platformAdapter) {
4544
+ function shareMiniProgramRuntimeScreenshot(payload, platformAdapter, context = {}) {
4383
4545
  const options = readMiniProgramScreenshotOptions(payload);
4384
4546
  const rect = options.rect || getMiniProgramRuntimeViewportRect(platformAdapter);
4385
4547
  const postResult = readMiniProgramRuntimeSharePostOptions(payload && typeof payload === 'object' ? payload.post : undefined, { method: 'share.screenshot' });
4548
+ const sourceMiniProgramId = context.miniProgramId?.trim() || undefined;
4386
4549
  return handleMiniProgramRuntimeSharePostValidation(postResult, platformAdapter, (post) => platformAdapter.share.shareScreenshot({
4387
4550
  rect,
4388
4551
  delay: options.delay,
4389
4552
  saveToAlbum: options.saveToAlbum,
4390
4553
  post,
4554
+ ...(sourceMiniProgramId ? { sourceMiniProgramId } : {}),
4391
4555
  }));
4392
4556
  }
4393
4557
  function readMiniProgramScreenshotOptions(payload) {
@@ -5349,8 +5513,10 @@ function createBrowserMockRuntimePlatformAdapter(options) {
5349
5513
  isDevRuntime: () => true,
5350
5514
  },
5351
5515
  launch: {
5352
- async getMiniProgramInfo() {
5516
+ async getMiniProgramInfo(miniProgramId) {
5517
+ // 与生产一致:启动详情返回的 canonical ID 作为可信身份,而非直接信任宿主 URL。
5353
5518
  return {
5519
+ miniProgramId,
5354
5520
  pageUrl: options.getMiniProgramPageUrl(),
5355
5521
  };
5356
5522
  },
@@ -5501,6 +5667,10 @@ class MiniProgramMockRuntime {
5501
5667
  this.vibrates = [];
5502
5668
  this.openAppPages = [];
5503
5669
  this.evaluateRuntimePermission = createMiniProgramRuntimePermissionEvaluator(options.runtimePermissions);
5670
+ this.leaderboardHandlers = createMiniProgramRuntimeLeaderboardHandlers({
5671
+ identity: options.identity,
5672
+ platformAdapter: adapter,
5673
+ });
5504
5674
  }
5505
5675
  async runMethod(method, payload) {
5506
5676
  if (!isMiniProgramMockRuntimeMethod(method)) {
@@ -5598,10 +5768,21 @@ class MiniProgramMockRuntime {
5598
5768
  : undefined;
5599
5769
  }
5600
5770
  showShareMenu(payload) {
5601
- return showMiniProgramRuntimeShareMenu(payload, this.adapter, readMockRuntimeShareContext(this.adapter.app.getCurrentHref()));
5771
+ return showMiniProgramRuntimeShareMenu(payload, this.adapter, this.getShareContext());
5602
5772
  }
5603
5773
  shareScreenshot(payload) {
5604
- return shareMiniProgramRuntimeScreenshot(payload, this.adapter);
5774
+ return shareMiniProgramRuntimeScreenshot(payload, this.adapter, this.getShareContext());
5775
+ }
5776
+ getShareContext() {
5777
+ if (this.options.identity) {
5778
+ return {
5779
+ miniProgramId: this.options.identity.miniProgramId?.trim() || undefined,
5780
+ miniProgramVersion: this.options.identity.miniProgramVersion?.trim() || undefined,
5781
+ };
5782
+ }
5783
+ // Mock host 由开发者控制:其 URL 启动参数等价于生产中的启动详情绑定,
5784
+ // 不是 iframe payload。生产 runtime 路径不会信任未绑定的宿主 URL 参数。
5785
+ return readMockHostShareContext(this.adapter.app.getCurrentHref());
5605
5786
  }
5606
5787
  getWindowInfo() {
5607
5788
  return getMiniProgramRuntimeWindowInfo(this.adapter);
@@ -5619,19 +5800,19 @@ class MiniProgramMockRuntime {
5619
5800
  return requestMiniProgramRuntimeNetwork(payload, this.adapter);
5620
5801
  }
5621
5802
  submitLeaderboardEntry(payload) {
5622
- return submitMiniProgramRuntimeLeaderboardEntry(payload, { platformAdapter: this.adapter });
5803
+ return this.leaderboardHandlers.submit(payload);
5623
5804
  }
5624
5805
  getLeaderboardList(payload) {
5625
- return getMiniProgramRuntimeLeaderboardList(payload, { platformAdapter: this.adapter });
5806
+ return this.leaderboardHandlers.getList(payload);
5626
5807
  }
5627
5808
  getCurrentUserLeaderboardEntry(payload) {
5628
- return getMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, { platformAdapter: this.adapter });
5809
+ return this.leaderboardHandlers.getCurrentUserEntry(payload);
5629
5810
  }
5630
5811
  deleteCurrentUserLeaderboardEntry(payload) {
5631
- return deleteMiniProgramRuntimeCurrentUserLeaderboardEntry(payload, { platformAdapter: this.adapter });
5812
+ return this.leaderboardHandlers.deleteCurrentUserEntry(payload);
5632
5813
  }
5633
5814
  getLeaderboardInfo(payload) {
5634
- return getMiniProgramRuntimeLeaderboardInfo(payload, { platformAdapter: this.adapter });
5815
+ return this.leaderboardHandlers.getInfo(payload);
5635
5816
  }
5636
5817
  async showToast(payload) {
5637
5818
  const toast = readShowToastPayload(payload);
@@ -5724,12 +5905,18 @@ class MiniProgramMockRuntime {
5724
5905
  this.records.splice(30);
5725
5906
  }
5726
5907
  }
5727
- function readMockRuntimeShareContext(href) {
5908
+ /**
5909
+ * 读取 mock host 自身 URL 上的启动参数作为可信分享上下文。
5910
+ * 与生产 runtime 不同:生产只信任启动详情回填的 canonical ID;
5911
+ * mock host 页面本身由开发者控制,因此允许从 host URL 读取,
5912
+ * 用于本地联调,且始终忽略 iframe 业务 payload 中的伪造字段。
5913
+ */
5914
+ function readMockHostShareContext(href) {
5728
5915
  try {
5729
5916
  const currentUrl = new URL(href);
5730
5917
  return {
5731
- miniProgramId: currentUrl.searchParams.get('mini_program_id') || undefined,
5732
- miniProgramVersion: currentUrl.searchParams.get('miniprogram_version') || undefined,
5918
+ miniProgramId: currentUrl.searchParams.get('mini_program_id')?.trim() || undefined,
5919
+ miniProgramVersion: currentUrl.searchParams.get('miniprogram_version')?.trim() || undefined,
5733
5920
  };
5734
5921
  }
5735
5922
  catch {
package/dist/index.cjs.js CHANGED
@@ -325,7 +325,7 @@ function createMessageId() {
325
325
  /** 构建时替换为当前发布包的实际版本。 */
326
326
  const HB_SDK_VERSION = typeof undefined === 'string'
327
327
  ? undefined
328
- : '0.6.6';
328
+ : '0.6.7-alpha.1';
329
329
 
330
330
  /**
331
331
  * 判断未知数据是否符合小程序 bridge 消息信封。
package/dist/index.esm.js CHANGED
@@ -321,7 +321,7 @@ function createMessageId() {
321
321
  /** 构建时替换为当前发布包的实际版本。 */
322
322
  const HB_SDK_VERSION = typeof undefined === 'string'
323
323
  ? undefined
324
- : '0.6.6';
324
+ : '0.6.7-alpha.1';
325
325
 
326
326
  /**
327
327
  * 判断未知数据是否符合小程序 bridge 消息信封。
package/dist/vite.cjs.js CHANGED
@@ -8,7 +8,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
8
8
  /** 构建时替换为当前发布包的实际版本。 */
9
9
  const HB_SDK_VERSION = typeof undefined === 'string'
10
10
  ? undefined
11
- : '0.6.6';
11
+ : '0.6.7-alpha.1';
12
12
 
13
13
  var re = {exports: {}};
14
14
 
package/dist/vite.esm.js CHANGED
@@ -5,7 +5,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
5
5
  /** 构建时替换为当前发布包的实际版本。 */
6
6
  const HB_SDK_VERSION = typeof undefined === 'string'
7
7
  ? undefined
8
- : '0.6.6';
8
+ : '0.6.7-alpha.1';
9
9
 
10
10
  var re = {exports: {}};
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk",
3
- "version": "0.6.6",
3
+ "version": "0.6.7-alpha.1",
4
4
  "sideEffects": [
5
5
  "./src/index.ts",
6
6
  "./src/core/singleton.ts",
@@ -19,7 +19,7 @@
19
19
  ## Package metadata
20
20
 
21
21
  - Package: `@heybox/hb-sdk`
22
- - Version at generation time: `0.6.6`
22
+ - Version at generation time: `0.6.7-alpha.1`
23
23
  - Public root export: `@heybox/hb-sdk`
24
24
  - Protocol export: `@heybox/hb-sdk/protocol`
25
25
  - Vite plugin export: `@heybox/hb-sdk/vite`
@@ -579,7 +579,7 @@ await share.screenshot({
579
579
  });
580
580
  ```
581
581
 
582
- 截图分享支持多个预置分区;分区与话题仍由用户在客户端发帖页中确认和修改,SDK 不会直接发布内容。
582
+ 截图分享支持多个预置分区;分区与话题仍由用户在客户端发帖页中确认和修改,SDK 不会直接发布内容。通过截图分享进入社区发帖流程时,客户端会自动把帖子关联到当前小程序,开发者无需配置额外来源字段。
583
583
 
584
584
  ### 基础 UI
585
585
 
@@ -385,7 +385,7 @@ await share.showShareMenu({
385
385
 
386
386
  ## 截图分享
387
387
 
388
- 截图分享可以预置多个分区,客户端发帖页负责最终选择与确认。
388
+ 截图分享可以预置多个分区,客户端发帖页负责最终选择与确认。进入社区发帖流程后,客户端会自动把帖子关联到当前小程序,开发者无需配置额外来源字段。
389
389
 
390
390
  ```ts
391
391
  await share.screenshot({
package/skill/skill.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "hb-sdk",
3
- "skillVersion": "0.6.6+skill.ec6411dd6834",
3
+ "skillVersion": "0.6.7-alpha.1+skill.00dab20ae3bc",
4
4
  "sdk": {
5
5
  "package": "@heybox/hb-sdk",
6
- "version": "0.6.6",
7
- "compatibility": "0.6.6"
6
+ "version": "0.6.7-alpha.1",
7
+ "compatibility": "0.6.7-alpha.1"
8
8
  },
9
9
  "source": "https://open.xiaoheihe.cn/agent-skills/hb-sdk",
10
- "integrity": "sha256-ec6411dd683403ca3e7e92ed169848274d6d7a7492759cbedfc38fb4b866e23a"
10
+ "integrity": "sha256-00dab20ae3bceff225037abb08cf86b24daee2d7b2002aa90e720492ef8b58f8"
11
11
  }