@heybox/hb-sdk 0.4.5 → 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 +29 -21
- package/dist/cli-chunks/{create-DpyZCNdo.cjs → create-BahMMgJH.cjs} +1 -1
- package/dist/cli-chunks/{dev-DWIpgJnn.cjs → dev-CTuXVPpU.cjs} +1 -1
- package/dist/cli-chunks/{doctor-DBotVUQI.cjs → doctor-9gg3ZIvt.cjs} +1 -1
- package/dist/cli-chunks/{index-DRsyeAcg.cjs → index-CLne_LW7.cjs} +2 -2
- package/dist/cli-chunks/{index-BYMTp2I6.cjs → index-DuwxUSkq.cjs} +24 -15
- package/dist/cli-chunks/{login-DIgcT1gv.cjs → login-OqaEx-Wd.cjs} +153 -2
- package/dist/cli-chunks/{remote-DjaOc1VS.cjs → remote-zX17hOT4.cjs} +220 -292
- package/dist/cli-chunks/{session-BAgaqpNL.cjs → session-D7lF9mpd.cjs} +347 -9
- package/dist/cli.cjs +1 -1
- package/dist/miniapp-publish.cjs.js +4 -0
- package/dist/miniapp-publish.esm.js +3 -1
- package/dist/templates/vue3-vite-ts/README.md.ejs +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +24 -22
- package/skill/references/api-root.md +1 -1
- package/skill/references/cli.md +37 -4
- package/skill/scripts/sync-references.mjs +38 -3
- package/skill/skill.json +4 -4
- package/types/miniapp-publish/index.d.ts +2 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var promises = require('node:readline/promises');
|
|
4
|
+
var session = require('./session-D7lF9mpd.cjs');
|
|
4
5
|
var childProcess = require('node:child_process');
|
|
5
6
|
var fs = require('node:fs');
|
|
6
7
|
var fs$1 = require('node:fs/promises');
|
|
7
8
|
var path = require('node:path');
|
|
8
|
-
var
|
|
9
|
-
var index = require('./index-BYMTp2I6.cjs');
|
|
10
|
-
var node_crypto = require('node:crypto');
|
|
9
|
+
var index = require('./index-DuwxUSkq.cjs');
|
|
11
10
|
|
|
12
11
|
var re = {exports: {}};
|
|
13
12
|
|
|
@@ -2860,6 +2859,8 @@ function formatReason(error) {
|
|
|
2860
2859
|
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
2861
2860
|
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
2862
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';
|
|
2863
2864
|
const LIST_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/list';
|
|
2864
2865
|
const CREATE_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/create';
|
|
2865
2866
|
const UPDATE_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/update';
|
|
@@ -2932,281 +2933,6 @@ function shouldUploadDistFile(relativePath) {
|
|
|
2932
2933
|
return true;
|
|
2933
2934
|
}
|
|
2934
2935
|
|
|
2935
|
-
const globalHeyboxCliRequestConfig = {};
|
|
2936
|
-
function readHeyboxCliRequestConfig() {
|
|
2937
|
-
return normalizeHeyboxRylaiServiceTagConfig(globalHeyboxCliRequestConfig);
|
|
2938
|
-
}
|
|
2939
|
-
function resolveHeyboxRylaiServiceTag(pathWithQuery, config = readHeyboxCliRequestConfig()) {
|
|
2940
|
-
const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
|
|
2941
|
-
const pathname = pathWithQuery ? getPathname(pathWithQuery) : '';
|
|
2942
|
-
const specialTag = normalized.special_tag;
|
|
2943
|
-
if (pathname && specialTag?.path_prefix_list.some((prefix) => pathname.startsWith(prefix))) {
|
|
2944
|
-
return specialTag.tag_name;
|
|
2945
|
-
}
|
|
2946
|
-
return normalized.default_tag;
|
|
2947
|
-
}
|
|
2948
|
-
function normalizeHeyboxRylaiServiceTagConfig(config) {
|
|
2949
|
-
const defaultTag = normalizeHeyboxRylaiServiceTag(config.default_tag);
|
|
2950
|
-
const specialTagName = normalizeHeyboxRylaiServiceTag(config.special_tag?.tag_name);
|
|
2951
|
-
const pathPrefixList = config.special_tag?.path_prefix_list?.filter(isValidPathPrefix) || [];
|
|
2952
|
-
return {
|
|
2953
|
-
...(defaultTag ? { default_tag: defaultTag } : {}),
|
|
2954
|
-
...(specialTagName && pathPrefixList.length
|
|
2955
|
-
? {
|
|
2956
|
-
special_tag: {
|
|
2957
|
-
tag_name: specialTagName,
|
|
2958
|
-
path_prefix_list: pathPrefixList,
|
|
2959
|
-
},
|
|
2960
|
-
}
|
|
2961
|
-
: {}),
|
|
2962
|
-
};
|
|
2963
|
-
}
|
|
2964
|
-
function normalizeHeyboxRylaiServiceTag(value) {
|
|
2965
|
-
const tag = String(value ?? '').trim();
|
|
2966
|
-
if (!tag) {
|
|
2967
|
-
return undefined;
|
|
2968
|
-
}
|
|
2969
|
-
if (/[\r\n]/.test(tag)) {
|
|
2970
|
-
throw new Error('x-rylai-service-tag 不允许包含换行符');
|
|
2971
|
-
}
|
|
2972
|
-
return tag;
|
|
2973
|
-
}
|
|
2974
|
-
function isValidPathPrefix(value) {
|
|
2975
|
-
return typeof value === 'string' && value.startsWith('/') && !/[\r\n]/.test(value);
|
|
2976
|
-
}
|
|
2977
|
-
function getPathname(pathWithQuery) {
|
|
2978
|
-
try {
|
|
2979
|
-
return new URL(pathWithQuery, 'https://api.xiaoheihe.cn').pathname;
|
|
2980
|
-
}
|
|
2981
|
-
catch {
|
|
2982
|
-
return '';
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
const SIGN_VERSION = '999.0.4';
|
|
2987
|
-
const SIGN_CHARSET = 'AB45STUVWZEFGJ6CH01D237IXYPQRKLMN89';
|
|
2988
|
-
function createHeyboxOpenPlatformSignParams(pathname, options = {}) {
|
|
2989
|
-
const now = options.now ?? new Date();
|
|
2990
|
-
const time = Math.trunc(now.getTime() / 1000);
|
|
2991
|
-
const nonce = options.nonce ?? md5(`${time}${Date.now()}${node_crypto.randomBytes(16).toString('hex')}`).toUpperCase();
|
|
2992
|
-
return {
|
|
2993
|
-
version: SIGN_VERSION,
|
|
2994
|
-
hkey: generateSignature(pathname, time + 1, nonce),
|
|
2995
|
-
_time: time,
|
|
2996
|
-
nonce,
|
|
2997
|
-
};
|
|
2998
|
-
}
|
|
2999
|
-
function generateSignature(path, time, nonce) {
|
|
3000
|
-
const normalizedPath = `/${path
|
|
3001
|
-
.split('/')
|
|
3002
|
-
.filter(Boolean)
|
|
3003
|
-
.join('/')}/`;
|
|
3004
|
-
const transformedTime = transformWithOffset(String(time), SIGN_CHARSET, -2);
|
|
3005
|
-
const transformedPath = transform(normalizedPath, SIGN_CHARSET);
|
|
3006
|
-
const transformedNonce = transform(nonce, SIGN_CHARSET);
|
|
3007
|
-
const combined = interleave([transformedTime, transformedPath, transformedNonce]).slice(0, 20);
|
|
3008
|
-
const hash = md5(combined);
|
|
3009
|
-
let sign = `${mixColumns(hash.slice(-6).split('').map((char) => char.charCodeAt(0))).reduce((sum, value) => sum + value, 0) % 100}`;
|
|
3010
|
-
sign = sign.length < 2 ? `0${sign}` : sign;
|
|
3011
|
-
return `${transformWithOffset(hash.substring(0, 5), SIGN_CHARSET, -4)}${sign}`;
|
|
3012
|
-
}
|
|
3013
|
-
function transformWithOffset(str, charset, offset) {
|
|
3014
|
-
return transform(str, charset.slice(0, offset));
|
|
3015
|
-
}
|
|
3016
|
-
function transform(str, charset) {
|
|
3017
|
-
let output = '';
|
|
3018
|
-
for (let index = 0; index < str.length; index += 1) {
|
|
3019
|
-
output += charset[str.charCodeAt(index) % charset.length];
|
|
3020
|
-
}
|
|
3021
|
-
return output;
|
|
3022
|
-
}
|
|
3023
|
-
function interleave(strings) {
|
|
3024
|
-
let output = '';
|
|
3025
|
-
const maxLength = Math.max(...strings.map((str) => str.length));
|
|
3026
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
3027
|
-
for (const str of strings) {
|
|
3028
|
-
if (index < str.length) {
|
|
3029
|
-
output += str[index];
|
|
3030
|
-
}
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
return output;
|
|
3034
|
-
}
|
|
3035
|
-
function mixColumns(column) {
|
|
3036
|
-
const output = [...column];
|
|
3037
|
-
output[0] = multiplyE(column[0]) ^ multiply4(column[1]) ^ multiply3(column[2]) ^ multiply2(column[3]);
|
|
3038
|
-
output[1] = multiply2(column[0]) ^ multiplyE(column[1]) ^ multiply4(column[2]) ^ multiply3(column[3]);
|
|
3039
|
-
output[2] = multiply3(column[0]) ^ multiply2(column[1]) ^ multiplyE(column[2]) ^ multiply4(column[3]);
|
|
3040
|
-
output[3] = multiply4(column[0]) ^ multiply3(column[1]) ^ multiply2(column[2]) ^ multiplyE(column[3]);
|
|
3041
|
-
return output;
|
|
3042
|
-
}
|
|
3043
|
-
function multiply1(value) {
|
|
3044
|
-
if (value & 0x80) {
|
|
3045
|
-
return ((value << 1) ^ 0x1b) & 0xff;
|
|
3046
|
-
}
|
|
3047
|
-
return value << 1;
|
|
3048
|
-
}
|
|
3049
|
-
function multiply2(value) {
|
|
3050
|
-
return multiply1(value) ^ value;
|
|
3051
|
-
}
|
|
3052
|
-
function multiply3(value) {
|
|
3053
|
-
return multiply2(multiply1(value));
|
|
3054
|
-
}
|
|
3055
|
-
function multiply4(value) {
|
|
3056
|
-
return multiply3(multiply2(multiply1(value)));
|
|
3057
|
-
}
|
|
3058
|
-
function multiplyE(value) {
|
|
3059
|
-
return multiply4(value) ^ multiply3(value) ^ multiply2(value);
|
|
3060
|
-
}
|
|
3061
|
-
function md5(input) {
|
|
3062
|
-
return node_crypto.createHash('md5').update(input).digest('hex');
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3065
|
-
const DEFAULT_PLATFORM_PARAMS = {
|
|
3066
|
-
os_type: 'web',
|
|
3067
|
-
app: 'heybox',
|
|
3068
|
-
x_client_type: 'web',
|
|
3069
|
-
x_os_type: 'Mac',
|
|
3070
|
-
x_app: 'heybox',
|
|
3071
|
-
x_client_version: '999.999.999',
|
|
3072
|
-
};
|
|
3073
|
-
const HEYBOX_WEB_REFERER = 'https://www.xiaoheihe.cn/';
|
|
3074
|
-
function resolveHeyboxId(session) {
|
|
3075
|
-
if (session.heyboxId.trim()) {
|
|
3076
|
-
return session.heyboxId.trim();
|
|
3077
|
-
}
|
|
3078
|
-
return session.cookieHeader
|
|
3079
|
-
.split(';')
|
|
3080
|
-
.map((part) => part.trim())
|
|
3081
|
-
.find((part) => part.startsWith('heybox_id='))
|
|
3082
|
-
?.slice('heybox_id='.length);
|
|
3083
|
-
}
|
|
3084
|
-
function createHeyboxAuthHeaders(session, options = {}) {
|
|
3085
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
3086
|
-
return {
|
|
3087
|
-
Cookie: session.cookieHeader,
|
|
3088
|
-
Referer: HEYBOX_WEB_REFERER,
|
|
3089
|
-
...(options.contentType ? { 'Content-Type': options.contentType } : {}),
|
|
3090
|
-
...(serviceTag ? { 'x-rylai-service-tag': serviceTag } : {}),
|
|
3091
|
-
};
|
|
3092
|
-
}
|
|
3093
|
-
function createHeyboxRequestContext(session$1, options = {}) {
|
|
3094
|
-
const heyboxId = resolveHeyboxId(session$1);
|
|
3095
|
-
const serviceTag = resolveHeyboxRylaiServiceTag(options.pathWithQuery);
|
|
3096
|
-
return {
|
|
3097
|
-
baseUrl: session.HEYBOX_API_BASE_URL,
|
|
3098
|
-
headers: createHeyboxAuthHeaders(session$1, options),
|
|
3099
|
-
platformParams: {
|
|
3100
|
-
...DEFAULT_PLATFORM_PARAMS,
|
|
3101
|
-
...options.platformParams,
|
|
3102
|
-
...(heyboxId ? { heybox_id: heyboxId } : {}),
|
|
3103
|
-
...(serviceTag ? { special_tag: serviceTag } : {}),
|
|
3104
|
-
},
|
|
3105
|
-
};
|
|
3106
|
-
}
|
|
3107
|
-
function createHeyboxOpenPlatformRequestContext(session, pathWithQuery, options = {}) {
|
|
3108
|
-
return createHeyboxRequestContext(session, {
|
|
3109
|
-
...options,
|
|
3110
|
-
pathWithQuery,
|
|
3111
|
-
platformParams: {
|
|
3112
|
-
x_app: 'heybox_website',
|
|
3113
|
-
...createHeyboxOpenPlatformSignParams(getApiPathname(pathWithQuery)),
|
|
3114
|
-
...options.platformParams,
|
|
3115
|
-
},
|
|
3116
|
-
});
|
|
3117
|
-
}
|
|
3118
|
-
function createHeyboxApiUrl(baseUrl, pathWithQuery, params) {
|
|
3119
|
-
const url = new URL(pathWithQuery, baseUrl);
|
|
3120
|
-
for (const [key, value] of Object.entries(params)) {
|
|
3121
|
-
if (value !== '') {
|
|
3122
|
-
url.searchParams.set(key, String(value));
|
|
3123
|
-
}
|
|
3124
|
-
}
|
|
3125
|
-
return url.toString();
|
|
3126
|
-
}
|
|
3127
|
-
function getApiPathname(pathWithQuery) {
|
|
3128
|
-
return new URL(pathWithQuery, session.HEYBOX_API_BASE_URL).pathname;
|
|
3129
|
-
}
|
|
3130
|
-
const ENVELOPE_BODY_PREVIEW_LENGTH = 1000;
|
|
3131
|
-
async function readHeyboxApiEnvelope(response, options) {
|
|
3132
|
-
const rawBody = await response.text();
|
|
3133
|
-
let envelope = null;
|
|
3134
|
-
let parseError = null;
|
|
3135
|
-
if (rawBody) {
|
|
3136
|
-
try {
|
|
3137
|
-
envelope = JSON.parse(rawBody);
|
|
3138
|
-
}
|
|
3139
|
-
catch (error) {
|
|
3140
|
-
parseError = error;
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
const envelopeOk = envelope?.status === 'ok' && (!options.requireResult || envelope?.result !== undefined);
|
|
3144
|
-
if (response.ok && envelopeOk) {
|
|
3145
|
-
return envelope.result;
|
|
3146
|
-
}
|
|
3147
|
-
const { message, verboseMessage } = formatHeyboxEnvelopeError({
|
|
3148
|
-
response,
|
|
3149
|
-
envelope,
|
|
3150
|
-
parseError,
|
|
3151
|
-
rawBody,
|
|
3152
|
-
pathWithQuery: options.pathWithQuery,
|
|
3153
|
-
});
|
|
3154
|
-
throw new index.CliError(message, verboseMessage);
|
|
3155
|
-
}
|
|
3156
|
-
function formatHeyboxEnvelopeError(input) {
|
|
3157
|
-
const parts = [`Heybox API ${input.pathWithQuery} failed`, `HTTP ${input.response.status}`];
|
|
3158
|
-
if (input.envelope) {
|
|
3159
|
-
const msg = typeof input.envelope.msg === 'string' ? input.envelope.msg.trim() : '';
|
|
3160
|
-
const sbeUserMessage = readSbeUserMessage(input.envelope.result);
|
|
3161
|
-
parts.push(`msg=${msg || '(empty)'}`);
|
|
3162
|
-
if (typeof input.envelope.status === 'string') {
|
|
3163
|
-
parts.push(`envelope.status=${input.envelope.status}`);
|
|
3164
|
-
}
|
|
3165
|
-
const { status: _s, msg: _m, result: _r, ...extras } = input.envelope;
|
|
3166
|
-
if (Object.keys(extras).length > 0) {
|
|
3167
|
-
parts.push(`extras=${truncate(safeJsonStringify(extras), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
3168
|
-
}
|
|
3169
|
-
if (input.envelope.result !== undefined) {
|
|
3170
|
-
parts.push(`result=${truncate(safeJsonStringify(input.envelope.result), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
3171
|
-
}
|
|
3172
|
-
return {
|
|
3173
|
-
message: sbeUserMessage || msg || `Heybox API ${input.pathWithQuery} 请求失败`,
|
|
3174
|
-
verboseMessage: parts.join(' '),
|
|
3175
|
-
};
|
|
3176
|
-
}
|
|
3177
|
-
if (input.parseError) {
|
|
3178
|
-
const parseMsg = input.parseError instanceof Error ? input.parseError.message : String(input.parseError);
|
|
3179
|
-
parts.push(`parseError=${parseMsg}`);
|
|
3180
|
-
}
|
|
3181
|
-
parts.push(input.rawBody ? `body=${truncate(input.rawBody, ENVELOPE_BODY_PREVIEW_LENGTH)}` : 'body=(empty)');
|
|
3182
|
-
return {
|
|
3183
|
-
message: `Heybox API ${input.pathWithQuery} 请求失败`,
|
|
3184
|
-
verboseMessage: parts.join(' '),
|
|
3185
|
-
};
|
|
3186
|
-
}
|
|
3187
|
-
function readSbeUserMessage(result) {
|
|
3188
|
-
if (!result || typeof result !== 'object') {
|
|
3189
|
-
return '';
|
|
3190
|
-
}
|
|
3191
|
-
const sbe = result.sbe;
|
|
3192
|
-
if (!sbe || typeof sbe !== 'object') {
|
|
3193
|
-
return '';
|
|
3194
|
-
}
|
|
3195
|
-
const userMessage = sbe.user_message;
|
|
3196
|
-
return typeof userMessage === 'string' ? userMessage.trim() : '';
|
|
3197
|
-
}
|
|
3198
|
-
function truncate(value, max) {
|
|
3199
|
-
return value.length > max ? `${value.slice(0, max)}...(+${value.length - max} chars)` : value;
|
|
3200
|
-
}
|
|
3201
|
-
function safeJsonStringify(value) {
|
|
3202
|
-
try {
|
|
3203
|
-
return JSON.stringify(value);
|
|
3204
|
-
}
|
|
3205
|
-
catch {
|
|
3206
|
-
return String(value);
|
|
3207
|
-
}
|
|
3208
|
-
}
|
|
3209
|
-
|
|
3210
2936
|
async function getCDNUploadInfo(options, runtime = {}) {
|
|
3211
2937
|
const body = new URLSearchParams();
|
|
3212
2938
|
body.set('file_infos', JSON.stringify(options.fileInfos));
|
|
@@ -3228,17 +2954,17 @@ async function postCDNUploadCallback(options, runtime = {}) {
|
|
|
3228
2954
|
const query = options.isFinished ? '?is_finished=true' : '';
|
|
3229
2955
|
return postHeyboxApi(`/bbs/app/api/qcloud/cos/upload/callback/v2${query}`, body, options.session, runtime);
|
|
3230
2956
|
}
|
|
3231
|
-
async function postHeyboxApi(pathWithQuery, body, session, runtime) {
|
|
2957
|
+
async function postHeyboxApi(pathWithQuery, body, session$1, runtime) {
|
|
3232
2958
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3233
|
-
const context = createHeyboxOpenPlatformRequestContext(session, pathWithQuery, {
|
|
2959
|
+
const context = session.createHeyboxOpenPlatformRequestContext(session$1, pathWithQuery, {
|
|
3234
2960
|
contentType: 'application/x-www-form-urlencoded',
|
|
3235
2961
|
});
|
|
3236
|
-
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), {
|
|
3237
2963
|
method: 'POST',
|
|
3238
2964
|
headers: context.headers,
|
|
3239
2965
|
body: body.toString(),
|
|
3240
2966
|
});
|
|
3241
|
-
const result = await readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
2967
|
+
const result = await session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
3242
2968
|
return result;
|
|
3243
2969
|
}
|
|
3244
2970
|
|
|
@@ -3341,7 +3067,7 @@ async function createDefaultCosClient(uploadToken) {
|
|
|
3341
3067
|
};
|
|
3342
3068
|
}
|
|
3343
3069
|
async function loadCosConstructor() {
|
|
3344
|
-
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; });
|
|
3345
3071
|
return cosModule.default;
|
|
3346
3072
|
}
|
|
3347
3073
|
function formatSize(bytes) {
|
|
@@ -3400,7 +3126,7 @@ async function submitUserMiniprogramAudit$1(options, runtime = {}) {
|
|
|
3400
3126
|
}
|
|
3401
3127
|
async function postUserMiniprogramVersionForm(path, options, fields, runtime) {
|
|
3402
3128
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3403
|
-
const context = createHeyboxOpenPlatformRequestContext(options.session, path, {
|
|
3129
|
+
const context = session.createHeyboxOpenPlatformRequestContext(options.session, path, {
|
|
3404
3130
|
contentType: 'application/x-www-form-urlencoded',
|
|
3405
3131
|
});
|
|
3406
3132
|
const body = new URLSearchParams();
|
|
@@ -3408,12 +3134,12 @@ async function postUserMiniprogramVersionForm(path, options, fields, runtime) {
|
|
|
3408
3134
|
for (const [key, value] of Object.entries(fields)) {
|
|
3409
3135
|
body.set(key, value);
|
|
3410
3136
|
}
|
|
3411
|
-
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), {
|
|
3412
3138
|
method: 'POST',
|
|
3413
3139
|
headers: context.headers,
|
|
3414
3140
|
body: body.toString(),
|
|
3415
3141
|
});
|
|
3416
|
-
const result = await readHeyboxApiEnvelope(response, {
|
|
3142
|
+
const result = await session.readHeyboxApiEnvelope(response, {
|
|
3417
3143
|
pathWithQuery: path,
|
|
3418
3144
|
});
|
|
3419
3145
|
return result ?? {};
|
|
@@ -3764,6 +3490,8 @@ function suggestNextPatchVersion(version) {
|
|
|
3764
3490
|
|
|
3765
3491
|
function createRemoteApiClient(options) {
|
|
3766
3492
|
return {
|
|
3493
|
+
listDeveloperEntities: () => listDeveloperEntities(options),
|
|
3494
|
+
switchDeveloperEntity: (requestOptions) => switchDeveloperEntity(requestOptions, options),
|
|
3767
3495
|
getDeveloperAccessStatus: () => getDeveloperAccessStatus(options),
|
|
3768
3496
|
listUserMiniprograms: (requestOptions = {}) => listUserMiniprograms(requestOptions, options),
|
|
3769
3497
|
createUserMiniprogram: (requestOptions) => createUserMiniprogram(requestOptions, options),
|
|
@@ -3781,6 +3509,12 @@ function createRemoteApiClient(options) {
|
|
|
3781
3509
|
listUserMiniprogramVersions: (requestOptions) => listUserMiniprogramVersions(requestOptions, options),
|
|
3782
3510
|
};
|
|
3783
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
|
+
}
|
|
3784
3518
|
async function getDeveloperAccessStatus(runtime) {
|
|
3785
3519
|
return remoteGet(USER_MINIPROGRAM_ACCESS_STATUS_API_PATH, {}, runtime);
|
|
3786
3520
|
}
|
|
@@ -3831,30 +3565,36 @@ async function listUserMiniprogramVersions(options, runtime) {
|
|
|
3831
3565
|
}
|
|
3832
3566
|
async function remoteGet(path, query, runtime) {
|
|
3833
3567
|
const pathWithQuery = createPathWithQuery(path, query);
|
|
3834
|
-
const context = createHeyboxOpenPlatformRequestContext(runtime.session, pathWithQuery);
|
|
3568
|
+
const context = session.createHeyboxOpenPlatformRequestContext(runtime.session, pathWithQuery);
|
|
3835
3569
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3836
|
-
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
3570
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
3837
3571
|
method: 'GET',
|
|
3838
3572
|
headers: context.headers,
|
|
3839
3573
|
});
|
|
3840
3574
|
return readRequiredResult(response, pathWithQuery);
|
|
3841
3575
|
}
|
|
3842
|
-
async function remotePostForm(path, fields, runtime) {
|
|
3843
|
-
const context = createHeyboxOpenPlatformRequestContext(runtime.session, path, {
|
|
3576
|
+
async function remotePostForm(path, fields, runtime, options = {}) {
|
|
3577
|
+
const context = session.createHeyboxOpenPlatformRequestContext(runtime.session, path, {
|
|
3844
3578
|
contentType: 'application/x-www-form-urlencoded',
|
|
3845
3579
|
});
|
|
3846
3580
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
3847
|
-
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, path, context.platformParams), {
|
|
3581
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, path, context.platformParams), {
|
|
3848
3582
|
method: 'POST',
|
|
3849
3583
|
headers: context.headers,
|
|
3850
3584
|
body: createFormBody(fields),
|
|
3851
3585
|
});
|
|
3586
|
+
if (options.requireResult === false) {
|
|
3587
|
+
return readOptionalResult(response, path);
|
|
3588
|
+
}
|
|
3852
3589
|
return readRequiredResult(response, path);
|
|
3853
3590
|
}
|
|
3854
3591
|
async function readRequiredResult(response, pathWithQuery) {
|
|
3855
|
-
const result = await readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
3592
|
+
const result = await session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
3856
3593
|
return result;
|
|
3857
3594
|
}
|
|
3595
|
+
async function readOptionalResult(response, pathWithQuery) {
|
|
3596
|
+
return session.readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: false });
|
|
3597
|
+
}
|
|
3858
3598
|
function createPathWithQuery(path, query) {
|
|
3859
3599
|
const params = new URLSearchParams();
|
|
3860
3600
|
for (const [key, value] of Object.entries(query)) {
|
|
@@ -4004,6 +3744,12 @@ async function runRemoteCommand(options, runtime = {}) {
|
|
|
4004
3744
|
switch (options.command) {
|
|
4005
3745
|
case 'access':
|
|
4006
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);
|
|
4007
3753
|
case 'list':
|
|
4008
3754
|
return remoteList(options, context, runtime);
|
|
4009
3755
|
case 'create':
|
|
@@ -4035,6 +3781,9 @@ async function runRemoteCommand(options, runtime = {}) {
|
|
|
4035
3781
|
}
|
|
4036
3782
|
async function runRemoteDeployCommand(options, runtime) {
|
|
4037
3783
|
const logger = resolveRemoteLogger(options, runtime);
|
|
3784
|
+
const context = await createRemoteCommandContext(options, runtime);
|
|
3785
|
+
const miniProgramId = requireBinding(context);
|
|
3786
|
+
await assertBoundMiniProgramEntityMatchesCurrent(context, miniProgramId);
|
|
4038
3787
|
const deployRuntime = {
|
|
4039
3788
|
cwd: runtime.cwd,
|
|
4040
3789
|
fetchImpl: runtime.fetchImpl,
|
|
@@ -4099,6 +3848,8 @@ function adaptRemoteApiClient(api) {
|
|
|
4099
3848
|
updateAllowlist: ({ miniProgramId, heyboxIds }) => api.updatePreviewAllowlist({ mini_program_id: miniProgramId, heybox_ids: heyboxIds }),
|
|
4100
3849
|
listVersions: (miniProgramId) => api.listUserMiniprogramVersions({ mini_program_id: miniProgramId, offset: 0, limit: 50 }),
|
|
4101
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 }),
|
|
4102
3853
|
releaseVersion: ({ miniProgramId, version }) => api.releaseUserMiniprogramVersion({ mini_program_id: miniProgramId, version }),
|
|
4103
3854
|
withdrawVersion: ({ miniProgramId, reason, version }) => api.withdrawUserMiniprogramVersion({ mini_program_id: miniProgramId, version, reason }),
|
|
4104
3855
|
takeDown: (miniProgramId) => api.takeDownUserMiniprogram({ mini_program_id: miniProgramId }),
|
|
@@ -4119,6 +3870,60 @@ async function remoteAccess(options, context, runtime) {
|
|
|
4119
3870
|
}
|
|
4120
3871
|
return finishRemoteCommand(options, runtime, output);
|
|
4121
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
|
+
}
|
|
4122
3927
|
async function remoteList(options, context, runtime) {
|
|
4123
3928
|
const result = await context.api.listMiniPrograms({ keyword: options.keyword, status: options.status });
|
|
4124
3929
|
const items = Array.isArray(result.items) ? result.items : [];
|
|
@@ -4150,6 +3955,7 @@ async function remoteCreate(options, context, runtime) {
|
|
|
4150
3955
|
if (access.status !== 'approved') {
|
|
4151
3956
|
throw new Error(`当前 CLI 用户没有创建开发者用户小程序权限:${String(access.status ?? 'unknown')}`);
|
|
4152
3957
|
}
|
|
3958
|
+
await confirmCreateWithCurrentEntity(options, context, runtime);
|
|
4153
3959
|
const result = await context.api.createMiniProgram({ name, previewImageUrl });
|
|
4154
3960
|
const miniProgramId = requireMiniProgramId(result);
|
|
4155
3961
|
await writeBoundMiniProgramId(context.packageJson.projectRoot, miniProgramId, { force: options.forceBind });
|
|
@@ -4166,6 +3972,7 @@ async function remoteBind(options, context, runtime) {
|
|
|
4166
3972
|
}
|
|
4167
3973
|
const detail = await context.api.getMiniProgramDetail(miniProgramId);
|
|
4168
3974
|
const verifiedId = requireMiniProgramId(detail);
|
|
3975
|
+
await assertMiniProgramEntityMatchesCurrent(context, detail);
|
|
4169
3976
|
const changed = context.binding !== verifiedId;
|
|
4170
3977
|
if (changed) {
|
|
4171
3978
|
await writeBoundMiniProgramId(context.packageJson.projectRoot, verifiedId, { force: options.force });
|
|
@@ -4332,6 +4139,70 @@ function requireBinding(context) {
|
|
|
4332
4139
|
}
|
|
4333
4140
|
return context.binding;
|
|
4334
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
|
+
}
|
|
4335
4206
|
function requireMiniProgramId(result) {
|
|
4336
4207
|
const miniProgramId = result.mini_program_id;
|
|
4337
4208
|
if (typeof miniProgramId !== 'string' || !miniProgramId.trim()) {
|
|
@@ -4339,6 +4210,50 @@ function requireMiniProgramId(result) {
|
|
|
4339
4210
|
}
|
|
4340
4211
|
return miniProgramId.trim();
|
|
4341
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
|
+
}
|
|
4342
4257
|
function requireNonEmpty(value, message) {
|
|
4343
4258
|
const normalized = typeof value === 'string' ? value.trim() : '';
|
|
4344
4259
|
if (!normalized) {
|
|
@@ -4466,6 +4381,19 @@ function printMiniProgramDetail(logger, detail) {
|
|
|
4466
4381
|
logger.info(`Publish URL: ${detail.publish_url}`);
|
|
4467
4382
|
}
|
|
4468
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
|
+
}
|
|
4469
4397
|
function printAllowlist(logger, result) {
|
|
4470
4398
|
const items = Array.isArray(result.items) ? result.items : [];
|
|
4471
4399
|
logger.info(`Limit: ${readNumber(result.limit, 0)}`);
|