@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,10 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var promises = require('node:readline/promises');
|
|
3
4
|
var node_crypto = require('node:crypto');
|
|
4
5
|
var node_http = require('node:http');
|
|
5
|
-
var session = require('./session-
|
|
6
|
+
var session = require('./session-D7lF9mpd.cjs');
|
|
6
7
|
var browser = require('./browser-RAy8e8cV.cjs');
|
|
7
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-DuwxUSkq.cjs');
|
|
8
9
|
require('node:path');
|
|
9
10
|
require('fs');
|
|
10
11
|
require('constants');
|
|
@@ -134,6 +135,8 @@ function closeServer(server) {
|
|
|
134
135
|
});
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
const DEVELOPER_ENTITY_LIST_API_PATH = '/mall/developer/entity/list';
|
|
139
|
+
const DEVELOPER_ENTITY_SWITCH_API_PATH = '/mall/developer/entity/switch';
|
|
137
140
|
async function loginToHeybox(options = {}) {
|
|
138
141
|
const logger = options.logger ?? index.createCliLogger();
|
|
139
142
|
const waitForBrowserCallback = options.waitForBrowserCallback ?? waitForHeyboxBrowserCallback;
|
|
@@ -162,6 +165,7 @@ async function loginToHeybox(options = {}) {
|
|
|
162
165
|
const session$1 = session.createHeyboxAuthSession(payload, { ...options, loginBaseUrl });
|
|
163
166
|
await session.writeHeyboxAuthSession(session$1, options);
|
|
164
167
|
logger.success(`Heybox 登录成功:${session$1.heyboxId}`);
|
|
168
|
+
await selectDeveloperEntityAfterLogin(session$1, options, logger);
|
|
165
169
|
logger.debug(`cache: ${session.getAuthCacheFilePath(options)}`);
|
|
166
170
|
logger.info('验证命令: hb-sdk login status');
|
|
167
171
|
}
|
|
@@ -179,6 +183,9 @@ async function printLoginStatus(options = {}) {
|
|
|
179
183
|
logger.info(`heyboxId: ${status.heyboxId}`);
|
|
180
184
|
logger.info(`loginBaseUrl: ${status.loginBaseUrl}`);
|
|
181
185
|
logger.info(`loggedInAt: ${status.loggedInAt}`);
|
|
186
|
+
if (status.selectedEntity) {
|
|
187
|
+
logger.info(`selectedEntity: ${formatDeveloperEntity(status.selectedEntity)}`);
|
|
188
|
+
}
|
|
182
189
|
logger.debug(`cache: ${status.cacheFile}`);
|
|
183
190
|
}
|
|
184
191
|
async function clearLoginStatus(options = {}) {
|
|
@@ -187,6 +194,150 @@ async function clearLoginStatus(options = {}) {
|
|
|
187
194
|
logger.success('已清理 Heybox 登录态');
|
|
188
195
|
logger.debug(`cache: ${session.getAuthCacheFilePath(options)}`);
|
|
189
196
|
}
|
|
197
|
+
async function selectDeveloperEntityAfterLogin(session$1, options, logger) {
|
|
198
|
+
if (options.noSelectEntity) {
|
|
199
|
+
logger.info('已跳过开发者主体选择。后续可运行: hb-sdk remote entity switch <entity-id>');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const entities = await logger.task('读取开发者主体列表', () => listDeveloperEntities(session$1, options), {
|
|
203
|
+
successText: '已读取开发者主体列表',
|
|
204
|
+
});
|
|
205
|
+
if (entities.length === 0) {
|
|
206
|
+
logger.warn('当前账号未绑定开发者平台主体。');
|
|
207
|
+
logger.info('请先在开发者平台完成主体绑定,再运行 remote 命令。');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (entities.length === 1) {
|
|
211
|
+
const [entity] = entities;
|
|
212
|
+
if (!entity.isCurrent) {
|
|
213
|
+
await switchDeveloperEntity(session$1, entity, options);
|
|
214
|
+
await session.setSelectedDeveloperEntitySnapshot(entity, options);
|
|
215
|
+
logger.success(`已切换开发者主体:${formatDeveloperEntity(entity)}`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
await session.setSelectedDeveloperEntitySnapshot(entity, options);
|
|
219
|
+
logger.info(`当前开发者主体:${formatDeveloperEntity(entity)}`);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
printDeveloperEntityChoices(logger, entities);
|
|
223
|
+
const isTTY = options.isTTY ?? logger.isInteractive;
|
|
224
|
+
if (!isTTY) {
|
|
225
|
+
logger.warn('检测到多个开发者主体,非交互环境不会自动切换。');
|
|
226
|
+
logger.info('请运行: hb-sdk remote entity switch <entity-id>');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const selected = options.promptSelectEntity
|
|
230
|
+
? await options.promptSelectEntity(entities)
|
|
231
|
+
: await promptSelectDeveloperEntity(entities, options);
|
|
232
|
+
if (!selected) {
|
|
233
|
+
throw new Error('必须选择一个开发者主体;如需跳过,请显式传 --no-select-entity');
|
|
234
|
+
}
|
|
235
|
+
await switchDeveloperEntity(session$1, selected, options);
|
|
236
|
+
await session.setSelectedDeveloperEntitySnapshot(selected, options);
|
|
237
|
+
logger.success(`已切换开发者主体:${formatDeveloperEntity(selected)}`);
|
|
238
|
+
}
|
|
239
|
+
async function listDeveloperEntities(session, options) {
|
|
240
|
+
const result = await requestDeveloperEntityApi(DEVELOPER_ENTITY_LIST_API_PATH, 'GET', session, options);
|
|
241
|
+
const rawItems = readDeveloperEntityItems(result);
|
|
242
|
+
return rawItems.map(normalizeDeveloperEntity).filter((item) => Boolean(item));
|
|
243
|
+
}
|
|
244
|
+
async function switchDeveloperEntity(session, entity, options) {
|
|
245
|
+
await requestDeveloperEntityApi(DEVELOPER_ENTITY_SWITCH_API_PATH, 'POST', session, options, {
|
|
246
|
+
entity_id: entity.entityId,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async function requestDeveloperEntityApi(path, method, session$1, options, fields = {}) {
|
|
250
|
+
const apiBaseUrl = session.resolveHeyboxApiBaseUrl(options);
|
|
251
|
+
const context = session.createHeyboxOpenPlatformRequestContext(session$1, path, {
|
|
252
|
+
...(method === 'POST' ? { contentType: 'application/x-www-form-urlencoded' } : {}),
|
|
253
|
+
});
|
|
254
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
255
|
+
const response = await fetchImpl(session.createHeyboxApiUrl(apiBaseUrl, path, context.platformParams), {
|
|
256
|
+
method,
|
|
257
|
+
headers: context.headers,
|
|
258
|
+
...(method === 'POST' ? { body: new URLSearchParams(stringifyFormFields(fields)).toString() } : {}),
|
|
259
|
+
});
|
|
260
|
+
return session.readHeyboxApiEnvelope(response, { pathWithQuery: path, requireResult: method === 'GET' });
|
|
261
|
+
}
|
|
262
|
+
function stringifyFormFields(fields) {
|
|
263
|
+
return Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, String(value)]));
|
|
264
|
+
}
|
|
265
|
+
function readDeveloperEntityItems(result) {
|
|
266
|
+
if (Array.isArray(result)) {
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
if (!isRecord(result)) {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
if (Array.isArray(result.items)) {
|
|
273
|
+
return result.items;
|
|
274
|
+
}
|
|
275
|
+
if (Array.isArray(result.list)) {
|
|
276
|
+
return result.list;
|
|
277
|
+
}
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
function normalizeDeveloperEntity(value) {
|
|
281
|
+
if (!isRecord(value)) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
const entityId = readPositiveInteger(value.entity_id ?? value.entityId);
|
|
285
|
+
if (entityId === undefined) {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
const ownerHeyboxId = readPositiveInteger(value.owner_heybox_id ?? value.ownerHeyboxId);
|
|
289
|
+
return {
|
|
290
|
+
entityId,
|
|
291
|
+
entityName: readNonEmptyString(value.entity_name ?? value.entityName) ?? `主体 ${entityId}`,
|
|
292
|
+
...(ownerHeyboxId === undefined ? {} : { ownerHeyboxId }),
|
|
293
|
+
isCurrent: value.is_current === true || value.isCurrent === true,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function readPositiveInteger(value) {
|
|
297
|
+
const parsed = typeof value === 'number' ? value : typeof value === 'string' && /^\d+$/.test(value.trim()) ? Number(value.trim()) : NaN;
|
|
298
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
299
|
+
}
|
|
300
|
+
function readNonEmptyString(value) {
|
|
301
|
+
const normalized = typeof value === 'string' ? value.trim() : '';
|
|
302
|
+
return normalized || undefined;
|
|
303
|
+
}
|
|
304
|
+
function printDeveloperEntityChoices(logger, entities) {
|
|
305
|
+
logger.info('可用开发者主体:');
|
|
306
|
+
entities.forEach((entity, index) => {
|
|
307
|
+
logger.info(`${index + 1}. ${formatDeveloperEntity(entity)}${entity.isCurrent ? ' (current)' : ''}`);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
async function promptSelectDeveloperEntity(entities, options) {
|
|
311
|
+
const input = options.stdin ?? process.stdin;
|
|
312
|
+
const output = options.stderr ?? process.stderr;
|
|
313
|
+
const rl = promises.createInterface({ input, output: output });
|
|
314
|
+
try {
|
|
315
|
+
for (;;) {
|
|
316
|
+
const answer = (await rl.question('请选择开发者主体序号或 entity_id: ')).trim();
|
|
317
|
+
const selected = findDeveloperEntityChoice(entities, answer);
|
|
318
|
+
if (selected) {
|
|
319
|
+
return selected;
|
|
320
|
+
}
|
|
321
|
+
output.write('输入无效,请重新选择。\n');
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
rl.close();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function findDeveloperEntityChoice(entities, answer) {
|
|
329
|
+
const index = readPositiveInteger(answer);
|
|
330
|
+
if (index !== undefined && index <= entities.length) {
|
|
331
|
+
return entities[index - 1];
|
|
332
|
+
}
|
|
333
|
+
return entities.find((entity) => String(entity.entityId) === answer);
|
|
334
|
+
}
|
|
335
|
+
function formatDeveloperEntity(entity) {
|
|
336
|
+
return `${entity.entityName} (ID: ${entity.entityId}${entity.ownerHeyboxId === undefined ? '' : `, owner: ${entity.ownerHeyboxId}`})`;
|
|
337
|
+
}
|
|
338
|
+
function isRecord(value) {
|
|
339
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
340
|
+
}
|
|
190
341
|
|
|
191
342
|
exports.clearLoginStatus = clearLoginStatus;
|
|
192
343
|
exports.loginToHeybox = loginToHeybox;
|