@heybox/hb-sdk 0.4.6 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +39 -5
  2. package/dist/cli-chunks/{create-BahMMgJH.cjs → create-BiCyOEAv.cjs} +1 -1
  3. package/dist/cli-chunks/{dev-CTuXVPpU.cjs → dev-D4XRqzz1.cjs} +1 -1
  4. package/dist/cli-chunks/{doctor-9gg3ZIvt.cjs → doctor-CmHZYQ2I.cjs} +1 -1
  5. package/dist/cli-chunks/{index-CLne_LW7.cjs → index-DXS0s9d7.cjs} +2 -2
  6. package/dist/cli-chunks/{index-DuwxUSkq.cjs → index-kv8oOmFw.cjs} +13 -13
  7. package/dist/cli-chunks/{login-OqaEx-Wd.cjs → login-F9AEL3cF.cjs} +2 -2
  8. package/dist/cli-chunks/{remote-zX17hOT4.cjs → remote-BRktlraB.cjs} +210 -91
  9. package/dist/cli-chunks/{session-D7lF9mpd.cjs → session-DItg0094.cjs} +1 -1
  10. package/dist/cli.cjs +1 -1
  11. package/dist/devtools/mock-host/main.js +987 -7
  12. package/dist/index.cjs.js +51 -0
  13. package/dist/index.esm.js +51 -0
  14. package/dist/miniapp-publish.cjs.js +16 -0
  15. package/dist/miniapp-publish.esm.js +14 -1
  16. package/dist/protocol.cjs.js +50 -0
  17. package/dist/protocol.esm.js +46 -1
  18. package/dist/templates/vue3-vite-ts/README.md.ejs +2 -1
  19. package/package.json +1 -1
  20. package/skill/SKILL.md +1 -1
  21. package/skill/references/api-protocol.md +22 -2
  22. package/skill/references/api-root.md +70 -2
  23. package/skill/references/cli.md +6 -3
  24. package/skill/references/safety-boundaries.md +2 -1
  25. package/skill/skill.json +4 -4
  26. package/types/index.d.ts +1 -1
  27. package/types/miniapp-publish/index.d.ts +10 -0
  28. package/types/modules/share/types.d.ts +2 -2
  29. package/types/modules/user/get-current-user-detail.d.ts +9 -0
  30. package/types/modules/user/get-current-user-profile.d.ts +9 -0
  31. package/types/modules/user/get-platform-account-info.d.ts +12 -0
  32. package/types/modules/user/get-platform-account-overview.d.ts +9 -0
  33. package/types/modules/user/get-steam-game-list.d.ts +12 -0
  34. package/types/modules/user/index.d.ts +33 -1
  35. package/types/modules/user/types.d.ts +285 -0
  36. package/types/protocol/capabilities.d.ts +52 -2
  37. package/types/protocol.d.ts +2 -2
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var promises = require('node:readline/promises');
4
- var session = require('./session-D7lF9mpd.cjs');
4
+ var session = require('./session-DItg0094.cjs');
5
5
  var childProcess = require('node:child_process');
6
6
  var fs = require('node:fs');
7
7
  var fs$1 = require('node:fs/promises');
8
8
  var path = require('node:path');
9
- var index = require('./index-DuwxUSkq.cjs');
9
+ var index = require('./index-kv8oOmFw.cjs');
10
10
 
11
11
  var re = {exports: {}};
12
12
 
@@ -2858,6 +2858,8 @@ function formatReason(error) {
2858
2858
 
2859
2859
  const MINIAPP_UPLOAD_SCOPE = 'activity';
2860
2860
  const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
2861
+ const MINIAPP_UPLOAD_BATCH_SIZE = 50;
2862
+ const MINIAPP_UPLOAD_TOTAL_SIZE_LIMIT_BYTES = 100 * 1024 * 1024;
2861
2863
  const USER_MINIPROGRAM_ACCESS_STATUS_API_PATH = '/mall/developer/user_miniprogram/access_status';
2862
2864
  const DEVELOPER_ENTITY_LIST_API_PATH = '/mall/developer/entity/list';
2863
2865
  const DEVELOPER_ENTITY_SWITCH_API_PATH = '/mall/developer/entity/switch';
@@ -2916,6 +2918,17 @@ function validateUploadPaths(items, options) {
2916
2918
  }
2917
2919
  return undefined;
2918
2920
  }
2921
+ function validateUploadTotalSize(items, options = {}) {
2922
+ const limit = options.limitBytes ?? MINIAPP_UPLOAD_TOTAL_SIZE_LIMIT_BYTES;
2923
+ const total = items.reduce((sum, item) => {
2924
+ const size = Number(item.size);
2925
+ return sum + (Number.isFinite(size) && size > 0 ? size : 0);
2926
+ }, 0);
2927
+ if (total > limit) {
2928
+ return '构建产物总大小超过 100MB,请删除未引用资源或压缩图片后重新 deploy';
2929
+ }
2930
+ return undefined;
2931
+ }
2919
2932
  function shouldUploadDistFile(relativePath) {
2920
2933
  const normalized = normalizeRelativePath(relativePath);
2921
2934
  if (!normalized) {
@@ -2978,7 +2991,74 @@ async function runUpload(options, runtime = {}) {
2978
2991
  const postCDNUploadCallback$1 = runtime.postCDNUploadCallback ?? postCDNUploadCallback;
2979
2992
  const createReadStream = runtime.createReadStream ?? fs.createReadStream;
2980
2993
  const orderedFiles = [...options.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
2981
- const fileInfos = orderedFiles.map((file) => ({
2994
+ const batches = chunkUploadFiles(orderedFiles, MINIAPP_UPLOAD_BATCH_SIZE);
2995
+ await logger.task(`正在上传 ${orderedFiles.length} 个文件`, async (taskContext) => {
2996
+ logger.debug(`上传并发数: ${concurrency}`);
2997
+ logger.debug(`上传批次数: ${batches.length}`);
2998
+ let completed = 0;
2999
+ for (let batchIndex = 0; batchIndex < batches.length; batchIndex += 1) {
3000
+ const batch = batches[batchIndex];
3001
+ logger.debug(`正在处理上传批次 ${batchIndex + 1}/${batches.length},文件数: ${batch.length}`);
3002
+ logger.debug('正在获取 CDN 上传信息');
3003
+ const fileInfos = createUploadFileInfos(batch, options);
3004
+ const uploadInfo = await getCDNUploadInfo$1({ session: options.session, scope: MINIAPP_UPLOAD_SCOPE, fileInfos, needCache: false }, { baseUrl: runtime.baseUrl, fetchImpl });
3005
+ logger.debug(`CDN bucket: ${uploadInfo.bucket}`);
3006
+ logger.debug(`CDN region: ${uploadInfo.region}`);
3007
+ validateUploadInfoKeys(batch, uploadInfo.keys, options);
3008
+ const indexedFiles = batch.map((file, index) => ({ file, key: uploadInfo.keys[index] }));
3009
+ const batchKeys = indexedFiles.map(({ key }) => key);
3010
+ logger.debug('正在获取 CDN 上传凭证');
3011
+ const uploadToken = await getCDNUploadToken$1({
3012
+ session: options.session,
3013
+ bucket: uploadInfo.bucket,
3014
+ keys: batchKeys,
3015
+ mimetypes: indexedFiles.map(({ file }) => file.mimeType),
3016
+ isMultipartUpload: 0,
3017
+ }, { baseUrl: runtime.baseUrl, fetchImpl });
3018
+ const cos = runtime.createCosClient ? runtime.createCosClient({ session: options.session, uploadToken }) : await createDefaultCosClient(uploadToken);
3019
+ const queue = indexedFiles.slice();
3020
+ const workers = Array.from({ length: Math.min(concurrency, indexedFiles.length) }, async () => {
3021
+ while (queue.length > 0) {
3022
+ const uploadTask = queue.shift();
3023
+ if (!uploadTask) {
3024
+ return;
3025
+ }
3026
+ try {
3027
+ await cos.putObject({
3028
+ Bucket: uploadInfo.bucket,
3029
+ Region: uploadInfo.region,
3030
+ Key: uploadTask.key,
3031
+ Body: createReadStream(uploadTask.file.absolutePath),
3032
+ ContentLength: uploadTask.file.size,
3033
+ ContentType: uploadTask.file.mimeType,
3034
+ });
3035
+ completed += 1;
3036
+ taskContext.update(`正在上传 ${completed}/${orderedFiles.length} 个文件`);
3037
+ logger.debug(`[${String(completed).padStart(2)}/${orderedFiles.length}] ok ${uploadTask.file.relativePath} (${formatSize(uploadTask.file.size)})`);
3038
+ }
3039
+ catch (error) {
3040
+ completed += 1;
3041
+ const message = readErrorMessage(error);
3042
+ logger.debug(`[${String(completed).padStart(2)}/${orderedFiles.length}] error ${uploadTask.file.relativePath} -> ${message}`);
3043
+ throw new index.CliError(`上传文件失败:${uploadTask.file.relativePath} -> ${message}`, readVerboseUploadError(uploadTask.file.relativePath, error));
3044
+ }
3045
+ }
3046
+ });
3047
+ await Promise.all(workers);
3048
+ logger.debug('正在确认 CDN 上传结果');
3049
+ await postCDNUploadCallback$1({ session: options.session, keys: batchKeys, isFinished: true }, { baseUrl: runtime.baseUrl, fetchImpl });
3050
+ }
3051
+ }, { successText: `已上传 ${orderedFiles.length} 个文件` });
3052
+ }
3053
+ function chunkUploadFiles(files, batchSize) {
3054
+ const batches = [];
3055
+ for (let index = 0; index < files.length; index += batchSize) {
3056
+ batches.push(files.slice(index, index + batchSize));
3057
+ }
3058
+ return batches;
3059
+ }
3060
+ function createUploadFileInfos(files, options) {
3061
+ return files.map((file) => ({
2982
3062
  name: file.relativePath.split('/').pop() ?? file.relativePath,
2983
3063
  mimetype: file.mimeType,
2984
3064
  fsize: file.size,
@@ -2988,56 +3068,22 @@ async function runUpload(options, runtime = {}) {
2988
3068
  relativePath: file.relativePath,
2989
3069
  }),
2990
3070
  }));
2991
- await logger.task(`正在上传 ${orderedFiles.length} 个文件`, async (taskContext) => {
2992
- logger.debug(`上传并发数: ${concurrency}`);
2993
- logger.debug('正在获取 CDN 上传信息');
2994
- const uploadInfo = await getCDNUploadInfo$1({ session: options.session, scope: MINIAPP_UPLOAD_SCOPE, fileInfos, needCache: false }, { baseUrl: runtime.baseUrl, fetchImpl });
2995
- logger.debug(`CDN bucket: ${uploadInfo.bucket}`);
2996
- logger.debug(`CDN region: ${uploadInfo.region}`);
2997
- const indexedFiles = orderedFiles.map((file, index) => ({ file, key: uploadInfo.keys[index] }));
2998
- logger.debug('正在获取 CDN 上传凭证');
2999
- const cos = runtime.createCosClient
3000
- ? runtime.createCosClient({ session: options.session })
3001
- : await createDefaultCosClient(await getCDNUploadToken$1({
3002
- session: options.session,
3003
- bucket: uploadInfo.bucket,
3004
- keys: indexedFiles.map(({ key }) => key),
3005
- mimetypes: indexedFiles.map(({ file }) => file.mimeType),
3006
- isMultipartUpload: 0,
3007
- }, { baseUrl: runtime.baseUrl, fetchImpl }));
3008
- const queue = indexedFiles.slice();
3009
- let completed = 0;
3010
- const workers = Array.from({ length: Math.min(concurrency, indexedFiles.length) }, async () => {
3011
- while (queue.length > 0) {
3012
- const uploadTask = queue.shift();
3013
- if (!uploadTask) {
3014
- return;
3015
- }
3016
- try {
3017
- await cos.putObject({
3018
- Bucket: uploadInfo.bucket,
3019
- Region: uploadInfo.region,
3020
- Key: uploadTask.key,
3021
- Body: createReadStream(uploadTask.file.absolutePath),
3022
- ContentLength: uploadTask.file.size,
3023
- ContentType: uploadTask.file.mimeType,
3024
- });
3025
- completed += 1;
3026
- taskContext.update(`正在上传 ${completed}/${indexedFiles.length} 个文件`);
3027
- logger.debug(`[${String(completed).padStart(2)}/${indexedFiles.length}] ok ${uploadTask.file.relativePath} (${formatSize(uploadTask.file.size)})`);
3028
- }
3029
- catch (error) {
3030
- completed += 1;
3031
- const message = readErrorMessage(error);
3032
- logger.debug(`[${String(completed).padStart(2)}/${indexedFiles.length}] error ${uploadTask.file.relativePath} -> ${message}`);
3033
- throw new index.CliError(`上传文件失败:${uploadTask.file.relativePath} -> ${message}`, readVerboseUploadError(uploadTask.file.relativePath, error));
3034
- }
3035
- }
3071
+ }
3072
+ function validateUploadInfoKeys(files, keys, options) {
3073
+ if (keys.length !== files.length) {
3074
+ throw new index.CliError(`CDN 上传接口返回 key 数量异常:期望 ${files.length},实际 ${keys.length}`);
3075
+ }
3076
+ for (let index$1 = 0; index$1 < files.length; index$1 += 1) {
3077
+ const expectedKey = getMiniappUploadKey({
3078
+ miniProgramId: options.miniProgramId,
3079
+ version: options.version,
3080
+ relativePath: files[index$1].relativePath,
3036
3081
  });
3037
- await Promise.all(workers);
3038
- logger.debug('正在确认 CDN 上传结果');
3039
- await postCDNUploadCallback$1({ session: options.session, keys: uploadInfo.keys, isFinished: true }, { baseUrl: runtime.baseUrl, fetchImpl });
3040
- }, { successText: `已上传 ${orderedFiles.length} 个文件` });
3082
+ const actualKey = keys[index$1];
3083
+ if (actualKey !== expectedKey) {
3084
+ throw new index.CliError(`CDN 上传接口返回 key 异常:${files[index$1].relativePath}`, [`CDN 上传接口返回 key 异常:${files[index$1].relativePath}`, `expected: ${expectedKey}`, `actual: ${actualKey}`].join('\n'));
3085
+ }
3086
+ }
3041
3087
  }
3042
3088
  async function createDefaultCosClient(uploadToken) {
3043
3089
  const COS = await loadCosConstructor();
@@ -3067,7 +3113,7 @@ async function createDefaultCosClient(uploadToken) {
3067
3113
  };
3068
3114
  }
3069
3115
  async function loadCosConstructor() {
3070
- const cosModule = await Promise.resolve().then(function () { return require('./index-CLne_LW7.cjs'); }).then(function (n) { return n.index; });
3116
+ const cosModule = await Promise.resolve().then(function () { return require('./index-DXS0s9d7.cjs'); }).then(function (n) { return n.index; });
3071
3117
  return cosModule.default;
3072
3118
  }
3073
3119
  function formatSize(bytes) {
@@ -3233,6 +3279,10 @@ async function runDeployCommand(options, runtime = {}) {
3233
3279
  if (pathError) {
3234
3280
  throw new Error(pathError);
3235
3281
  }
3282
+ const sizeError = validateUploadTotalSize(files);
3283
+ if (sizeError) {
3284
+ throw new Error(sizeError);
3285
+ }
3236
3286
  logger.debug(`待上传文件数: ${files.length}`);
3237
3287
  return files;
3238
3288
  }, { successText: 'dist 上传文件校验完成' });
@@ -3249,12 +3299,12 @@ async function runDeployCommand(options, runtime = {}) {
3249
3299
  catch (error) {
3250
3300
  throw translateHeyboxDeployError(error, { projectRoot, stage: 'submitAudit', version });
3251
3301
  }
3252
- printDeploySuccess({ autoPublish, logger, miniProgramId, mode: options.successOutputMode ?? 'legacy', previewUrl: submitAuditResult.preview_url, version });
3302
+ printDeploySuccess({ autoPublish, logger, miniProgramId, mode: options.successOutputMode ?? 'legacy', protocolString: submitAuditResult.protocol_string, version });
3253
3303
  return {
3254
3304
  autoPublish,
3255
3305
  changed: true,
3256
3306
  miniProgramId,
3257
- ...(submitAuditResult.preview_url ? { previewUrl: submitAuditResult.preview_url } : {}),
3307
+ ...(submitAuditResult.protocol_string ? { protocolString: submitAuditResult.protocol_string } : {}),
3258
3308
  version,
3259
3309
  };
3260
3310
  }
@@ -3262,8 +3312,8 @@ function printDeploySuccess(options) {
3262
3312
  options.logger.success(`提交审核成功:${options.miniProgramId} ${options.version}`);
3263
3313
  if (options.mode === 'remote') {
3264
3314
  options.logger.info(`发布策略:${options.autoPublish ? '审核通过后自动发布' : '审核通过后需手动发布'}`);
3265
- if (options.previewUrl) {
3266
- options.logger.info(`Preview URL: ${options.previewUrl}`);
3315
+ if (options.protocolString) {
3316
+ options.logger.info(`Protocol: ${options.protocolString}`);
3267
3317
  options.logger.info('允许他人预览:hb-sdk remote allowlist add <heybox_id>');
3268
3318
  }
3269
3319
  options.logger.info(options.autoPublish
@@ -3272,8 +3322,8 @@ function printDeploySuccess(options) {
3272
3322
  return;
3273
3323
  }
3274
3324
  options.logger.info(`发布策略:${options.autoPublish ? '审核通过后自动发布' : '审核通过后需在开放平台手动发布'}`);
3275
- if (options.previewUrl) {
3276
- options.logger.info(`Preview URL: ${options.previewUrl}`);
3325
+ if (options.protocolString) {
3326
+ options.logger.info(`Protocol: ${options.protocolString}`);
3277
3327
  }
3278
3328
  }
3279
3329
  function findProjectRoot(startDir) {
@@ -3840,14 +3890,14 @@ async function createRemoteCommandContext(options, runtime) {
3840
3890
  function adaptRemoteApiClient(api) {
3841
3891
  return {
3842
3892
  accessStatus: () => api.getDeveloperAccessStatus(),
3843
- listMiniPrograms: ({ keyword, status }) => api.listUserMiniprograms({ keyword, status, offset: 0, limit: 200 }),
3893
+ listMiniPrograms: ({ keyword, limit = 200, offset = 0, status }) => api.listUserMiniprograms({ keyword, status, offset, limit }),
3844
3894
  createMiniProgram: ({ name, previewImageUrl }) => api.createUserMiniprogram({ name, ...(previewImageUrl ? { preview_image_url: previewImageUrl } : {}) }),
3845
3895
  updateMiniProgram: ({ miniProgramId, name, previewImageUrl }) => api.updateUserMiniprogram({ mini_program_id: miniProgramId, name, preview_image_url: previewImageUrl }),
3846
3896
  getMiniProgramDetail: (miniProgramId) => api.getUserMiniprogramDetail({ mini_program_id: miniProgramId }),
3847
3897
  getAllowlist: (miniProgramId) => api.getPreviewAllowlist({ mini_program_id: miniProgramId }),
3848
3898
  updateAllowlist: ({ miniProgramId, heyboxIds }) => api.updatePreviewAllowlist({ mini_program_id: miniProgramId, heybox_ids: heyboxIds }),
3849
3899
  listVersions: (miniProgramId) => api.listUserMiniprogramVersions({ mini_program_id: miniProgramId, offset: 0, limit: 50 }),
3850
- getPreviewInfo: ({ miniProgramId, version }) => api.getVersionPreviewInfo({ mini_program_id: miniProgramId, preview_version: version }),
3900
+ getPreviewInfo: ({ miniProgramId, version }) => api.getVersionPreviewInfo({ mini_program_id: miniProgramId, version }),
3851
3901
  listDeveloperEntities: () => api.listDeveloperEntities(),
3852
3902
  switchDeveloperEntity: ({ entityId }) => api.switchDeveloperEntity({ entity_id: entityId }),
3853
3903
  releaseVersion: ({ miniProgramId, version }) => api.releaseUserMiniprogramVersion({ mini_program_id: miniProgramId, version }),
@@ -3871,9 +3921,9 @@ async function remoteAccess(options, context, runtime) {
3871
3921
  return finishRemoteCommand(options, runtime, output);
3872
3922
  }
3873
3923
  async function remoteEntityList(options, context, runtime) {
3874
- const result = await context.api.listDeveloperEntities();
3875
- const items = normalizeDeveloperEntities(result);
3876
- const output = { changed: false, items: toCamelCaseDeep(items), total: readNumber(result.total, items.length) };
3924
+ const result = await listDeveloperEntitiesWithAccessFallback(context);
3925
+ const items = result.items;
3926
+ const output = { changed: false, items: toCamelCaseDeep(items), total: result.total };
3877
3927
  if (!options.json) {
3878
3928
  if (items.length === 0) {
3879
3929
  context.logger.info('当前账号未绑定开发者主体');
@@ -3899,18 +3949,24 @@ async function remoteEntityCurrent(options, context, runtime) {
3899
3949
  }
3900
3950
  async function remoteEntitySwitch(options, context, runtime) {
3901
3951
  const entityId = parseEntityId(options.entityId);
3902
- const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
3952
+ const entityList = await listDeveloperEntitiesWithAccessFallback(context);
3953
+ const entities = entityList.items;
3903
3954
  const target = entities.find((entity) => entity.entity_id === entityId);
3904
3955
  if (!target) {
3905
3956
  throw new Error(`当前账号不可切换到开发者主体 ${entityId};请先运行 hb-sdk remote entity list 查看可用主体`);
3906
3957
  }
3907
- const result = await context.api.switchDeveloperEntity({ entityId });
3958
+ const result = entityList.fromAccessFallback === true && target.is_current === true ? target : await context.api.switchDeveloperEntity({ entityId });
3908
3959
  const access = await context.api.accessStatus();
3909
3960
  const switched = normalizeDeveloperEntity(result) ?? { ...target, is_current: true };
3961
+ const switchedEntityId = normalizeEntityId(switched.entity_id);
3962
+ if (switchedEntityId === undefined) {
3963
+ throw new Error('远端响应缺少 entity_id');
3964
+ }
3965
+ const switchedOwnerHeyboxId = normalizePositiveInteger(switched.owner_heybox_id);
3910
3966
  await session.setSelectedDeveloperEntitySnapshot({
3911
- entityId: switched.entity_id,
3967
+ entityId: switchedEntityId,
3912
3968
  entityName: switched.entity_name || '--',
3913
- ...(switched.owner_heybox_id !== undefined ? { ownerHeyboxId: switched.owner_heybox_id } : {}),
3969
+ ...(switchedOwnerHeyboxId !== undefined ? { ownerHeyboxId: switchedOwnerHeyboxId } : {}),
3914
3970
  }, {
3915
3971
  cacheFile: options.cacheFile,
3916
3972
  env: options.env,
@@ -4050,7 +4106,7 @@ async function remoteVersions(options, context, runtime) {
4050
4106
  const output = { changed: false, items: toCamelCaseDeep(items), miniProgramId, total: readNumber(result.total, items.length) };
4051
4107
  if (!options.json) {
4052
4108
  for (const item of items) {
4053
- context.logger.info(`${item.version ?? '--'} status=${item.status ?? '--'} preview=${item.preview_url ?? '--'} publish=${item.publish_url ?? '--'}`);
4109
+ context.logger.info(`${item.version ?? '--'} status=${item.status ?? '--'} auto_publish=${item.auto_publish === true ? 'yes' : 'no'}`);
4054
4110
  }
4055
4111
  if (items.length === 0) {
4056
4112
  context.logger.info('暂无远端版本');
@@ -4062,10 +4118,13 @@ async function remotePreview(options, context, runtime) {
4062
4118
  const miniProgramId = requireBinding(context);
4063
4119
  const version = requireNonEmpty(options.version, 'remote preview 必须传 <version>');
4064
4120
  const result = await context.api.getPreviewInfo({ miniProgramId, version });
4065
- const previewUrl = String(result.preview_url || result.publish_url || result.page_url || '');
4066
- const output = { changed: false, miniProgramId, previewUrl, version, preview: toCamelCaseDeep(result) };
4121
+ const protocolString = String(result.protocol_string || '');
4122
+ if (!protocolString) {
4123
+ throw new Error(`版本 ${version} 暂无 protocol_string,无法打开预览`);
4124
+ }
4125
+ const output = { changed: false, miniProgramId, protocolString, version, preview: toCamelCaseDeep(result) };
4067
4126
  if (!options.json) {
4068
- context.logger.info(previewUrl ? `Preview URL: ${previewUrl}` : `版本 ${version} 暂无 preview URL`);
4127
+ context.logger.info(`Protocol: ${protocolString}`);
4069
4128
  }
4070
4129
  return finishRemoteCommand(options, runtime, output);
4071
4130
  }
@@ -4140,7 +4199,7 @@ function requireBinding(context) {
4140
4199
  return context.binding;
4141
4200
  }
4142
4201
  async function requireCurrentDeveloperEntity(context) {
4143
- const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
4202
+ const entities = (await listDeveloperEntitiesWithAccessFallback(context)).items;
4144
4203
  const current = entities.find((entity) => entity.is_current === true);
4145
4204
  if (!current) {
4146
4205
  throw new Error('当前账号没有服务端 current 开发者主体;请先运行 hb-sdk remote entity list 查看可用主体,并用 hb-sdk remote entity switch <entity-id> 切换');
@@ -4148,7 +4207,7 @@ async function requireCurrentDeveloperEntity(context) {
4148
4207
  return current;
4149
4208
  }
4150
4209
  async function confirmCreateWithCurrentEntity(options, context, runtime) {
4151
- const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
4210
+ const entities = (await listDeveloperEntitiesWithAccessFallback(context)).items;
4152
4211
  if (entities.length <= 1) {
4153
4212
  return;
4154
4213
  }
@@ -4175,24 +4234,43 @@ async function confirmCreateWithCurrentEntity(options, context, runtime) {
4175
4234
  }
4176
4235
  }
4177
4236
  async function assertMiniProgramEntityMatchesCurrent(context, detail) {
4178
- if (!isValidEntityId(detail.entity_id)) {
4237
+ const detailEntityId = normalizeEntityId(detail.entity_id);
4238
+ if (detailEntityId === undefined) {
4179
4239
  return;
4180
4240
  }
4181
4241
  const current = await requireCurrentDeveloperEntity(context);
4182
- if (current.entity_id === detail.entity_id) {
4242
+ if (current.entity_id === detailEntityId) {
4183
4243
  return;
4184
4244
  }
4185
- throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail(detail) }));
4245
+ throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail({ ...detail, entity_id: detailEntityId }) }));
4186
4246
  }
4187
4247
  async function assertBoundMiniProgramEntityMatchesCurrent(context, miniProgramId) {
4188
4248
  const current = await requireCurrentDeveloperEntity(context);
4189
4249
  const detail = await context.api.getMiniProgramDetail(miniProgramId);
4190
4250
  requireMiniProgramId(detail);
4191
- if (!isValidEntityId(detail.entity_id)) {
4192
- throw new Error(`远端小程序 ${miniProgramId} 详情缺少 entity_id,无法校验当前主体一致性,已停止 deploy`);
4251
+ const detailEntityId = normalizeEntityId(detail.entity_id);
4252
+ if (detailEntityId === undefined) {
4253
+ const listed = await findMiniProgramInCurrentEntityList(context, miniProgramId);
4254
+ if (listed) {
4255
+ return;
4256
+ }
4257
+ throw new Error(`远端小程序 ${miniProgramId} 详情缺少 entity_id,且当前主体列表中找不到该小程序,无法校验当前主体一致性,已停止 deploy`);
4258
+ }
4259
+ if (current.entity_id !== detailEntityId) {
4260
+ throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail({ ...detail, entity_id: detailEntityId }) }));
4193
4261
  }
4194
- if (current.entity_id !== detail.entity_id) {
4195
- throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail(detail) }));
4262
+ }
4263
+ async function findMiniProgramInCurrentEntityList(context, miniProgramId) {
4264
+ const pageSize = 200;
4265
+ for (let offset = 0;; offset += pageSize) {
4266
+ const result = await context.api.listMiniPrograms({ limit: pageSize, offset });
4267
+ const items = Array.isArray(result.items) ? result.items : [];
4268
+ if (items.some((item) => item.mini_program_id === miniProgramId)) {
4269
+ return true;
4270
+ }
4271
+ if (items.length < pageSize || offset + items.length >= readNumber(result.total, Number.POSITIVE_INFINITY)) {
4272
+ return false;
4273
+ }
4196
4274
  }
4197
4275
  }
4198
4276
  function createEntityMismatchMessage(options) {
@@ -4221,6 +4299,18 @@ function parseEntityId(value) {
4221
4299
  }
4222
4300
  return entityId;
4223
4301
  }
4302
+ async function listDeveloperEntitiesWithAccessFallback(context) {
4303
+ const result = await context.api.listDeveloperEntities();
4304
+ const items = normalizeDeveloperEntities(result);
4305
+ if (items.length > 0) {
4306
+ return { items, total: readNumber(result.total, items.length) };
4307
+ }
4308
+ const fallback = createEntityFromAccessStatus(await context.api.accessStatus());
4309
+ if (!fallback) {
4310
+ return { items, total: readNumber(result.total, items.length) };
4311
+ }
4312
+ return { fromAccessFallback: true, items: [fallback], total: 1 };
4313
+ }
4224
4314
  function normalizeDeveloperEntities(result) {
4225
4315
  const rawItems = Array.isArray(result.items) ? result.items : [];
4226
4316
  return rawItems.map((item) => normalizeDeveloperEntity(item)).filter((item) => item !== undefined);
@@ -4229,31 +4319,57 @@ function normalizeDeveloperEntity(value) {
4229
4319
  if (!value || typeof value !== 'object') {
4230
4320
  return undefined;
4231
4321
  }
4232
- const rawEntityId = value.entity_id;
4233
- if (!isValidEntityId(rawEntityId)) {
4322
+ const entityId = normalizeEntityId(value.entity_id);
4323
+ if (entityId === undefined) {
4234
4324
  return undefined;
4235
4325
  }
4326
+ const ownerHeyboxId = normalizePositiveInteger(value.owner_heybox_id);
4236
4327
  return {
4237
4328
  ...value,
4238
- entity_id: rawEntityId,
4329
+ entity_id: entityId,
4239
4330
  entity_name: typeof value.entity_name === 'string' ? value.entity_name : undefined,
4240
- owner_heybox_id: isValidHeyboxIdNumber(value.owner_heybox_id)
4241
- ? value.owner_heybox_id
4242
- : undefined,
4331
+ owner_heybox_id: ownerHeyboxId,
4243
4332
  is_current: value.is_current === true,
4244
4333
  };
4245
4334
  }
4246
4335
  function createEntityFromMiniProgramDetail(detail) {
4336
+ const entityId = normalizeEntityId(detail.entity_id);
4247
4337
  return {
4248
- entity_id: detail.entity_id,
4338
+ ...(entityId !== undefined ? { entity_id: entityId } : {}),
4249
4339
  entity_name: typeof detail.developer_name === 'string' ? detail.developer_name : undefined,
4250
- owner_heybox_id: detail.owner_heybox_id,
4340
+ owner_heybox_id: normalizePositiveInteger(detail.owner_heybox_id),
4251
4341
  is_current: false,
4252
4342
  };
4253
4343
  }
4344
+ function createEntityFromAccessStatus(access) {
4345
+ const entity = normalizeDeveloperEntity({
4346
+ entity_id: access.entity_id,
4347
+ entity_name: access.developer_name,
4348
+ owner_heybox_id: access.owner_heybox_id,
4349
+ is_current: true,
4350
+ });
4351
+ return entity;
4352
+ }
4254
4353
  function isValidEntityId(value) {
4255
4354
  return Number.isSafeInteger(value) && Number(value) > 0;
4256
4355
  }
4356
+ function normalizeEntityId(value) {
4357
+ return normalizePositiveInteger(value);
4358
+ }
4359
+ function normalizePositiveInteger(value) {
4360
+ if (typeof value === 'number') {
4361
+ return isValidEntityId(value) ? value : undefined;
4362
+ }
4363
+ if (typeof value !== 'string') {
4364
+ return undefined;
4365
+ }
4366
+ const normalized = value.trim();
4367
+ if (!/^[1-9]\d*$/.test(normalized)) {
4368
+ return undefined;
4369
+ }
4370
+ const parsed = Number(normalized);
4371
+ return isValidEntityId(parsed) ? parsed : undefined;
4372
+ }
4257
4373
  function requireNonEmpty(value, message) {
4258
4374
  const normalized = typeof value === 'string' ? value.trim() : '';
4259
4375
  if (!normalized) {
@@ -4377,8 +4493,11 @@ function printMiniProgramDetail(logger, detail) {
4377
4493
  logger.info(`Name: ${detail.name ?? '--'}`);
4378
4494
  logger.info(`Status: ${detail.status ?? '--'}`);
4379
4495
  logger.info(`Version: ${detail.version || detail.latest_version_status || '--'}`);
4380
- if (detail.publish_url) {
4381
- logger.info(`Publish URL: ${detail.publish_url}`);
4496
+ if (detail.page_url) {
4497
+ logger.info(`Page URL: ${detail.page_url}`);
4498
+ }
4499
+ if (detail.protocol_string) {
4500
+ logger.info(`Protocol: ${detail.protocol_string}`);
4382
4501
  }
4383
4502
  }
4384
4503
  function printDeveloperEntities(logger, entities) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DuwxUSkq.cjs');
3
+ var index = require('./index-kv8oOmFw.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-DuwxUSkq.cjs');
3
+ var index = require('./cli-chunks/index-kv8oOmFw.cjs');
4
4
  require('node:module');
5
5
  require('node:fs');
6
6
  require('node:fs/promises');