@heybox/hb-sdk 0.4.4 → 0.4.6
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 +78 -29
- package/dist/cli-chunks/{create-DAW1oAnH.cjs → create-BahMMgJH.cjs} +1 -1
- package/dist/cli-chunks/{dev-BA_4fnzO.cjs → dev-CTuXVPpU.cjs} +1 -1
- package/dist/cli-chunks/{doctor-Bbv8Lzu_.cjs → doctor-9gg3ZIvt.cjs} +1 -1
- package/dist/cli-chunks/{index-D7-awGYB.cjs → index-CLne_LW7.cjs} +3 -3
- package/dist/cli-chunks/{index-Bboot1us.cjs → index-DuwxUSkq.cjs} +181 -44
- package/dist/cli-chunks/{login-BQo2pIkq.cjs → login-OqaEx-Wd.cjs} +153 -2
- package/dist/cli-chunks/{deploy-BaLyuR1X.cjs → remote-zX17hOT4.cjs} +1008 -304
- package/dist/cli-chunks/{session-DiyDXvXu.cjs → session-D7lF9mpd.cjs} +347 -9
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/main.js +430 -391
- package/dist/miniapp-publish.cjs.js +30 -0
- package/dist/miniapp-publish.esm.js +16 -1
- package/dist/templates/vue3-vite-ts/README.md.ejs +1 -1
- package/dist/templates/vue3-vite-ts/package.json.ejs +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +25 -18
- package/skill/references/api-root.md +2 -2
- package/skill/references/cli.md +120 -350
- package/skill/scripts/sync-references.mjs +84 -5
- package/skill/skill.json +4 -4
- package/types/miniapp-publish/index.d.ts +15 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var promises = require('node:readline/promises');
|
|
4
|
+
var session = require('./session-D7lF9mpd.cjs');
|
|
3
5
|
var childProcess = require('node:child_process');
|
|
4
6
|
var fs = require('node:fs');
|
|
5
7
|
var fs$1 = require('node:fs/promises');
|
|
6
8
|
var path = require('node:path');
|
|
7
|
-
var
|
|
8
|
-
var session = require('./session-DiyDXvXu.cjs');
|
|
9
|
-
var index = require('./index-Bboot1us.cjs');
|
|
10
|
-
var node_crypto = require('node:crypto');
|
|
9
|
+
var index = require('./index-DuwxUSkq.cjs');
|
|
11
10
|
|
|
12
11
|
var re = {exports: {}};
|
|
13
12
|
|
|
@@ -2859,8 +2858,23 @@ function formatReason(error) {
|
|
|
2859
2858
|
|
|
2860
2859
|
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
2861
2860
|
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
2861
|
+
const USER_MINIPROGRAM_ACCESS_STATUS_API_PATH = '/mall/developer/user_miniprogram/access_status';
|
|
2862
|
+
const DEVELOPER_ENTITY_LIST_API_PATH = '/mall/developer/entity/list';
|
|
2863
|
+
const DEVELOPER_ENTITY_SWITCH_API_PATH = '/mall/developer/entity/switch';
|
|
2864
|
+
const LIST_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/list';
|
|
2865
|
+
const CREATE_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/create';
|
|
2866
|
+
const UPDATE_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/update';
|
|
2867
|
+
const DETAIL_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/detail';
|
|
2868
|
+
const USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH = '/mall/developer/user_miniprogram/preview_allowlist';
|
|
2869
|
+
const UPDATE_USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH = '/mall/developer/user_miniprogram/preview_allowlist/update';
|
|
2862
2870
|
const PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH = '/mall/developer/user_miniprogram/version/precheck';
|
|
2863
2871
|
const SUBMIT_USER_MINIPROGRAM_AUDIT_API_PATH = '/mall/developer/user_miniprogram/version/submit_audit';
|
|
2872
|
+
const USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH = '/mall/developer/user_miniprogram/version/preview_info';
|
|
2873
|
+
const WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH = '/mall/developer/user_miniprogram/version/withdraw';
|
|
2874
|
+
const RELEASE_USER_MINIPROGRAM_VERSION_API_PATH = '/mall/developer/user_miniprogram/version/release';
|
|
2875
|
+
const TAKE_DOWN_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/take_down';
|
|
2876
|
+
const REOPEN_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/reopen';
|
|
2877
|
+
const LIST_USER_MINIPROGRAM_VERSION_API_PATH = '/mall/developer/user_miniprogram/version/list';
|
|
2864
2878
|
const FNV_OFFSET = 0x811c9dc5;
|
|
2865
2879
|
const FNV_PRIME = 0x01000193;
|
|
2866
2880
|
function normalizeRelativePath(relativePath) {
|
|
@@ -2919,281 +2933,6 @@ function shouldUploadDistFile(relativePath) {
|
|
|
2919
2933
|
return true;
|
|
2920
2934
|
}
|
|
2921
2935
|
|
|
2922
|
-
const globalHeyboxCliRequestConfig = {};
|
|
2923
|
-
function readHeyboxCliRequestConfig() {
|
|
2924
|
-
return normalizeHeyboxRylaiServiceTagConfig(globalHeyboxCliRequestConfig);
|
|
2925
|
-
}
|
|
2926
|
-
function resolveHeyboxRylaiServiceTag(pathWithQuery, config = readHeyboxCliRequestConfig()) {
|
|
2927
|
-
const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
|
|
2928
|
-
const pathname = pathWithQuery ? getPathname(pathWithQuery) : '';
|
|
2929
|
-
const specialTag = normalized.special_tag;
|
|
2930
|
-
if (pathname && specialTag?.path_prefix_list.some((prefix) => pathname.startsWith(prefix))) {
|
|
2931
|
-
return specialTag.tag_name;
|
|
2932
|
-
}
|
|
2933
|
-
return normalized.default_tag;
|
|
2934
|
-
}
|
|
2935
|
-
function normalizeHeyboxRylaiServiceTagConfig(config) {
|
|
2936
|
-
const defaultTag = normalizeHeyboxRylaiServiceTag(config.default_tag);
|
|
2937
|
-
const specialTagName = normalizeHeyboxRylaiServiceTag(config.special_tag?.tag_name);
|
|
2938
|
-
const pathPrefixList = config.special_tag?.path_prefix_list?.filter(isValidPathPrefix) || [];
|
|
2939
|
-
return {
|
|
2940
|
-
...(defaultTag ? { default_tag: defaultTag } : {}),
|
|
2941
|
-
...(specialTagName && pathPrefixList.length
|
|
2942
|
-
? {
|
|
2943
|
-
special_tag: {
|
|
2944
|
-
tag_name: specialTagName,
|
|
2945
|
-
path_prefix_list: pathPrefixList,
|
|
2946
|
-
},
|
|
2947
|
-
}
|
|
2948
|
-
: {}),
|
|
2949
|
-
};
|
|
2950
|
-
}
|
|
2951
|
-
function normalizeHeyboxRylaiServiceTag(value) {
|
|
2952
|
-
const tag = String(value ?? '').trim();
|
|
2953
|
-
if (!tag) {
|
|
2954
|
-
return undefined;
|
|
2955
|
-
}
|
|
2956
|
-
if (/[\r\n]/.test(tag)) {
|
|
2957
|
-
throw new Error('x-rylai-service-tag 不允许包含换行符');
|
|
2958
|
-
}
|
|
2959
|
-
return tag;
|
|
2960
|
-
}
|
|
2961
|
-
function isValidPathPrefix(value) {
|
|
2962
|
-
return typeof value === 'string' && value.startsWith('/') && !/[\r\n]/.test(value);
|
|
2963
|
-
}
|
|
2964
|
-
function getPathname(pathWithQuery) {
|
|
2965
|
-
try {
|
|
2966
|
-
return new URL(pathWithQuery, 'https://api.xiaoheihe.cn').pathname;
|
|
2967
|
-
}
|
|
2968
|
-
catch {
|
|
2969
|
-
return '';
|
|
2970
|
-
}
|
|
2971
|
-
}
|
|
2972
|
-
|
|
2973
|
-
const SIGN_VERSION = '999.0.4';
|
|
2974
|
-
const SIGN_CHARSET = 'AB45STUVWZEFGJ6CH01D237IXYPQRKLMN89';
|
|
2975
|
-
function createHeyboxOpenPlatformSignParams(pathname, options = {}) {
|
|
2976
|
-
const now = options.now ?? new Date();
|
|
2977
|
-
const time = Math.trunc(now.getTime() / 1000);
|
|
2978
|
-
const nonce = options.nonce ?? md5(`${time}${Date.now()}${node_crypto.randomBytes(16).toString('hex')}`).toUpperCase();
|
|
2979
|
-
return {
|
|
2980
|
-
version: SIGN_VERSION,
|
|
2981
|
-
hkey: generateSignature(pathname, time + 1, nonce),
|
|
2982
|
-
_time: time,
|
|
2983
|
-
nonce,
|
|
2984
|
-
};
|
|
2985
|
-
}
|
|
2986
|
-
function generateSignature(path, time, nonce) {
|
|
2987
|
-
const normalizedPath = `/${path
|
|
2988
|
-
.split('/')
|
|
2989
|
-
.filter(Boolean)
|
|
2990
|
-
.join('/')}/`;
|
|
2991
|
-
const transformedTime = transformWithOffset(String(time), SIGN_CHARSET, -2);
|
|
2992
|
-
const transformedPath = transform(normalizedPath, SIGN_CHARSET);
|
|
2993
|
-
const transformedNonce = transform(nonce, SIGN_CHARSET);
|
|
2994
|
-
const combined = interleave([transformedTime, transformedPath, transformedNonce]).slice(0, 20);
|
|
2995
|
-
const hash = md5(combined);
|
|
2996
|
-
let sign = `${mixColumns(hash.slice(-6).split('').map((char) => char.charCodeAt(0))).reduce((sum, value) => sum + value, 0) % 100}`;
|
|
2997
|
-
sign = sign.length < 2 ? `0${sign}` : sign;
|
|
2998
|
-
return `${transformWithOffset(hash.substring(0, 5), SIGN_CHARSET, -4)}${sign}`;
|
|
2999
|
-
}
|
|
3000
|
-
function transformWithOffset(str, charset, offset) {
|
|
3001
|
-
return transform(str, charset.slice(0, offset));
|
|
3002
|
-
}
|
|
3003
|
-
function transform(str, charset) {
|
|
3004
|
-
let output = '';
|
|
3005
|
-
for (let index = 0; index < str.length; index += 1) {
|
|
3006
|
-
output += charset[str.charCodeAt(index) % charset.length];
|
|
3007
|
-
}
|
|
3008
|
-
return output;
|
|
3009
|
-
}
|
|
3010
|
-
function interleave(strings) {
|
|
3011
|
-
let output = '';
|
|
3012
|
-
const maxLength = Math.max(...strings.map((str) => str.length));
|
|
3013
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
3014
|
-
for (const str of strings) {
|
|
3015
|
-
if (index < str.length) {
|
|
3016
|
-
output += str[index];
|
|
3017
|
-
}
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
return output;
|
|
3021
|
-
}
|
|
3022
|
-
function mixColumns(column) {
|
|
3023
|
-
const output = [...column];
|
|
3024
|
-
output[0] = multiplyE(column[0]) ^ multiply4(column[1]) ^ multiply3(column[2]) ^ multiply2(column[3]);
|
|
3025
|
-
output[1] = multiply2(column[0]) ^ multiplyE(column[1]) ^ multiply4(column[2]) ^ multiply3(column[3]);
|
|
3026
|
-
output[2] = multiply3(column[0]) ^ multiply2(column[1]) ^ multiplyE(column[2]) ^ multiply4(column[3]);
|
|
3027
|
-
output[3] = multiply4(column[0]) ^ multiply3(column[1]) ^ multiply2(column[2]) ^ multiplyE(column[3]);
|
|
3028
|
-
return output;
|
|
3029
|
-
}
|
|
3030
|
-
function multiply1(value) {
|
|
3031
|
-
if (value & 0x80) {
|
|
3032
|
-
return ((value << 1) ^ 0x1b) & 0xff;
|
|
3033
|
-
}
|
|
3034
|
-
return value << 1;
|
|
3035
|
-
}
|
|
3036
|
-
function multiply2(value) {
|
|
3037
|
-
return multiply1(value) ^ value;
|
|
3038
|
-
}
|
|
3039
|
-
function multiply3(value) {
|
|
3040
|
-
return multiply2(multiply1(value));
|
|
3041
|
-
}
|
|
3042
|
-
function multiply4(value) {
|
|
3043
|
-
return multiply3(multiply2(multiply1(value)));
|
|
3044
|
-
}
|
|
3045
|
-
function multiplyE(value) {
|
|
3046
|
-
return multiply4(value) ^ multiply3(value) ^ multiply2(value);
|
|
3047
|
-
}
|
|
3048
|
-
function md5(input) {
|
|
3049
|
-
return node_crypto.createHash('md5').update(input).digest('hex');
|
|
3050
|
-
}
|
|
3051
|
-
|
|
3052
|
-
const DEFAULT_PLATFORM_PARAMS = {
|
|
3053
|
-
os_type: 'web',
|
|
3054
|
-
app: 'heybox',
|
|
3055
|
-
x_client_type: 'web',
|
|
3056
|
-
x_os_type: 'Mac',
|
|
3057
|
-
x_app: 'heybox',
|
|
3058
|
-
x_client_version: '999.999.999',
|
|
3059
|
-
};
|
|
3060
|
-
const HEYBOX_WEB_REFERER = 'https://www.xiaoheihe.cn/';
|
|
3061
|
-
function resolveHeyboxId(session) {
|
|
3062
|
-
if (session.heyboxId.trim()) {
|
|
3063
|
-
return session.heyboxId.trim();
|
|
3064
|
-
}
|
|
3065
|
-
return session.cookieHeader
|
|
3066
|
-
.split(';')
|
|
3067
|
-
.map((part) => part.trim())
|
|
3068
|
-
.find((part) => part.startsWith('heybox_id='))
|
|
3069
|
-
?.slice('heybox_id='.length);
|
|
3070
|
-
}
|
|
3071
|
-
function createHeyboxAuthHeaders(session, options = {}) {
|
|
3072
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
3073
|
-
return {
|
|
3074
|
-
Cookie: session.cookieHeader,
|
|
3075
|
-
Referer: HEYBOX_WEB_REFERER,
|
|
3076
|
-
...(options.contentType ? { 'Content-Type': options.contentType } : {}),
|
|
3077
|
-
...(serviceTag ? { 'x-rylai-service-tag': serviceTag } : {}),
|
|
3078
|
-
};
|
|
3079
|
-
}
|
|
3080
|
-
function createHeyboxRequestContext(session$1, options = {}) {
|
|
3081
|
-
const heyboxId = resolveHeyboxId(session$1);
|
|
3082
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
3083
|
-
return {
|
|
3084
|
-
baseUrl: session.HEYBOX_API_BASE_URL,
|
|
3085
|
-
headers: createHeyboxAuthHeaders(session$1, options),
|
|
3086
|
-
platformParams: {
|
|
3087
|
-
...DEFAULT_PLATFORM_PARAMS,
|
|
3088
|
-
...options.platformParams,
|
|
3089
|
-
...(heyboxId ? { heybox_id: heyboxId } : {}),
|
|
3090
|
-
...(serviceTag ? { special_tag: serviceTag } : {}),
|
|
3091
|
-
},
|
|
3092
|
-
};
|
|
3093
|
-
}
|
|
3094
|
-
function createHeyboxOpenPlatformRequestContext(session, pathWithQuery, options = {}) {
|
|
3095
|
-
return createHeyboxRequestContext(session, {
|
|
3096
|
-
...options,
|
|
3097
|
-
pathWithQuery,
|
|
3098
|
-
platformParams: {
|
|
3099
|
-
x_app: 'heybox_website',
|
|
3100
|
-
...createHeyboxOpenPlatformSignParams(getApiPathname(pathWithQuery)),
|
|
3101
|
-
...options.platformParams,
|
|
3102
|
-
},
|
|
3103
|
-
});
|
|
3104
|
-
}
|
|
3105
|
-
function createHeyboxApiUrl(baseUrl, pathWithQuery, params) {
|
|
3106
|
-
const url = new URL(pathWithQuery, baseUrl);
|
|
3107
|
-
for (const [key, value] of Object.entries(params)) {
|
|
3108
|
-
if (value !== '') {
|
|
3109
|
-
url.searchParams.set(key, String(value));
|
|
3110
|
-
}
|
|
3111
|
-
}
|
|
3112
|
-
return url.toString();
|
|
3113
|
-
}
|
|
3114
|
-
function getApiPathname(pathWithQuery) {
|
|
3115
|
-
return new URL(pathWithQuery, session.HEYBOX_API_BASE_URL).pathname;
|
|
3116
|
-
}
|
|
3117
|
-
const ENVELOPE_BODY_PREVIEW_LENGTH = 1000;
|
|
3118
|
-
async function readHeyboxApiEnvelope(response, options) {
|
|
3119
|
-
const rawBody = await response.text();
|
|
3120
|
-
let envelope = null;
|
|
3121
|
-
let parseError = null;
|
|
3122
|
-
if (rawBody) {
|
|
3123
|
-
try {
|
|
3124
|
-
envelope = JSON.parse(rawBody);
|
|
3125
|
-
}
|
|
3126
|
-
catch (error) {
|
|
3127
|
-
parseError = error;
|
|
3128
|
-
}
|
|
3129
|
-
}
|
|
3130
|
-
const envelopeOk = envelope?.status === 'ok' && (!options.requireResult || envelope?.result !== undefined);
|
|
3131
|
-
if (response.ok && envelopeOk) {
|
|
3132
|
-
return envelope.result;
|
|
3133
|
-
}
|
|
3134
|
-
const { message, verboseMessage } = formatHeyboxEnvelopeError({
|
|
3135
|
-
response,
|
|
3136
|
-
envelope,
|
|
3137
|
-
parseError,
|
|
3138
|
-
rawBody,
|
|
3139
|
-
pathWithQuery: options.pathWithQuery,
|
|
3140
|
-
});
|
|
3141
|
-
throw new index.CliError(message, verboseMessage);
|
|
3142
|
-
}
|
|
3143
|
-
function formatHeyboxEnvelopeError(input) {
|
|
3144
|
-
const parts = [`Heybox API ${input.pathWithQuery} failed`, `HTTP ${input.response.status}`];
|
|
3145
|
-
if (input.envelope) {
|
|
3146
|
-
const msg = typeof input.envelope.msg === 'string' ? input.envelope.msg.trim() : '';
|
|
3147
|
-
const sbeUserMessage = readSbeUserMessage(input.envelope.result);
|
|
3148
|
-
parts.push(`msg=${msg || '(empty)'}`);
|
|
3149
|
-
if (typeof input.envelope.status === 'string') {
|
|
3150
|
-
parts.push(`envelope.status=${input.envelope.status}`);
|
|
3151
|
-
}
|
|
3152
|
-
const { status: _s, msg: _m, result: _r, ...extras } = input.envelope;
|
|
3153
|
-
if (Object.keys(extras).length > 0) {
|
|
3154
|
-
parts.push(`extras=${truncate(safeJsonStringify(extras), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
3155
|
-
}
|
|
3156
|
-
if (input.envelope.result !== undefined) {
|
|
3157
|
-
parts.push(`result=${truncate(safeJsonStringify(input.envelope.result), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
3158
|
-
}
|
|
3159
|
-
return {
|
|
3160
|
-
message: sbeUserMessage || msg || `Heybox API ${input.pathWithQuery} 请求失败`,
|
|
3161
|
-
verboseMessage: parts.join(' '),
|
|
3162
|
-
};
|
|
3163
|
-
}
|
|
3164
|
-
if (input.parseError) {
|
|
3165
|
-
const parseMsg = input.parseError instanceof Error ? input.parseError.message : String(input.parseError);
|
|
3166
|
-
parts.push(`parseError=${parseMsg}`);
|
|
3167
|
-
}
|
|
3168
|
-
parts.push(input.rawBody ? `body=${truncate(input.rawBody, ENVELOPE_BODY_PREVIEW_LENGTH)}` : 'body=(empty)');
|
|
3169
|
-
return {
|
|
3170
|
-
message: `Heybox API ${input.pathWithQuery} 请求失败`,
|
|
3171
|
-
verboseMessage: parts.join(' '),
|
|
3172
|
-
};
|
|
3173
|
-
}
|
|
3174
|
-
function readSbeUserMessage(result) {
|
|
3175
|
-
if (!result || typeof result !== 'object') {
|
|
3176
|
-
return '';
|
|
3177
|
-
}
|
|
3178
|
-
const sbe = result.sbe;
|
|
3179
|
-
if (!sbe || typeof sbe !== 'object') {
|
|
3180
|
-
return '';
|
|
3181
|
-
}
|
|
3182
|
-
const userMessage = sbe.user_message;
|
|
3183
|
-
return typeof userMessage === 'string' ? userMessage.trim() : '';
|
|
3184
|
-
}
|
|
3185
|
-
function truncate(value, max) {
|
|
3186
|
-
return value.length > max ? `${value.slice(0, max)}...(+${value.length - max} chars)` : value;
|
|
3187
|
-
}
|
|
3188
|
-
function safeJsonStringify(value) {
|
|
3189
|
-
try {
|
|
3190
|
-
return JSON.stringify(value);
|
|
3191
|
-
}
|
|
3192
|
-
catch {
|
|
3193
|
-
return String(value);
|
|
3194
|
-
}
|
|
3195
|
-
}
|
|
3196
|
-
|
|
3197
2936
|
async function getCDNUploadInfo(options, runtime = {}) {
|
|
3198
2937
|
const body = new URLSearchParams();
|
|
3199
2938
|
body.set('file_infos', JSON.stringify(options.fileInfos));
|
|
@@ -3215,17 +2954,17 @@ async function postCDNUploadCallback(options, runtime = {}) {
|
|
|
3215
2954
|
const query = options.isFinished ? '?is_finished=true' : '';
|
|
3216
2955
|
return postHeyboxApi(`/bbs/app/api/qcloud/cos/upload/callback/v2${query}`, body, options.session, runtime);
|
|
3217
2956
|
}
|
|
3218
|
-
async function postHeyboxApi(pathWithQuery, body, session, runtime) {
|
|
2957
|
+
async function postHeyboxApi(pathWithQuery, body, session$1, runtime) {
|
|
3219
2958
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3220
|
-
const context = createHeyboxOpenPlatformRequestContext(session, pathWithQuery, {
|
|
2959
|
+
const context = session.createHeyboxOpenPlatformRequestContext(session$1, pathWithQuery, {
|
|
3221
2960
|
contentType: 'application/x-www-form-urlencoded',
|
|
3222
2961
|
});
|
|
3223
|
-
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
2962
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
3224
2963
|
method: 'POST',
|
|
3225
2964
|
headers: context.headers,
|
|
3226
2965
|
body: body.toString(),
|
|
3227
2966
|
});
|
|
3228
|
-
const result = await readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
2967
|
+
const result = await session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
3229
2968
|
return result;
|
|
3230
2969
|
}
|
|
3231
2970
|
|
|
@@ -3328,7 +3067,7 @@ async function createDefaultCosClient(uploadToken) {
|
|
|
3328
3067
|
};
|
|
3329
3068
|
}
|
|
3330
3069
|
async function loadCosConstructor() {
|
|
3331
|
-
const cosModule = await Promise.resolve().then(function () { return require('./index-
|
|
3070
|
+
const cosModule = await Promise.resolve().then(function () { return require('./index-CLne_LW7.cjs'); }).then(function (n) { return n.index; });
|
|
3332
3071
|
return cosModule.default;
|
|
3333
3072
|
}
|
|
3334
3073
|
function formatSize(bytes) {
|
|
@@ -3371,14 +3110,14 @@ function isRecord(value) {
|
|
|
3371
3110
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
3372
3111
|
}
|
|
3373
3112
|
|
|
3374
|
-
async function precheckUserMiniprogramVersion(options, runtime = {}) {
|
|
3113
|
+
async function precheckUserMiniprogramVersion$1(options, runtime = {}) {
|
|
3375
3114
|
return postUserMiniprogramVersionForm(PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH, options, {
|
|
3376
3115
|
version: options.version,
|
|
3377
3116
|
release_note: options.releaseNote,
|
|
3378
3117
|
auto_publish: String(options.autoPublish),
|
|
3379
3118
|
}, runtime);
|
|
3380
3119
|
}
|
|
3381
|
-
async function submitUserMiniprogramAudit(options, runtime = {}) {
|
|
3120
|
+
async function submitUserMiniprogramAudit$1(options, runtime = {}) {
|
|
3382
3121
|
return postUserMiniprogramVersionForm(SUBMIT_USER_MINIPROGRAM_AUDIT_API_PATH, options, {
|
|
3383
3122
|
manifest: JSON.stringify(options.manifest),
|
|
3384
3123
|
release_note: options.releaseNote,
|
|
@@ -3387,7 +3126,7 @@ async function submitUserMiniprogramAudit(options, runtime = {}) {
|
|
|
3387
3126
|
}
|
|
3388
3127
|
async function postUserMiniprogramVersionForm(path, options, fields, runtime) {
|
|
3389
3128
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3390
|
-
const context = createHeyboxOpenPlatformRequestContext(options.session, path, {
|
|
3129
|
+
const context = session.createHeyboxOpenPlatformRequestContext(options.session, path, {
|
|
3391
3130
|
contentType: 'application/x-www-form-urlencoded',
|
|
3392
3131
|
});
|
|
3393
3132
|
const body = new URLSearchParams();
|
|
@@ -3395,12 +3134,12 @@ async function postUserMiniprogramVersionForm(path, options, fields, runtime) {
|
|
|
3395
3134
|
for (const [key, value] of Object.entries(fields)) {
|
|
3396
3135
|
body.set(key, value);
|
|
3397
3136
|
}
|
|
3398
|
-
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, path, context.platformParams), {
|
|
3137
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, path, context.platformParams), {
|
|
3399
3138
|
method: 'POST',
|
|
3400
3139
|
headers: context.headers,
|
|
3401
3140
|
body: body.toString(),
|
|
3402
3141
|
});
|
|
3403
|
-
const result = await readHeyboxApiEnvelope(response, {
|
|
3142
|
+
const result = await session.readHeyboxApiEnvelope(response, {
|
|
3404
3143
|
pathWithQuery: path,
|
|
3405
3144
|
});
|
|
3406
3145
|
return result ?? {};
|
|
@@ -3460,7 +3199,10 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
3460
3199
|
}, runtime, apiBaseUrl, projectRoot, logger);
|
|
3461
3200
|
const pm = detectPackageManager(projectRoot);
|
|
3462
3201
|
logger.info(`开始构建: ${pm} run build`);
|
|
3463
|
-
await runBuildScript(pm, projectRoot, runtime.spawn ?? childProcess.spawn
|
|
3202
|
+
await runBuildScript(pm, projectRoot, runtime.spawn ?? childProcess.spawn, {
|
|
3203
|
+
outputMode: options.buildOutputMode ?? 'inherit',
|
|
3204
|
+
stderr: runtime.stderr,
|
|
3205
|
+
});
|
|
3464
3206
|
logger.success('构建完成');
|
|
3465
3207
|
}
|
|
3466
3208
|
else {
|
|
@@ -3502,15 +3244,36 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
3502
3244
|
throw translateHeyboxDeployError(error, { projectRoot, stage: 'upload', version });
|
|
3503
3245
|
}
|
|
3504
3246
|
try {
|
|
3505
|
-
submitAuditResult = await logger.task('正在提交审核', () => (runtime.submitUserMiniprogramAudit ?? submitUserMiniprogramAudit)({ session: session$1, miniProgramId, manifest, releaseNote, autoPublish }, { baseUrl: apiBaseUrl, fetchImpl: runtime.fetchImpl }), { successText: '审核提交完成' });
|
|
3247
|
+
submitAuditResult = await logger.task('正在提交审核', () => (runtime.submitUserMiniprogramAudit ?? submitUserMiniprogramAudit$1)({ session: session$1, miniProgramId, manifest, releaseNote, autoPublish }, { baseUrl: apiBaseUrl, fetchImpl: runtime.fetchImpl }), { successText: '审核提交完成' });
|
|
3506
3248
|
}
|
|
3507
3249
|
catch (error) {
|
|
3508
3250
|
throw translateHeyboxDeployError(error, { projectRoot, stage: 'submitAudit', version });
|
|
3509
3251
|
}
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3252
|
+
printDeploySuccess({ autoPublish, logger, miniProgramId, mode: options.successOutputMode ?? 'legacy', previewUrl: submitAuditResult.preview_url, version });
|
|
3253
|
+
return {
|
|
3254
|
+
autoPublish,
|
|
3255
|
+
changed: true,
|
|
3256
|
+
miniProgramId,
|
|
3257
|
+
...(submitAuditResult.preview_url ? { previewUrl: submitAuditResult.preview_url } : {}),
|
|
3258
|
+
version,
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
function printDeploySuccess(options) {
|
|
3262
|
+
options.logger.success(`提交审核成功:${options.miniProgramId} ${options.version}`);
|
|
3263
|
+
if (options.mode === 'remote') {
|
|
3264
|
+
options.logger.info(`发布策略:${options.autoPublish ? '审核通过后自动发布' : '审核通过后需手动发布'}`);
|
|
3265
|
+
if (options.previewUrl) {
|
|
3266
|
+
options.logger.info(`Preview URL: ${options.previewUrl}`);
|
|
3267
|
+
options.logger.info('允许他人预览:hb-sdk remote allowlist add <heybox_id>');
|
|
3268
|
+
}
|
|
3269
|
+
options.logger.info(options.autoPublish
|
|
3270
|
+
? '下一步:hb-sdk remote versions'
|
|
3271
|
+
: `下一步:hb-sdk remote versions;审核通过后运行 hb-sdk remote release ${options.version}`);
|
|
3272
|
+
return;
|
|
3273
|
+
}
|
|
3274
|
+
options.logger.info(`发布策略:${options.autoPublish ? '审核通过后自动发布' : '审核通过后需在开放平台手动发布'}`);
|
|
3275
|
+
if (options.previewUrl) {
|
|
3276
|
+
options.logger.info(`Preview URL: ${options.previewUrl}`);
|
|
3514
3277
|
}
|
|
3515
3278
|
}
|
|
3516
3279
|
function findProjectRoot(startDir) {
|
|
@@ -3574,7 +3337,7 @@ async function maybePromptReleaseNote(runtime) {
|
|
|
3574
3337
|
}
|
|
3575
3338
|
const isTTY = runtime.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
3576
3339
|
if (!isTTY) {
|
|
3577
|
-
throw new Error('非交互环境执行 hb-sdk deploy 必须传 --release-note <text>');
|
|
3340
|
+
throw new Error('非交互环境执行 hb-sdk remote deploy 必须传 --release-note <text>');
|
|
3578
3341
|
}
|
|
3579
3342
|
const input = runtime.stdin ?? process.stdin;
|
|
3580
3343
|
const output = runtime.stdout ?? process.stdout;
|
|
@@ -3588,7 +3351,7 @@ async function maybePromptReleaseNote(runtime) {
|
|
|
3588
3351
|
}
|
|
3589
3352
|
async function runVersionPrecheck(options, runtime, apiBaseUrl, projectRoot, logger) {
|
|
3590
3353
|
try {
|
|
3591
|
-
await logger.task(`正在预检版本 ${options.version}`, () => (runtime.precheckUserMiniprogramVersion ?? precheckUserMiniprogramVersion)(options, {
|
|
3354
|
+
await logger.task(`正在预检版本 ${options.version}`, () => (runtime.precheckUserMiniprogramVersion ?? precheckUserMiniprogramVersion$1)(options, {
|
|
3592
3355
|
baseUrl: apiBaseUrl,
|
|
3593
3356
|
fetchImpl: runtime.fetchImpl,
|
|
3594
3357
|
}), { successText: `版本 ${options.version} 预检通过` });
|
|
@@ -3605,12 +3368,18 @@ function detectPackageManager(projectRoot) {
|
|
|
3605
3368
|
}
|
|
3606
3369
|
return 'npm';
|
|
3607
3370
|
}
|
|
3608
|
-
async function runBuildScript(pm, cwd, spawnImpl) {
|
|
3371
|
+
async function runBuildScript(pm, cwd, spawnImpl, options) {
|
|
3609
3372
|
await new Promise((resolve, reject) => {
|
|
3373
|
+
const pipeStdoutToStderr = options.outputMode === 'stderr';
|
|
3610
3374
|
const child = spawnImpl(pm, ['run', 'build'], {
|
|
3611
3375
|
cwd,
|
|
3612
|
-
stdio: 'inherit',
|
|
3376
|
+
stdio: pipeStdoutToStderr ? ['inherit', 'pipe', 'inherit'] : 'inherit',
|
|
3613
3377
|
});
|
|
3378
|
+
if (pipeStdoutToStderr) {
|
|
3379
|
+
child.stdout?.on('data', (chunk) => {
|
|
3380
|
+
(options.stderr ?? process.stderr).write(chunk);
|
|
3381
|
+
});
|
|
3382
|
+
}
|
|
3614
3383
|
child.on('error', reject);
|
|
3615
3384
|
child.on('exit', (code) => {
|
|
3616
3385
|
if (code === 0) {
|
|
@@ -3719,12 +3488,947 @@ function suggestNextPatchVersion(version) {
|
|
|
3719
3488
|
return `${matched[1]}.${matched[2]}.${Number(matched[3]) + 1}`;
|
|
3720
3489
|
}
|
|
3721
3490
|
|
|
3722
|
-
|
|
3491
|
+
function createRemoteApiClient(options) {
|
|
3492
|
+
return {
|
|
3493
|
+
listDeveloperEntities: () => listDeveloperEntities(options),
|
|
3494
|
+
switchDeveloperEntity: (requestOptions) => switchDeveloperEntity(requestOptions, options),
|
|
3495
|
+
getDeveloperAccessStatus: () => getDeveloperAccessStatus(options),
|
|
3496
|
+
listUserMiniprograms: (requestOptions = {}) => listUserMiniprograms(requestOptions, options),
|
|
3497
|
+
createUserMiniprogram: (requestOptions) => createUserMiniprogram(requestOptions, options),
|
|
3498
|
+
updateUserMiniprogram: (requestOptions) => updateUserMiniprogram(requestOptions, options),
|
|
3499
|
+
getUserMiniprogramDetail: (requestOptions) => getUserMiniprogramDetail(requestOptions, options),
|
|
3500
|
+
getPreviewAllowlist: (requestOptions) => getPreviewAllowlist(requestOptions, options),
|
|
3501
|
+
updatePreviewAllowlist: (requestOptions) => updatePreviewAllowlist(requestOptions, options),
|
|
3502
|
+
precheckUserMiniprogramVersion: (requestOptions) => precheckUserMiniprogramVersion(requestOptions, options),
|
|
3503
|
+
submitUserMiniprogramAudit: (requestOptions) => submitUserMiniprogramAudit(requestOptions, options),
|
|
3504
|
+
getVersionPreviewInfo: (requestOptions) => getVersionPreviewInfo(requestOptions, options),
|
|
3505
|
+
withdrawUserMiniprogramVersion: (requestOptions) => withdrawUserMiniprogramVersion(requestOptions, options),
|
|
3506
|
+
releaseUserMiniprogramVersion: (requestOptions) => releaseUserMiniprogramVersion(requestOptions, options),
|
|
3507
|
+
takeDownUserMiniprogram: (requestOptions) => takeDownUserMiniprogram(requestOptions, options),
|
|
3508
|
+
reopenUserMiniprogram: (requestOptions) => reopenUserMiniprogram(requestOptions, options),
|
|
3509
|
+
listUserMiniprogramVersions: (requestOptions) => listUserMiniprogramVersions(requestOptions, options),
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3512
|
+
async function listDeveloperEntities(runtime) {
|
|
3513
|
+
return remoteGet(DEVELOPER_ENTITY_LIST_API_PATH, {}, runtime);
|
|
3514
|
+
}
|
|
3515
|
+
async function switchDeveloperEntity(options, runtime) {
|
|
3516
|
+
return (await remotePostForm(DEVELOPER_ENTITY_SWITCH_API_PATH, options, runtime, { requireResult: false })) ?? {};
|
|
3517
|
+
}
|
|
3518
|
+
async function getDeveloperAccessStatus(runtime) {
|
|
3519
|
+
return remoteGet(USER_MINIPROGRAM_ACCESS_STATUS_API_PATH, {}, runtime);
|
|
3520
|
+
}
|
|
3521
|
+
async function listUserMiniprograms(options, runtime) {
|
|
3522
|
+
return remoteGet(LIST_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3523
|
+
}
|
|
3524
|
+
async function createUserMiniprogram(options, runtime) {
|
|
3525
|
+
return remotePostForm(CREATE_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3526
|
+
}
|
|
3527
|
+
async function updateUserMiniprogram(options, runtime) {
|
|
3528
|
+
return remotePostForm(UPDATE_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3529
|
+
}
|
|
3530
|
+
async function getUserMiniprogramDetail(options, runtime) {
|
|
3531
|
+
return remoteGet(DETAIL_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3532
|
+
}
|
|
3533
|
+
async function getPreviewAllowlist(options, runtime) {
|
|
3534
|
+
return remoteGet(USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
|
|
3535
|
+
}
|
|
3536
|
+
async function updatePreviewAllowlist(options, runtime) {
|
|
3537
|
+
return remotePostForm(UPDATE_USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
|
|
3538
|
+
}
|
|
3539
|
+
async function precheckUserMiniprogramVersion(options, runtime) {
|
|
3540
|
+
return remotePostForm(PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
|
|
3541
|
+
}
|
|
3542
|
+
async function submitUserMiniprogramAudit(options, runtime) {
|
|
3543
|
+
return remotePostForm(SUBMIT_USER_MINIPROGRAM_AUDIT_API_PATH, {
|
|
3544
|
+
...options,
|
|
3545
|
+
manifest: typeof options.manifest === 'string' ? options.manifest : JSON.stringify(options.manifest),
|
|
3546
|
+
}, runtime);
|
|
3547
|
+
}
|
|
3548
|
+
async function getVersionPreviewInfo(options, runtime) {
|
|
3549
|
+
return remoteGet(USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH, options, runtime);
|
|
3550
|
+
}
|
|
3551
|
+
async function withdrawUserMiniprogramVersion(options, runtime) {
|
|
3552
|
+
return remotePostForm(WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
|
|
3553
|
+
}
|
|
3554
|
+
async function releaseUserMiniprogramVersion(options, runtime) {
|
|
3555
|
+
return remotePostForm(RELEASE_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
|
|
3556
|
+
}
|
|
3557
|
+
async function takeDownUserMiniprogram(options, runtime) {
|
|
3558
|
+
return remotePostForm(TAKE_DOWN_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3559
|
+
}
|
|
3560
|
+
async function reopenUserMiniprogram(options, runtime) {
|
|
3561
|
+
return remotePostForm(REOPEN_USER_MINIPROGRAM_API_PATH, options, runtime);
|
|
3562
|
+
}
|
|
3563
|
+
async function listUserMiniprogramVersions(options, runtime) {
|
|
3564
|
+
return remoteGet(LIST_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
|
|
3565
|
+
}
|
|
3566
|
+
async function remoteGet(path, query, runtime) {
|
|
3567
|
+
const pathWithQuery = createPathWithQuery(path, query);
|
|
3568
|
+
const context = session.createHeyboxOpenPlatformRequestContext(runtime.session, pathWithQuery);
|
|
3569
|
+
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3570
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
3571
|
+
method: 'GET',
|
|
3572
|
+
headers: context.headers,
|
|
3573
|
+
});
|
|
3574
|
+
return readRequiredResult(response, pathWithQuery);
|
|
3575
|
+
}
|
|
3576
|
+
async function remotePostForm(path, fields, runtime, options = {}) {
|
|
3577
|
+
const context = session.createHeyboxOpenPlatformRequestContext(runtime.session, path, {
|
|
3578
|
+
contentType: 'application/x-www-form-urlencoded',
|
|
3579
|
+
});
|
|
3580
|
+
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3581
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, path, context.platformParams), {
|
|
3582
|
+
method: 'POST',
|
|
3583
|
+
headers: context.headers,
|
|
3584
|
+
body: createFormBody(fields),
|
|
3585
|
+
});
|
|
3586
|
+
if (options.requireResult === false) {
|
|
3587
|
+
return readOptionalResult(response, path);
|
|
3588
|
+
}
|
|
3589
|
+
return readRequiredResult(response, path);
|
|
3590
|
+
}
|
|
3591
|
+
async function readRequiredResult(response, pathWithQuery) {
|
|
3592
|
+
const result = await session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
3593
|
+
return result;
|
|
3594
|
+
}
|
|
3595
|
+
async function readOptionalResult(response, pathWithQuery) {
|
|
3596
|
+
return session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: false });
|
|
3597
|
+
}
|
|
3598
|
+
function createPathWithQuery(path, query) {
|
|
3599
|
+
const params = new URLSearchParams();
|
|
3600
|
+
for (const [key, value] of Object.entries(query)) {
|
|
3601
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
3602
|
+
params.set(key, String(value));
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
const queryString = params.toString();
|
|
3606
|
+
return queryString ? `${path}?${queryString}` : path;
|
|
3607
|
+
}
|
|
3608
|
+
function createFormBody(fields) {
|
|
3609
|
+
const body = new URLSearchParams();
|
|
3610
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
3611
|
+
if (value === undefined || value === null) {
|
|
3612
|
+
continue;
|
|
3613
|
+
}
|
|
3614
|
+
if (Array.isArray(value)) {
|
|
3615
|
+
body.set(key, value.join(','));
|
|
3616
|
+
continue;
|
|
3617
|
+
}
|
|
3618
|
+
if (typeof value === 'object') {
|
|
3619
|
+
body.set(key, JSON.stringify(value));
|
|
3620
|
+
continue;
|
|
3621
|
+
}
|
|
3622
|
+
body.set(key, String(value));
|
|
3623
|
+
}
|
|
3624
|
+
return body.toString();
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
class MiniProgramProjectBindingError extends Error {
|
|
3628
|
+
code;
|
|
3629
|
+
constructor(message, code) {
|
|
3630
|
+
super(message);
|
|
3631
|
+
this.code = code;
|
|
3632
|
+
this.name = 'MiniProgramProjectBindingError';
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
function findMiniProgramProjectRoot(startDir) {
|
|
3636
|
+
let current = path.resolve(startDir);
|
|
3637
|
+
while (true) {
|
|
3638
|
+
if (fs.existsSync(path.join(current, 'package.json'))) {
|
|
3639
|
+
return current;
|
|
3640
|
+
}
|
|
3641
|
+
const parent = path.dirname(current);
|
|
3642
|
+
if (parent === current) {
|
|
3643
|
+
throw new MiniProgramProjectBindingError('当前目录或父目录未找到 package.json', 'PACKAGE_JSON_NOT_FOUND');
|
|
3644
|
+
}
|
|
3645
|
+
current = parent;
|
|
3646
|
+
}
|
|
3647
|
+
}
|
|
3648
|
+
async function readMiniProgramProjectPackage(startDir) {
|
|
3649
|
+
const projectRoot = findMiniProgramProjectRoot(startDir);
|
|
3650
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
3651
|
+
const raw = await fs$1.readFile(packageJsonPath, 'utf8');
|
|
3652
|
+
let packageJson;
|
|
3653
|
+
try {
|
|
3654
|
+
packageJson = JSON.parse(raw);
|
|
3655
|
+
}
|
|
3656
|
+
catch (error) {
|
|
3657
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3658
|
+
throw new MiniProgramProjectBindingError(`package.json 不是合法 JSON:${packageJsonPath}\n${message}`, 'PACKAGE_JSON_INVALID');
|
|
3659
|
+
}
|
|
3660
|
+
return {
|
|
3661
|
+
projectRoot,
|
|
3662
|
+
packageJsonPath,
|
|
3663
|
+
packageJson,
|
|
3664
|
+
raw,
|
|
3665
|
+
indent: detectJsonIndent(raw),
|
|
3666
|
+
trailingNewline: raw.endsWith('\r\n') ? '\r\n' : raw.endsWith('\n') ? '\n' : '',
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
function readBoundMiniProgramIdFromPackageJson(packageJson) {
|
|
3670
|
+
const value = packageJson.heybox?.miniProgramId;
|
|
3671
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
3672
|
+
}
|
|
3673
|
+
async function writeBoundMiniProgramId(startDir, miniProgramId, options = {}) {
|
|
3674
|
+
const context = await readMiniProgramProjectPackage(startDir);
|
|
3675
|
+
const normalizedMiniProgramId = String(miniProgramId).trim();
|
|
3676
|
+
if (!normalizedMiniProgramId) {
|
|
3677
|
+
throw new MiniProgramProjectBindingError('miniProgramId 不能为空', 'PACKAGE_JSON_INVALID');
|
|
3678
|
+
}
|
|
3679
|
+
const currentMiniProgramId = readBoundMiniProgramIdFromPackageJson(context.packageJson);
|
|
3680
|
+
if (currentMiniProgramId && currentMiniProgramId !== normalizedMiniProgramId && !options.force) {
|
|
3681
|
+
throw new MiniProgramProjectBindingError(`当前项目已绑定小程序 ${currentMiniProgramId}。如需覆盖本地绑定,请使用 --force。`, 'MINI_PROGRAM_BINDING_EXISTS');
|
|
3682
|
+
}
|
|
3683
|
+
if (currentMiniProgramId === normalizedMiniProgramId) {
|
|
3684
|
+
return {
|
|
3685
|
+
...context,
|
|
3686
|
+
changed: false,
|
|
3687
|
+
miniProgramId: normalizedMiniProgramId,
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3690
|
+
if (context.packageJson.heybox !== undefined && !isPlainObject(context.packageJson.heybox)) {
|
|
3691
|
+
throw new MiniProgramProjectBindingError('package.json heybox 字段必须是对象,不能写入 miniProgramId', 'PACKAGE_JSON_HEYBOX_INVALID');
|
|
3692
|
+
}
|
|
3693
|
+
context.packageJson.heybox = {
|
|
3694
|
+
...(context.packageJson.heybox ?? {}),
|
|
3695
|
+
miniProgramId: normalizedMiniProgramId,
|
|
3696
|
+
};
|
|
3697
|
+
await fs$1.writeFile(context.packageJsonPath, `${JSON.stringify(context.packageJson, null, context.indent)}${context.trailingNewline || '\n'}`, 'utf8');
|
|
3698
|
+
return {
|
|
3699
|
+
...context,
|
|
3700
|
+
changed: true,
|
|
3701
|
+
miniProgramId: normalizedMiniProgramId,
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
function detectJsonIndent(raw) {
|
|
3705
|
+
const match = raw.match(/\n(\s+)"[^"]+":/);
|
|
3706
|
+
return match?.[1] ?? 2;
|
|
3707
|
+
}
|
|
3708
|
+
function isPlainObject(value) {
|
|
3709
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
async function resolveRemoteEnvironment(options = {}, runtime = {}) {
|
|
3713
|
+
const env = options.env ?? process.env;
|
|
3714
|
+
const apiBaseUrl = session.resolveHeyboxApiBaseUrl({ ...options, env });
|
|
3715
|
+
const loginBaseUrl = session.resolveHeyboxLoginBaseUrl({ ...options, env });
|
|
3716
|
+
const session$1 = options.session ?? (await (runtime.requireAuthSession ?? session.requireHeyboxAuthSession)({ loginBaseUrl }));
|
|
3717
|
+
return {
|
|
3718
|
+
apiBaseUrl,
|
|
3719
|
+
loginBaseUrl,
|
|
3720
|
+
allowUnsafeApiBaseUrl: options.allowUnsafeApiBaseUrl === true || isTruthyEnvFlag(env.HB_SDK_ALLOW_UNSAFE_API_BASE_URL),
|
|
3721
|
+
env,
|
|
3722
|
+
fetchImpl: runtime.fetchImpl ?? options.fetchImpl ?? fetch,
|
|
3723
|
+
session: session$1,
|
|
3724
|
+
};
|
|
3725
|
+
}
|
|
3726
|
+
function createRemoteApiClientForEnvironment(environment) {
|
|
3727
|
+
return createRemoteApiClient({
|
|
3728
|
+
baseUrl: environment.apiBaseUrl,
|
|
3729
|
+
fetchImpl: environment.fetchImpl,
|
|
3730
|
+
session: environment.session,
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
function isTruthyEnvFlag(value) {
|
|
3734
|
+
return ['1', 'true', 'yes', 'on'].includes(String(value ?? '')
|
|
3735
|
+
.trim()
|
|
3736
|
+
.toLowerCase());
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
async function runRemoteCommand(options, runtime = {}) {
|
|
3740
|
+
if (options.command === 'deploy') {
|
|
3741
|
+
return runRemoteDeployCommand(options, runtime);
|
|
3742
|
+
}
|
|
3743
|
+
const context = await createRemoteCommandContext(options, runtime);
|
|
3744
|
+
switch (options.command) {
|
|
3745
|
+
case 'access':
|
|
3746
|
+
return remoteAccess(options, context, runtime);
|
|
3747
|
+
case 'entity:list':
|
|
3748
|
+
return remoteEntityList(options, context, runtime);
|
|
3749
|
+
case 'entity:current':
|
|
3750
|
+
return remoteEntityCurrent(options, context, runtime);
|
|
3751
|
+
case 'entity:switch':
|
|
3752
|
+
return remoteEntitySwitch(options, context, runtime);
|
|
3753
|
+
case 'list':
|
|
3754
|
+
return remoteList(options, context, runtime);
|
|
3755
|
+
case 'create':
|
|
3756
|
+
return remoteCreate(options, context, runtime);
|
|
3757
|
+
case 'bind':
|
|
3758
|
+
return remoteBind(options, context, runtime);
|
|
3759
|
+
case 'info':
|
|
3760
|
+
return remoteInfo(options, context, runtime);
|
|
3761
|
+
case 'update':
|
|
3762
|
+
return remoteUpdate(options, context, runtime);
|
|
3763
|
+
case 'allowlist:list':
|
|
3764
|
+
return remoteAllowlistList(options, context, runtime);
|
|
3765
|
+
case 'allowlist:add':
|
|
3766
|
+
case 'allowlist:remove':
|
|
3767
|
+
case 'allowlist:set':
|
|
3768
|
+
return remoteAllowlistWrite(options, context, runtime);
|
|
3769
|
+
case 'versions':
|
|
3770
|
+
return remoteVersions(options, context, runtime);
|
|
3771
|
+
case 'preview':
|
|
3772
|
+
return remotePreview(options, context, runtime);
|
|
3773
|
+
case 'release':
|
|
3774
|
+
case 'withdraw':
|
|
3775
|
+
case 'take-down':
|
|
3776
|
+
case 'reopen':
|
|
3777
|
+
return remoteDangerousWrite(options, context, runtime);
|
|
3778
|
+
default:
|
|
3779
|
+
throw new Error(`不支持的 remote 命令:${String(options.command)}`);
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
async function runRemoteDeployCommand(options, runtime) {
|
|
3783
|
+
const logger = resolveRemoteLogger(options, runtime);
|
|
3784
|
+
const context = await createRemoteCommandContext(options, runtime);
|
|
3785
|
+
const miniProgramId = requireBinding(context);
|
|
3786
|
+
await assertBoundMiniProgramEntityMatchesCurrent(context, miniProgramId);
|
|
3787
|
+
const deployRuntime = {
|
|
3788
|
+
cwd: runtime.cwd,
|
|
3789
|
+
fetchImpl: runtime.fetchImpl,
|
|
3790
|
+
isTTY: runtime.isTTY,
|
|
3791
|
+
logger: options.json ? createJsonSafeLogger(runtime) : logger,
|
|
3792
|
+
requireAuthSession: runtime.requireAuthSession,
|
|
3793
|
+
stdin: runtime.stdin,
|
|
3794
|
+
stdout: runtime.stdout,
|
|
3795
|
+
};
|
|
3796
|
+
const deployOptions = {
|
|
3797
|
+
allowUnsafeApiBaseUrl: options.allowUnsafeApiBaseUrl,
|
|
3798
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
3799
|
+
autoPublish: options.autoPublish,
|
|
3800
|
+
env: options.env,
|
|
3801
|
+
loginBaseUrl: options.loginBaseUrl,
|
|
3802
|
+
releaseNote: options.releaseNote,
|
|
3803
|
+
skipBuild: options.skipBuild,
|
|
3804
|
+
buildOutputMode: options.json ? 'stderr' : 'inherit',
|
|
3805
|
+
successOutputMode: 'remote',
|
|
3806
|
+
};
|
|
3807
|
+
const result = await (runtime.runDeployCommand ?? runDeployCommand)(deployOptions, deployRuntime);
|
|
3808
|
+
const output = result ?? { changed: true };
|
|
3809
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3810
|
+
}
|
|
3811
|
+
async function createRemoteCommandContext(options, runtime) {
|
|
3812
|
+
const logger = resolveRemoteLogger(options, runtime);
|
|
3813
|
+
const environment = await resolveRemoteEnvironment({
|
|
3814
|
+
allowUnsafeApiBaseUrl: options.allowUnsafeApiBaseUrl,
|
|
3815
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
3816
|
+
env: options.env,
|
|
3817
|
+
fetchImpl: runtime.fetchImpl,
|
|
3818
|
+
loginBaseUrl: options.loginBaseUrl,
|
|
3819
|
+
}, {
|
|
3820
|
+
fetchImpl: runtime.fetchImpl,
|
|
3821
|
+
requireAuthSession: runtime.requireAuthSession,
|
|
3822
|
+
});
|
|
3823
|
+
const packageJson = await readMiniProgramProjectPackage(runtime.cwd ?? process.cwd());
|
|
3824
|
+
const binding = readBoundMiniProgramIdFromPackageJson(packageJson.packageJson);
|
|
3825
|
+
const api = {
|
|
3826
|
+
...adaptRemoteApiClient(createRemoteApiClientForEnvironment(environment)),
|
|
3827
|
+
...runtime.api,
|
|
3828
|
+
};
|
|
3829
|
+
logger.debug(`Heybox API: ${environment.apiBaseUrl}`);
|
|
3830
|
+
return {
|
|
3831
|
+
api,
|
|
3832
|
+
apiBaseUrl: environment.apiBaseUrl,
|
|
3833
|
+
binding,
|
|
3834
|
+
logger,
|
|
3835
|
+
loginBaseUrl: environment.loginBaseUrl,
|
|
3836
|
+
packageJson,
|
|
3837
|
+
session: environment.session,
|
|
3838
|
+
};
|
|
3839
|
+
}
|
|
3840
|
+
function adaptRemoteApiClient(api) {
|
|
3841
|
+
return {
|
|
3842
|
+
accessStatus: () => api.getDeveloperAccessStatus(),
|
|
3843
|
+
listMiniPrograms: ({ keyword, status }) => api.listUserMiniprograms({ keyword, status, offset: 0, limit: 200 }),
|
|
3844
|
+
createMiniProgram: ({ name, previewImageUrl }) => api.createUserMiniprogram({ name, ...(previewImageUrl ? { preview_image_url: previewImageUrl } : {}) }),
|
|
3845
|
+
updateMiniProgram: ({ miniProgramId, name, previewImageUrl }) => api.updateUserMiniprogram({ mini_program_id: miniProgramId, name, preview_image_url: previewImageUrl }),
|
|
3846
|
+
getMiniProgramDetail: (miniProgramId) => api.getUserMiniprogramDetail({ mini_program_id: miniProgramId }),
|
|
3847
|
+
getAllowlist: (miniProgramId) => api.getPreviewAllowlist({ mini_program_id: miniProgramId }),
|
|
3848
|
+
updateAllowlist: ({ miniProgramId, heyboxIds }) => api.updatePreviewAllowlist({ mini_program_id: miniProgramId, heybox_ids: heyboxIds }),
|
|
3849
|
+
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 }),
|
|
3851
|
+
listDeveloperEntities: () => api.listDeveloperEntities(),
|
|
3852
|
+
switchDeveloperEntity: ({ entityId }) => api.switchDeveloperEntity({ entity_id: entityId }),
|
|
3853
|
+
releaseVersion: ({ miniProgramId, version }) => api.releaseUserMiniprogramVersion({ mini_program_id: miniProgramId, version }),
|
|
3854
|
+
withdrawVersion: ({ miniProgramId, reason, version }) => api.withdrawUserMiniprogramVersion({ mini_program_id: miniProgramId, version, reason }),
|
|
3855
|
+
takeDown: (miniProgramId) => api.takeDownUserMiniprogram({ mini_program_id: miniProgramId }),
|
|
3856
|
+
reopen: (miniProgramId) => api.reopenUserMiniprogram({ mini_program_id: miniProgramId }),
|
|
3857
|
+
};
|
|
3858
|
+
}
|
|
3859
|
+
async function remoteAccess(options, context, runtime) {
|
|
3860
|
+
const result = await context.api.accessStatus();
|
|
3861
|
+
const output = { changed: false, access: toCamelCaseDeep(result) };
|
|
3862
|
+
if (!options.json) {
|
|
3863
|
+
context.logger.info(`Access status: ${String(result.status ?? 'unknown')}`);
|
|
3864
|
+
if (result.developer_name) {
|
|
3865
|
+
context.logger.info(`Developer: ${String(result.developer_name)}`);
|
|
3866
|
+
}
|
|
3867
|
+
if (result.disabled_reason) {
|
|
3868
|
+
context.logger.warn(`Disabled reason: ${String(result.disabled_reason)}`);
|
|
3869
|
+
}
|
|
3870
|
+
}
|
|
3871
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3872
|
+
}
|
|
3873
|
+
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) };
|
|
3877
|
+
if (!options.json) {
|
|
3878
|
+
if (items.length === 0) {
|
|
3879
|
+
context.logger.info('当前账号未绑定开发者主体');
|
|
3880
|
+
}
|
|
3881
|
+
else {
|
|
3882
|
+
printDeveloperEntities(context.logger, items);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3886
|
+
}
|
|
3887
|
+
async function remoteEntityCurrent(options, context, runtime) {
|
|
3888
|
+
const current = await requireCurrentDeveloperEntity(context);
|
|
3889
|
+
const access = await context.api.accessStatus();
|
|
3890
|
+
const output = { changed: false, current: toCamelCaseDeep(current), access: toCamelCaseDeep(access) };
|
|
3891
|
+
if (!options.json) {
|
|
3892
|
+
printDeveloperEntity(context.logger, current, '* ');
|
|
3893
|
+
context.logger.info(`Access status: ${String(access.status ?? 'unknown')}`);
|
|
3894
|
+
if (access.disabled_reason) {
|
|
3895
|
+
context.logger.warn(`Disabled reason: ${String(access.disabled_reason)}`);
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3899
|
+
}
|
|
3900
|
+
async function remoteEntitySwitch(options, context, runtime) {
|
|
3901
|
+
const entityId = parseEntityId(options.entityId);
|
|
3902
|
+
const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
|
|
3903
|
+
const target = entities.find((entity) => entity.entity_id === entityId);
|
|
3904
|
+
if (!target) {
|
|
3905
|
+
throw new Error(`当前账号不可切换到开发者主体 ${entityId};请先运行 hb-sdk remote entity list 查看可用主体`);
|
|
3906
|
+
}
|
|
3907
|
+
const result = await context.api.switchDeveloperEntity({ entityId });
|
|
3908
|
+
const access = await context.api.accessStatus();
|
|
3909
|
+
const switched = normalizeDeveloperEntity(result) ?? { ...target, is_current: true };
|
|
3910
|
+
await session.setSelectedDeveloperEntitySnapshot({
|
|
3911
|
+
entityId: switched.entity_id,
|
|
3912
|
+
entityName: switched.entity_name || '--',
|
|
3913
|
+
...(switched.owner_heybox_id !== undefined ? { ownerHeyboxId: switched.owner_heybox_id } : {}),
|
|
3914
|
+
}, {
|
|
3915
|
+
cacheFile: options.cacheFile,
|
|
3916
|
+
env: options.env,
|
|
3917
|
+
loginBaseUrl: options.loginBaseUrl,
|
|
3918
|
+
now: options.now,
|
|
3919
|
+
});
|
|
3920
|
+
const output = { changed: true, current: toCamelCaseDeep(switched), access: toCamelCaseDeep(access) };
|
|
3921
|
+
if (!options.json) {
|
|
3922
|
+
context.logger.success(`已切换开发者主体:${formatDeveloperEntity(switched)}`);
|
|
3923
|
+
context.logger.info(`Access status: ${String(access.status ?? 'unknown')}`);
|
|
3924
|
+
}
|
|
3925
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3926
|
+
}
|
|
3927
|
+
async function remoteList(options, context, runtime) {
|
|
3928
|
+
const result = await context.api.listMiniPrograms({ keyword: options.keyword, status: options.status });
|
|
3929
|
+
const items = Array.isArray(result.items) ? result.items : [];
|
|
3930
|
+
const outputItems = items.map((item) => ({ ...toCamelCaseDeep(item), bound: item.mini_program_id === context.binding }));
|
|
3931
|
+
const output = { changed: false, items: outputItems, total: readNumber(result.total, items.length) };
|
|
3932
|
+
if (!options.json) {
|
|
3933
|
+
if (items.length === 0) {
|
|
3934
|
+
context.logger.info('未找到远端小程序');
|
|
3935
|
+
}
|
|
3936
|
+
else {
|
|
3937
|
+
for (const item of items) {
|
|
3938
|
+
const marker = item.mini_program_id === context.binding ? '* ' : ' ';
|
|
3939
|
+
context.logger.info(`${marker}${item.mini_program_id ?? '--'} ${item.name ?? '--'} status=${item.status ?? '--'} version=${item.version || item.latest_version_status || '--'}`);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
if (!context.binding) {
|
|
3943
|
+
context.logger.info('当前项目尚未绑定远端小程序。绑定已有小程序:hb-sdk remote bind <mini-program-id>');
|
|
3944
|
+
}
|
|
3945
|
+
}
|
|
3946
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3947
|
+
}
|
|
3948
|
+
async function remoteCreate(options, context, runtime) {
|
|
3949
|
+
if (context.binding && !options.forceBind) {
|
|
3950
|
+
throw new Error(`当前项目已绑定 ${context.binding};如需覆盖,请使用 --force-bind`);
|
|
3951
|
+
}
|
|
3952
|
+
const name = requireNonEmpty(options.name, 'remote create 必须传 --name <name>');
|
|
3953
|
+
const previewImageUrl = validateOptionalHttpsUrl(options.previewImageUrl, '--preview-image-url');
|
|
3954
|
+
const access = await context.api.accessStatus();
|
|
3955
|
+
if (access.status !== 'approved') {
|
|
3956
|
+
throw new Error(`当前 CLI 用户没有创建开发者用户小程序权限:${String(access.status ?? 'unknown')}`);
|
|
3957
|
+
}
|
|
3958
|
+
await confirmCreateWithCurrentEntity(options, context, runtime);
|
|
3959
|
+
const result = await context.api.createMiniProgram({ name, previewImageUrl });
|
|
3960
|
+
const miniProgramId = requireMiniProgramId(result);
|
|
3961
|
+
await writeBoundMiniProgramId(context.packageJson.projectRoot, miniProgramId, { force: options.forceBind });
|
|
3962
|
+
const output = { changed: true, miniProgramId, remote: toCamelCaseDeep(result) };
|
|
3963
|
+
if (!options.json) {
|
|
3964
|
+
context.logger.success(`创建并绑定成功:${miniProgramId}`);
|
|
3965
|
+
}
|
|
3966
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3967
|
+
}
|
|
3968
|
+
async function remoteBind(options, context, runtime) {
|
|
3969
|
+
const miniProgramId = requireNonEmpty(options.miniProgramId, 'remote bind 必须传 <mini-program-id>');
|
|
3970
|
+
if (context.binding && context.binding !== miniProgramId && !options.force) {
|
|
3971
|
+
throw new Error(`当前项目已绑定 ${context.binding};如需覆盖本地绑定,请使用 --force`);
|
|
3972
|
+
}
|
|
3973
|
+
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
3974
|
+
const verifiedId = requireMiniProgramId(detail);
|
|
3975
|
+
await assertMiniProgramEntityMatchesCurrent(context, detail);
|
|
3976
|
+
const changed = context.binding !== verifiedId;
|
|
3977
|
+
if (changed) {
|
|
3978
|
+
await writeBoundMiniProgramId(context.packageJson.projectRoot, verifiedId, { force: options.force });
|
|
3979
|
+
}
|
|
3980
|
+
const output = { changed, miniProgramId: verifiedId, remote: toCamelCaseDeep(detail) };
|
|
3981
|
+
if (!options.json) {
|
|
3982
|
+
context.logger.success(changed ? `绑定成功:${verifiedId}` : `已绑定:${verifiedId}`);
|
|
3983
|
+
}
|
|
3984
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3985
|
+
}
|
|
3986
|
+
async function remoteInfo(options, context, runtime) {
|
|
3987
|
+
const miniProgramId = requireBinding(context);
|
|
3988
|
+
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
3989
|
+
const output = { changed: false, miniProgramId, detail: toCamelCaseDeep(detail) };
|
|
3990
|
+
if (!options.json) {
|
|
3991
|
+
printMiniProgramDetail(context.logger, detail);
|
|
3992
|
+
}
|
|
3993
|
+
return finishRemoteCommand(options, runtime, output);
|
|
3994
|
+
}
|
|
3995
|
+
async function remoteUpdate(options, context, runtime) {
|
|
3996
|
+
const miniProgramId = requireBinding(context);
|
|
3997
|
+
const hasName = options.name !== undefined;
|
|
3998
|
+
const hasPreviewImageUrl = options.previewImageUrl !== undefined;
|
|
3999
|
+
if (!hasName && !hasPreviewImageUrl) {
|
|
4000
|
+
throw new Error('remote update 至少需要传 --name 或 --preview-image-url');
|
|
4001
|
+
}
|
|
4002
|
+
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
4003
|
+
const nextName = hasName ? requireNonEmpty(options.name, '--name 不能为空') : requireNonEmpty(detail.name, '远端详情缺少 name,无法补全 update 请求');
|
|
4004
|
+
const nextPreviewImageUrl = hasPreviewImageUrl
|
|
4005
|
+
? validateOptionalHttpsUrl(options.previewImageUrl, '--preview-image-url') ?? ''
|
|
4006
|
+
: String(detail.preview_image_url ?? '');
|
|
4007
|
+
const result = await context.api.updateMiniProgram({ miniProgramId, name: nextName, previewImageUrl: nextPreviewImageUrl });
|
|
4008
|
+
const output = { changed: true, miniProgramId, remote: toCamelCaseDeep(result) };
|
|
4009
|
+
if (!options.json) {
|
|
4010
|
+
context.logger.success(`更新成功:${miniProgramId}`);
|
|
4011
|
+
}
|
|
4012
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4013
|
+
}
|
|
4014
|
+
async function remoteAllowlistList(options, context, runtime) {
|
|
4015
|
+
const miniProgramId = requireBinding(context);
|
|
4016
|
+
const result = await context.api.getAllowlist(miniProgramId);
|
|
4017
|
+
const output = {
|
|
4018
|
+
changed: false,
|
|
4019
|
+
items: toCamelCaseDeep(Array.isArray(result.items) ? result.items : []),
|
|
4020
|
+
limit: readNumber(result.limit, 0),
|
|
4021
|
+
miniProgramId,
|
|
4022
|
+
};
|
|
4023
|
+
if (!options.json) {
|
|
4024
|
+
printAllowlist(context.logger, result);
|
|
4025
|
+
}
|
|
4026
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4027
|
+
}
|
|
4028
|
+
async function remoteAllowlistWrite(options, context, runtime) {
|
|
4029
|
+
const miniProgramId = requireBinding(context);
|
|
4030
|
+
const inputIds = parseHeyboxIds(options.heyboxIds ?? []);
|
|
4031
|
+
const current = await context.api.getAllowlist(miniProgramId);
|
|
4032
|
+
const nextIds = mergeAllowlistIds(options.command, current, inputIds);
|
|
4033
|
+
assertAllowlistLimit(nextIds, current.limit);
|
|
4034
|
+
const result = await context.api.updateAllowlist({ miniProgramId, heyboxIds: nextIds });
|
|
4035
|
+
const output = {
|
|
4036
|
+
changed: true,
|
|
4037
|
+
items: toCamelCaseDeep(Array.isArray(result.items) ? result.items : []),
|
|
4038
|
+
limit: readNumber(result.limit, readNumber(current.limit, 0)),
|
|
4039
|
+
miniProgramId,
|
|
4040
|
+
};
|
|
4041
|
+
if (!options.json) {
|
|
4042
|
+
context.logger.success(`白名单已更新:${nextIds.join(',') || '(empty)'}`);
|
|
4043
|
+
}
|
|
4044
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4045
|
+
}
|
|
4046
|
+
async function remoteVersions(options, context, runtime) {
|
|
4047
|
+
const miniProgramId = requireBinding(context);
|
|
4048
|
+
const result = await context.api.listVersions(miniProgramId);
|
|
4049
|
+
const items = Array.isArray(result.items) ? result.items : [];
|
|
4050
|
+
const output = { changed: false, items: toCamelCaseDeep(items), miniProgramId, total: readNumber(result.total, items.length) };
|
|
4051
|
+
if (!options.json) {
|
|
4052
|
+
for (const item of items) {
|
|
4053
|
+
context.logger.info(`${item.version ?? '--'} status=${item.status ?? '--'} preview=${item.preview_url ?? '--'} publish=${item.publish_url ?? '--'}`);
|
|
4054
|
+
}
|
|
4055
|
+
if (items.length === 0) {
|
|
4056
|
+
context.logger.info('暂无远端版本');
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4060
|
+
}
|
|
4061
|
+
async function remotePreview(options, context, runtime) {
|
|
4062
|
+
const miniProgramId = requireBinding(context);
|
|
4063
|
+
const version = requireNonEmpty(options.version, 'remote preview 必须传 <version>');
|
|
4064
|
+
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) };
|
|
4067
|
+
if (!options.json) {
|
|
4068
|
+
context.logger.info(previewUrl ? `Preview URL: ${previewUrl}` : `版本 ${version} 暂无 preview URL`);
|
|
4069
|
+
}
|
|
4070
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4071
|
+
}
|
|
4072
|
+
async function remoteDangerousWrite(options, context, runtime) {
|
|
4073
|
+
const miniProgramId = requireBinding(context);
|
|
4074
|
+
const version = options.command === 'release' || options.command === 'withdraw' ? requireNonEmpty(options.version, `remote ${options.command} 必须传 <version>`) : undefined;
|
|
4075
|
+
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
4076
|
+
await confirmDangerousRemoteChange(options, runtime, context.logger, {
|
|
4077
|
+
miniProgramId,
|
|
4078
|
+
name: detail.name,
|
|
4079
|
+
operation: options.command,
|
|
4080
|
+
status: detail.status,
|
|
4081
|
+
version,
|
|
4082
|
+
});
|
|
4083
|
+
if (options.command === 'release') {
|
|
4084
|
+
const result = await context.api.releaseVersion({ miniProgramId, version: version });
|
|
4085
|
+
return finishDangerousWrite(options, runtime, context.logger, miniProgramId, result, { status: result.status, version });
|
|
4086
|
+
}
|
|
4087
|
+
if (options.command === 'withdraw') {
|
|
4088
|
+
const result = await context.api.withdrawVersion({ miniProgramId, reason: options.reason, version: version });
|
|
4089
|
+
return finishDangerousWrite(options, runtime, context.logger, miniProgramId, result, { status: result.status, version });
|
|
4090
|
+
}
|
|
4091
|
+
if (options.command === 'take-down') {
|
|
4092
|
+
const result = await context.api.takeDown(miniProgramId);
|
|
4093
|
+
return finishDangerousWrite(options, runtime, context.logger, miniProgramId, result, { status: result.status });
|
|
4094
|
+
}
|
|
4095
|
+
const result = await context.api.reopen(miniProgramId);
|
|
4096
|
+
return finishDangerousWrite(options, runtime, context.logger, miniProgramId, result, { status: result.status });
|
|
4097
|
+
}
|
|
4098
|
+
function finishDangerousWrite(options, runtime, logger, miniProgramId, result, extras) {
|
|
4099
|
+
const output = { changed: true, miniProgramId, ...extras, remote: toCamelCaseDeep(result) };
|
|
4100
|
+
if (!options.json) {
|
|
4101
|
+
logger.success(`操作成功:${options.command} ${miniProgramId}`);
|
|
4102
|
+
}
|
|
4103
|
+
return finishRemoteCommand(options, runtime, output);
|
|
4104
|
+
}
|
|
4105
|
+
function finishRemoteCommand(options, runtime, output) {
|
|
4106
|
+
const normalized = toCamelCaseDeep(output);
|
|
4107
|
+
if (options.json) {
|
|
4108
|
+
writeStdout(runtime, `${JSON.stringify(normalized)}\n`);
|
|
4109
|
+
}
|
|
4110
|
+
return normalized;
|
|
4111
|
+
}
|
|
4112
|
+
function resolveRemoteLogger(options, runtime) {
|
|
4113
|
+
if (options.json) {
|
|
4114
|
+
return createJsonSafeLogger(runtime);
|
|
4115
|
+
}
|
|
4116
|
+
if (runtime.logger) {
|
|
4117
|
+
return runtime.logger;
|
|
4118
|
+
}
|
|
4119
|
+
return index.createCliLogger({
|
|
4120
|
+
isTTY: runtime.isTTY,
|
|
4121
|
+
stderr: runtime.stderr,
|
|
4122
|
+
stdout: runtime.stdout,
|
|
4123
|
+
});
|
|
4124
|
+
}
|
|
4125
|
+
function createJsonSafeLogger(runtime) {
|
|
4126
|
+
const stderr = runtime.stderr ?? process.stderr;
|
|
4127
|
+
return index.createCliLogger({
|
|
4128
|
+
isTTY: runtime.isTTY,
|
|
4129
|
+
stderr,
|
|
4130
|
+
stdout: stderr,
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
4133
|
+
function writeStdout(runtime, message) {
|
|
4134
|
+
(runtime.stdout ?? process.stdout).write(message);
|
|
4135
|
+
}
|
|
4136
|
+
function requireBinding(context) {
|
|
4137
|
+
if (!context.binding) {
|
|
4138
|
+
throw new Error('当前项目尚未绑定远端小程序,请先运行 hb-sdk remote create 或 hb-sdk remote bind <mini-program-id>');
|
|
4139
|
+
}
|
|
4140
|
+
return context.binding;
|
|
4141
|
+
}
|
|
4142
|
+
async function requireCurrentDeveloperEntity(context) {
|
|
4143
|
+
const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
|
|
4144
|
+
const current = entities.find((entity) => entity.is_current === true);
|
|
4145
|
+
if (!current) {
|
|
4146
|
+
throw new Error('当前账号没有服务端 current 开发者主体;请先运行 hb-sdk remote entity list 查看可用主体,并用 hb-sdk remote entity switch <entity-id> 切换');
|
|
4147
|
+
}
|
|
4148
|
+
return current;
|
|
4149
|
+
}
|
|
4150
|
+
async function confirmCreateWithCurrentEntity(options, context, runtime) {
|
|
4151
|
+
const entities = normalizeDeveloperEntities(await context.api.listDeveloperEntities());
|
|
4152
|
+
if (entities.length <= 1) {
|
|
4153
|
+
return;
|
|
4154
|
+
}
|
|
4155
|
+
const current = entities.find((entity) => entity.is_current === true);
|
|
4156
|
+
if (!current) {
|
|
4157
|
+
throw new Error('当前账号存在多个开发者主体,但没有服务端 current 主体;请先运行 hb-sdk remote entity switch <entity-id>');
|
|
4158
|
+
}
|
|
4159
|
+
if (!options.json) {
|
|
4160
|
+
context.logger.info(`当前创建将归属开发者主体:${formatDeveloperEntity(current)}`);
|
|
4161
|
+
context.logger.info(`如需切换主体,请先运行:hb-sdk remote entity switch <entity-id>`);
|
|
4162
|
+
}
|
|
4163
|
+
if (options.yes) {
|
|
4164
|
+
return;
|
|
4165
|
+
}
|
|
4166
|
+
const isTTY = runtime.isTTY ?? Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
4167
|
+
if (!isTTY) {
|
|
4168
|
+
throw new Error(`当前账号存在多个开发者主体,非交互环境执行 hb-sdk remote create 必须传 --yes 确认使用当前主体:${formatDeveloperEntity(current)}。如需切换,请先运行 hb-sdk remote entity switch <entity-id>`);
|
|
4169
|
+
}
|
|
4170
|
+
const accepted = runtime.promptConfirm
|
|
4171
|
+
? await runtime.promptConfirm(`确认使用当前开发者主体 ${formatDeveloperEntity(current)} 创建小程序?`)
|
|
4172
|
+
: await promptConfirm(`确认使用当前开发者主体 ${formatDeveloperEntity(current)} 创建小程序?输入 yes 继续: `, runtime);
|
|
4173
|
+
if (!accepted) {
|
|
4174
|
+
throw new Error('已取消操作');
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
async function assertMiniProgramEntityMatchesCurrent(context, detail) {
|
|
4178
|
+
if (!isValidEntityId(detail.entity_id)) {
|
|
4179
|
+
return;
|
|
4180
|
+
}
|
|
4181
|
+
const current = await requireCurrentDeveloperEntity(context);
|
|
4182
|
+
if (current.entity_id === detail.entity_id) {
|
|
4183
|
+
return;
|
|
4184
|
+
}
|
|
4185
|
+
throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail(detail) }));
|
|
4186
|
+
}
|
|
4187
|
+
async function assertBoundMiniProgramEntityMatchesCurrent(context, miniProgramId) {
|
|
4188
|
+
const current = await requireCurrentDeveloperEntity(context);
|
|
4189
|
+
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
4190
|
+
requireMiniProgramId(detail);
|
|
4191
|
+
if (!isValidEntityId(detail.entity_id)) {
|
|
4192
|
+
throw new Error(`远端小程序 ${miniProgramId} 详情缺少 entity_id,无法校验当前主体一致性,已停止 deploy`);
|
|
4193
|
+
}
|
|
4194
|
+
if (current.entity_id !== detail.entity_id) {
|
|
4195
|
+
throw new Error(createEntityMismatchMessage({ current, target: createEntityFromMiniProgramDetail(detail) }));
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
function createEntityMismatchMessage(options) {
|
|
4199
|
+
return [
|
|
4200
|
+
'当前开发者主体与远端小程序所属主体不一致,已停止操作。',
|
|
4201
|
+
`当前主体:${formatDeveloperEntity(options.current)}`,
|
|
4202
|
+
`小程序所属主体:${formatDeveloperEntity(options.target)}`,
|
|
4203
|
+
`请先运行:hb-sdk remote entity switch ${options.target.entity_id}`,
|
|
4204
|
+
].join('\n');
|
|
4205
|
+
}
|
|
4206
|
+
function requireMiniProgramId(result) {
|
|
4207
|
+
const miniProgramId = result.mini_program_id;
|
|
4208
|
+
if (typeof miniProgramId !== 'string' || !miniProgramId.trim()) {
|
|
4209
|
+
throw new Error('远端响应缺少 mini_program_id');
|
|
4210
|
+
}
|
|
4211
|
+
return miniProgramId.trim();
|
|
4212
|
+
}
|
|
4213
|
+
function parseEntityId(value) {
|
|
4214
|
+
const raw = requireNonEmpty(value, 'remote entity switch 必须传 <entity-id>');
|
|
4215
|
+
if (!/^(0|[1-9]\d*)$/.test(raw)) {
|
|
4216
|
+
throw new Error(`entity-id 只接受十进制数字:${raw}`);
|
|
4217
|
+
}
|
|
4218
|
+
const entityId = Number(raw);
|
|
4219
|
+
if (!isValidEntityId(entityId)) {
|
|
4220
|
+
throw new Error(`entity-id 超出有效范围:${raw}`);
|
|
4221
|
+
}
|
|
4222
|
+
return entityId;
|
|
4223
|
+
}
|
|
4224
|
+
function normalizeDeveloperEntities(result) {
|
|
4225
|
+
const rawItems = Array.isArray(result.items) ? result.items : [];
|
|
4226
|
+
return rawItems.map((item) => normalizeDeveloperEntity(item)).filter((item) => item !== undefined);
|
|
4227
|
+
}
|
|
4228
|
+
function normalizeDeveloperEntity(value) {
|
|
4229
|
+
if (!value || typeof value !== 'object') {
|
|
4230
|
+
return undefined;
|
|
4231
|
+
}
|
|
4232
|
+
const rawEntityId = value.entity_id;
|
|
4233
|
+
if (!isValidEntityId(rawEntityId)) {
|
|
4234
|
+
return undefined;
|
|
4235
|
+
}
|
|
4236
|
+
return {
|
|
4237
|
+
...value,
|
|
4238
|
+
entity_id: rawEntityId,
|
|
4239
|
+
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,
|
|
4243
|
+
is_current: value.is_current === true,
|
|
4244
|
+
};
|
|
4245
|
+
}
|
|
4246
|
+
function createEntityFromMiniProgramDetail(detail) {
|
|
4247
|
+
return {
|
|
4248
|
+
entity_id: detail.entity_id,
|
|
4249
|
+
entity_name: typeof detail.developer_name === 'string' ? detail.developer_name : undefined,
|
|
4250
|
+
owner_heybox_id: detail.owner_heybox_id,
|
|
4251
|
+
is_current: false,
|
|
4252
|
+
};
|
|
4253
|
+
}
|
|
4254
|
+
function isValidEntityId(value) {
|
|
4255
|
+
return Number.isSafeInteger(value) && Number(value) > 0;
|
|
4256
|
+
}
|
|
4257
|
+
function requireNonEmpty(value, message) {
|
|
4258
|
+
const normalized = typeof value === 'string' ? value.trim() : '';
|
|
4259
|
+
if (!normalized) {
|
|
4260
|
+
throw new Error(message);
|
|
4261
|
+
}
|
|
4262
|
+
return normalized;
|
|
4263
|
+
}
|
|
4264
|
+
function validateOptionalHttpsUrl(value, label) {
|
|
4265
|
+
if (value === undefined) {
|
|
4266
|
+
return undefined;
|
|
4267
|
+
}
|
|
4268
|
+
const raw = requireNonEmpty(value, `${label} 不能为空`);
|
|
4269
|
+
let url;
|
|
4270
|
+
try {
|
|
4271
|
+
url = new URL(raw);
|
|
4272
|
+
}
|
|
4273
|
+
catch {
|
|
4274
|
+
throw new Error(`${label} 必须是合法 HTTPS URL`);
|
|
4275
|
+
}
|
|
4276
|
+
if (url.protocol !== 'https:') {
|
|
4277
|
+
throw new Error(`${label} 只接受 HTTPS URL`);
|
|
4278
|
+
}
|
|
4279
|
+
return raw;
|
|
4280
|
+
}
|
|
4281
|
+
function parseHeyboxIds(values) {
|
|
4282
|
+
if (values.length === 0) {
|
|
4283
|
+
throw new Error('请传入至少一个十进制 heybox_id');
|
|
4284
|
+
}
|
|
4285
|
+
const ids = [];
|
|
4286
|
+
for (const value of values) {
|
|
4287
|
+
const raw = String(value).trim();
|
|
4288
|
+
if (!/^(0|[1-9]\d*)$/.test(raw)) {
|
|
4289
|
+
throw new Error(`heybox_id 只接受十进制数字:${value}`);
|
|
4290
|
+
}
|
|
4291
|
+
const id = Number(raw);
|
|
4292
|
+
if (!Number.isSafeInteger(id) || id <= 0) {
|
|
4293
|
+
throw new Error(`heybox_id 超出有效范围:${value}`);
|
|
4294
|
+
}
|
|
4295
|
+
if (!ids.includes(id)) {
|
|
4296
|
+
ids.push(id);
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
return ids;
|
|
4300
|
+
}
|
|
4301
|
+
function mergeAllowlistIds(command, current, inputIds) {
|
|
4302
|
+
const items = Array.isArray(current.items) ? current.items : [];
|
|
4303
|
+
const ownerIds = items.filter((item) => item.is_owner === true && isValidHeyboxIdNumber(item.heybox_id)).map((item) => item.heybox_id);
|
|
4304
|
+
const currentIds = items.filter((item) => isValidHeyboxIdNumber(item.heybox_id)).map((item) => item.heybox_id);
|
|
4305
|
+
if (command === 'allowlist:add') {
|
|
4306
|
+
return uniqueNumbers([...currentIds, ...inputIds]);
|
|
4307
|
+
}
|
|
4308
|
+
if (command === 'allowlist:remove') {
|
|
4309
|
+
return uniqueNumbers(currentIds.filter((id) => ownerIds.includes(id) || !inputIds.includes(id)));
|
|
4310
|
+
}
|
|
4311
|
+
return uniqueNumbers([...ownerIds, ...inputIds.filter((id) => !ownerIds.includes(id))]);
|
|
4312
|
+
}
|
|
4313
|
+
function assertAllowlistLimit(ids, limit) {
|
|
4314
|
+
const parsedLimit = typeof limit === 'number' && Number.isFinite(limit) ? limit : undefined;
|
|
4315
|
+
if (parsedLimit !== undefined && ids.length > parsedLimit) {
|
|
4316
|
+
throw new Error(`内测白名单最多 ${parsedLimit} 人,当前操作会变为 ${ids.length} 人`);
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
function uniqueNumbers(values) {
|
|
4320
|
+
const result = [];
|
|
4321
|
+
for (const value of values) {
|
|
4322
|
+
if (!result.includes(value)) {
|
|
4323
|
+
result.push(value);
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
return result;
|
|
4327
|
+
}
|
|
4328
|
+
function isValidHeyboxIdNumber(value) {
|
|
4329
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
|
|
4330
|
+
}
|
|
4331
|
+
async function confirmDangerousRemoteChange(options, runtime, logger, context) {
|
|
4332
|
+
const lines = [
|
|
4333
|
+
`操作:${context.operation}`,
|
|
4334
|
+
`Mini-program: ${context.miniProgramId}`,
|
|
4335
|
+
`名称:${context.name || '--'}`,
|
|
4336
|
+
`当前状态:${context.status || '--'}`,
|
|
4337
|
+
...(context.version ? [`目标版本:${context.version}`] : []),
|
|
4338
|
+
];
|
|
4339
|
+
if (!options.json) {
|
|
4340
|
+
for (const line of lines) {
|
|
4341
|
+
logger.info(line);
|
|
4342
|
+
}
|
|
4343
|
+
}
|
|
4344
|
+
else if (!options.yes) {
|
|
4345
|
+
for (const line of lines) {
|
|
4346
|
+
logger.info(line, { stream: 'stderr' });
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
if (options.yes) {
|
|
4350
|
+
return;
|
|
4351
|
+
}
|
|
4352
|
+
const isTTY = runtime.isTTY ?? Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
4353
|
+
if (!isTTY) {
|
|
4354
|
+
throw new Error(`非交互环境执行 hb-sdk remote ${context.operation} 必须传 --yes`);
|
|
4355
|
+
}
|
|
4356
|
+
const accepted = runtime.promptConfirm
|
|
4357
|
+
? await runtime.promptConfirm(`确认执行 ${context.operation}?`)
|
|
4358
|
+
: await promptConfirm(`确认执行 ${context.operation}?输入 yes 继续: `, runtime);
|
|
4359
|
+
if (!accepted) {
|
|
4360
|
+
throw new Error('已取消操作');
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
async function promptConfirm(message, runtime) {
|
|
4364
|
+
const input = runtime.stdin ?? process.stdin;
|
|
4365
|
+
const output = runtime.stderr ?? process.stderr;
|
|
4366
|
+
const rl = promises.createInterface({ input, output: output });
|
|
4367
|
+
try {
|
|
4368
|
+
const answer = await rl.question(message);
|
|
4369
|
+
return answer.trim().toLowerCase() === 'yes';
|
|
4370
|
+
}
|
|
4371
|
+
finally {
|
|
4372
|
+
rl.close();
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
function printMiniProgramDetail(logger, detail) {
|
|
4376
|
+
logger.info(`Mini-program: ${detail.mini_program_id ?? '--'}`);
|
|
4377
|
+
logger.info(`Name: ${detail.name ?? '--'}`);
|
|
4378
|
+
logger.info(`Status: ${detail.status ?? '--'}`);
|
|
4379
|
+
logger.info(`Version: ${detail.version || detail.latest_version_status || '--'}`);
|
|
4380
|
+
if (detail.publish_url) {
|
|
4381
|
+
logger.info(`Publish URL: ${detail.publish_url}`);
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
function printDeveloperEntities(logger, entities) {
|
|
4385
|
+
for (const entity of entities) {
|
|
4386
|
+
printDeveloperEntity(logger, entity, entity.is_current ? '* ' : ' ');
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
function printDeveloperEntity(logger, entity, marker = '') {
|
|
4390
|
+
logger.info(`${marker}${formatDeveloperEntity(entity)}${entity.is_current ? ' current' : ''}`);
|
|
4391
|
+
}
|
|
4392
|
+
function formatDeveloperEntity(entity) {
|
|
4393
|
+
const name = entity.entity_name || '--';
|
|
4394
|
+
const owner = entity.owner_heybox_id ? ` owner=${entity.owner_heybox_id}` : '';
|
|
4395
|
+
return `${entity.entity_id ?? '--'} ${name}${owner}`;
|
|
4396
|
+
}
|
|
4397
|
+
function printAllowlist(logger, result) {
|
|
4398
|
+
const items = Array.isArray(result.items) ? result.items : [];
|
|
4399
|
+
logger.info(`Limit: ${readNumber(result.limit, 0)}`);
|
|
4400
|
+
if (items.length === 0) {
|
|
4401
|
+
logger.info('内测白名单为空');
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
for (const item of items) {
|
|
4405
|
+
logger.info(`${item.heybox_id ?? '--'}${item.is_owner ? ' (owner)' : ''}${item.nickname ? ` ${item.nickname}` : ''}`);
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
function readNumber(value, fallback) {
|
|
4409
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
|
4410
|
+
}
|
|
4411
|
+
function toCamelCaseDeep(value) {
|
|
4412
|
+
if (Array.isArray(value)) {
|
|
4413
|
+
return value.map((item) => toCamelCaseDeep(item));
|
|
4414
|
+
}
|
|
4415
|
+
if (!value || Object.prototype.toString.call(value) !== '[object Object]') {
|
|
4416
|
+
return value;
|
|
4417
|
+
}
|
|
4418
|
+
const result = {};
|
|
4419
|
+
for (const [key, item] of Object.entries(value)) {
|
|
4420
|
+
result[toCamelKey(key)] = toCamelCaseDeep(item);
|
|
4421
|
+
}
|
|
4422
|
+
return result;
|
|
4423
|
+
}
|
|
4424
|
+
function toCamelKey(key) {
|
|
4425
|
+
return key.replace(/_([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
4426
|
+
}
|
|
4427
|
+
|
|
4428
|
+
var remote = /*#__PURE__*/Object.freeze({
|
|
3723
4429
|
__proto__: null,
|
|
3724
|
-
|
|
3725
|
-
runDeployCommand: runDeployCommand,
|
|
3726
|
-
validateDeployReleaseNote: validateDeployReleaseNote
|
|
4430
|
+
runRemoteCommand: runRemoteCommand
|
|
3727
4431
|
});
|
|
3728
4432
|
|
|
3729
|
-
exports.
|
|
4433
|
+
exports.remote = remote;
|
|
3730
4434
|
exports.requireSemver = requireSemver;
|