@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.
- package/README.md +39 -5
- package/dist/cli-chunks/{create-BahMMgJH.cjs → create-BiCyOEAv.cjs} +1 -1
- package/dist/cli-chunks/{dev-CTuXVPpU.cjs → dev-D4XRqzz1.cjs} +1 -1
- package/dist/cli-chunks/{doctor-9gg3ZIvt.cjs → doctor-CmHZYQ2I.cjs} +1 -1
- package/dist/cli-chunks/{index-CLne_LW7.cjs → index-DXS0s9d7.cjs} +2 -2
- package/dist/cli-chunks/{index-DuwxUSkq.cjs → index-kv8oOmFw.cjs} +13 -13
- package/dist/cli-chunks/{login-OqaEx-Wd.cjs → login-F9AEL3cF.cjs} +2 -2
- package/dist/cli-chunks/{remote-zX17hOT4.cjs → remote-BRktlraB.cjs} +210 -91
- package/dist/cli-chunks/{session-D7lF9mpd.cjs → session-DItg0094.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/main.js +987 -7
- package/dist/index.cjs.js +51 -0
- package/dist/index.esm.js +51 -0
- package/dist/miniapp-publish.cjs.js +16 -0
- package/dist/miniapp-publish.esm.js +14 -1
- package/dist/protocol.cjs.js +50 -0
- package/dist/protocol.esm.js +46 -1
- package/dist/templates/vue3-vite-ts/README.md.ejs +2 -1
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/api-protocol.md +22 -2
- package/skill/references/api-root.md +70 -2
- package/skill/references/cli.md +6 -3
- package/skill/references/safety-boundaries.md +2 -1
- package/skill/skill.json +4 -4
- package/types/index.d.ts +1 -1
- package/types/miniapp-publish/index.d.ts +10 -0
- package/types/modules/share/types.d.ts +2 -2
- package/types/modules/user/get-current-user-detail.d.ts +9 -0
- package/types/modules/user/get-current-user-profile.d.ts +9 -0
- package/types/modules/user/get-platform-account-info.d.ts +12 -0
- package/types/modules/user/get-platform-account-overview.d.ts +9 -0
- package/types/modules/user/get-steam-game-list.d.ts +12 -0
- package/types/modules/user/index.d.ts +33 -1
- package/types/modules/user/types.d.ts +285 -0
- package/types/protocol/capabilities.d.ts +52 -2
- 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-
|
|
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-
|
|
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
|
|
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
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
const
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
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
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
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-
|
|
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',
|
|
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.
|
|
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.
|
|
3266
|
-
options.logger.info(`
|
|
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.
|
|
3276
|
-
options.logger.info(`
|
|
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
|
|
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,
|
|
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
|
|
3875
|
-
const items =
|
|
3876
|
-
const output = { changed: false, items: toCamelCaseDeep(items), total:
|
|
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
|
|
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:
|
|
3967
|
+
entityId: switchedEntityId,
|
|
3912
3968
|
entityName: switched.entity_name || '--',
|
|
3913
|
-
...(
|
|
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 ?? '--'}
|
|
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
|
|
4066
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 ===
|
|
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
|
-
|
|
4192
|
-
|
|
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
|
-
|
|
4195
|
-
|
|
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
|
|
4233
|
-
if (
|
|
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:
|
|
4329
|
+
entity_id: entityId,
|
|
4239
4330
|
entity_name: typeof value.entity_name === 'string' ? value.entity_name : undefined,
|
|
4240
|
-
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:
|
|
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.
|
|
4381
|
-
logger.info(`
|
|
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) {
|