@heybox/hb-sdk 0.2.0-alpha.2 → 0.3.1
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 +2 -2
- package/dist/cli.cjs +773 -473
- package/dist/devtools/mock-host/main.js +336 -203
- package/dist/index.cjs.js +2 -14
- package/dist/index.esm.js +3 -2
- package/dist/miniapp-publish.cjs.js +6 -5
- package/dist/miniapp-publish.esm.js +6 -5
- package/dist/templates/vue3-vite-ts/README.md.ejs +2 -0
- package/dist/templates/vue3-vite-ts/package.json.ejs +5 -0
- package/dist/vite.cjs.js +54 -30
- package/dist/vite.esm.js +55 -31
- package/package.json +3 -4
- package/skill/references/api-root.md +14 -87
- package/skill/references/cli.md +2 -0
- package/skill/scripts/skill-metadata.mjs +4 -1
- package/skill/skill.json +4 -4
- package/types/core/client.d.ts +7 -16
- package/types/index.d.ts +2 -6
- package/types/miniapp-manifest/index.d.ts +2 -0
- package/types/miniapp-manifest/node.d.ts +1 -0
- package/types/miniapp-manifest/schema.d.ts +14 -0
- package/types/miniapp-publish/index.d.ts +1 -1
- package/types/skill-metadata.d.ts +6 -0
package/dist/cli.cjs
CHANGED
|
@@ -22,14 +22,14 @@ var require$$4$3 = require('https');
|
|
|
22
22
|
var require$$5$2 = require('zlib');
|
|
23
23
|
var require$$1$4 = require('querystring');
|
|
24
24
|
var require$$3$3 = require('tls');
|
|
25
|
-
var
|
|
25
|
+
var node_crypto = require('node:crypto');
|
|
26
26
|
var node_url = require('node:url');
|
|
27
27
|
var net = require('node:net');
|
|
28
28
|
var os = require('node:os');
|
|
29
|
+
var node_http = require('node:http');
|
|
29
30
|
var process$1 = require('node:process');
|
|
30
31
|
var node_buffer = require('node:buffer');
|
|
31
32
|
var node_util = require('node:util');
|
|
32
|
-
var node_crypto = require('node:crypto');
|
|
33
33
|
|
|
34
34
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
35
35
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -5162,15 +5162,55 @@ function quoteShellPath(value) {
|
|
|
5162
5162
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
5163
5163
|
}
|
|
5164
5164
|
|
|
5165
|
+
const MINIAPP_TEMPLATE_VERSION = '0.0.0';
|
|
5166
|
+
const PUBLISH_VERSION_RE = /^\d+\.\d+\.\d+$/;
|
|
5167
|
+
function isValidMiniappManifestVersion(version) {
|
|
5168
|
+
return PUBLISH_VERSION_RE.test(String(version || '').trim());
|
|
5169
|
+
}
|
|
5170
|
+
function parseMiniappManifestJson(raw, sourceLabel = 'manifest.json') {
|
|
5171
|
+
const hadBom = raw.charCodeAt(0) === 0xfeff;
|
|
5172
|
+
const text = hadBom ? raw.slice(1) : raw;
|
|
5173
|
+
let parsed;
|
|
5174
|
+
try {
|
|
5175
|
+
parsed = JSON.parse(text);
|
|
5176
|
+
}
|
|
5177
|
+
catch (error) {
|
|
5178
|
+
throw new Error(`${sourceLabel} 不是合法 JSON:${formatReason(error)}`);
|
|
5179
|
+
}
|
|
5180
|
+
if (!isManifestRecord(parsed)) {
|
|
5181
|
+
throw new Error(`${sourceLabel} 必须是 JSON 对象`);
|
|
5182
|
+
}
|
|
5183
|
+
return {
|
|
5184
|
+
manifest: {
|
|
5185
|
+
version: parsed.version,
|
|
5186
|
+
},
|
|
5187
|
+
hadBom,
|
|
5188
|
+
};
|
|
5189
|
+
}
|
|
5190
|
+
function validateMiniappManifestForDeploy(manifest) {
|
|
5191
|
+
if (manifest.version === MINIAPP_TEMPLATE_VERSION) {
|
|
5192
|
+
throw new Error('manifest.version 仍是模板默认的 0.0.0,请改成实际版本号后再发布');
|
|
5193
|
+
}
|
|
5194
|
+
if (typeof manifest.version !== 'string' || !isValidMiniappManifestVersion(manifest.version)) {
|
|
5195
|
+
throw new Error(`manifest.version 格式错误,必须是 x.y.z:${String(manifest.version)}`);
|
|
5196
|
+
}
|
|
5197
|
+
return manifest.version;
|
|
5198
|
+
}
|
|
5199
|
+
function isManifestRecord(value) {
|
|
5200
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5201
|
+
}
|
|
5202
|
+
function formatReason(error) {
|
|
5203
|
+
if (error instanceof Error && error.message) {
|
|
5204
|
+
return error.message;
|
|
5205
|
+
}
|
|
5206
|
+
return String(error);
|
|
5207
|
+
}
|
|
5208
|
+
|
|
5165
5209
|
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
5166
5210
|
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
5167
5211
|
const PUBLISH_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/publish';
|
|
5168
|
-
const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
5169
5212
|
const FNV_OFFSET = 0x811c9dc5;
|
|
5170
5213
|
const FNV_PRIME = 0x01000193;
|
|
5171
|
-
function isValidVersion(version) {
|
|
5172
|
-
return VERSION_PATTERN.test(String(version || '').trim());
|
|
5173
|
-
}
|
|
5174
5214
|
function normalizeRelativePath(relativePath) {
|
|
5175
5215
|
return String(relativePath || '')
|
|
5176
5216
|
.replace(/\\/g, '/')
|
|
@@ -6596,30 +6636,47 @@ function requireUtimes () {
|
|
|
6596
6636
|
const u = requireUniversalify().fromPromise;
|
|
6597
6637
|
|
|
6598
6638
|
async function utimesMillis (path, atime, mtime) {
|
|
6599
|
-
// if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
|
|
6600
6639
|
const fd = await fs.open(path, 'r+');
|
|
6601
6640
|
|
|
6602
|
-
let
|
|
6641
|
+
let error = null;
|
|
6603
6642
|
|
|
6604
6643
|
try {
|
|
6605
6644
|
await fs.futimes(fd, atime, mtime);
|
|
6645
|
+
} catch (futimesErr) {
|
|
6646
|
+
error = futimesErr;
|
|
6606
6647
|
} finally {
|
|
6607
6648
|
try {
|
|
6608
6649
|
await fs.close(fd);
|
|
6609
|
-
} catch (
|
|
6610
|
-
|
|
6650
|
+
} catch (closeErr) {
|
|
6651
|
+
if (!error) error = closeErr;
|
|
6611
6652
|
}
|
|
6612
6653
|
}
|
|
6613
6654
|
|
|
6614
|
-
if (
|
|
6615
|
-
throw
|
|
6655
|
+
if (error) {
|
|
6656
|
+
throw error
|
|
6616
6657
|
}
|
|
6617
6658
|
}
|
|
6618
6659
|
|
|
6619
6660
|
function utimesMillisSync (path, atime, mtime) {
|
|
6620
6661
|
const fd = fs.openSync(path, 'r+');
|
|
6621
|
-
|
|
6622
|
-
|
|
6662
|
+
|
|
6663
|
+
let error = null;
|
|
6664
|
+
|
|
6665
|
+
try {
|
|
6666
|
+
fs.futimesSync(fd, atime, mtime);
|
|
6667
|
+
} catch (futimesErr) {
|
|
6668
|
+
error = futimesErr;
|
|
6669
|
+
} finally {
|
|
6670
|
+
try {
|
|
6671
|
+
fs.closeSync(fd);
|
|
6672
|
+
} catch (closeErr) {
|
|
6673
|
+
if (!error) error = closeErr;
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
|
|
6677
|
+
if (error) {
|
|
6678
|
+
throw error
|
|
6679
|
+
}
|
|
6623
6680
|
}
|
|
6624
6681
|
|
|
6625
6682
|
utimes = {
|
|
@@ -7383,14 +7440,14 @@ function requireLink () {
|
|
|
7383
7440
|
async function createLink (srcpath, dstpath) {
|
|
7384
7441
|
let dstStat;
|
|
7385
7442
|
try {
|
|
7386
|
-
dstStat = await fs.lstat(dstpath);
|
|
7443
|
+
dstStat = await fs.lstat(dstpath, { bigint: true });
|
|
7387
7444
|
} catch {
|
|
7388
7445
|
// ignore error
|
|
7389
7446
|
}
|
|
7390
7447
|
|
|
7391
7448
|
let srcStat;
|
|
7392
7449
|
try {
|
|
7393
|
-
srcStat = await fs.lstat(srcpath);
|
|
7450
|
+
srcStat = await fs.lstat(srcpath, { bigint: true });
|
|
7394
7451
|
} catch (err) {
|
|
7395
7452
|
err.message = err.message.replace('lstat', 'ensureLink');
|
|
7396
7453
|
throw err
|
|
@@ -7412,11 +7469,11 @@ function requireLink () {
|
|
|
7412
7469
|
function createLinkSync (srcpath, dstpath) {
|
|
7413
7470
|
let dstStat;
|
|
7414
7471
|
try {
|
|
7415
|
-
dstStat = fs.lstatSync(dstpath);
|
|
7472
|
+
dstStat = fs.lstatSync(dstpath, { bigint: true });
|
|
7416
7473
|
} catch {}
|
|
7417
7474
|
|
|
7418
7475
|
try {
|
|
7419
|
-
const srcStat = fs.lstatSync(srcpath);
|
|
7476
|
+
const srcStat = fs.lstatSync(srcpath, { bigint: true });
|
|
7420
7477
|
if (dstStat && areIdentical(srcStat, dstStat)) return
|
|
7421
7478
|
} catch (err) {
|
|
7422
7479
|
err.message = err.message.replace('lstat', 'ensureLink');
|
|
@@ -7620,18 +7677,18 @@ function requireSymlink () {
|
|
|
7620
7677
|
// (standard symlink behavior) or fall back to cwd if that doesn't exist
|
|
7621
7678
|
let srcStat;
|
|
7622
7679
|
if (path.isAbsolute(srcpath)) {
|
|
7623
|
-
srcStat = await fs.stat(srcpath);
|
|
7680
|
+
srcStat = await fs.stat(srcpath, { bigint: true });
|
|
7624
7681
|
} else {
|
|
7625
7682
|
const dstdir = path.dirname(dstpath);
|
|
7626
7683
|
const relativeToDst = path.join(dstdir, srcpath);
|
|
7627
7684
|
try {
|
|
7628
|
-
srcStat = await fs.stat(relativeToDst);
|
|
7685
|
+
srcStat = await fs.stat(relativeToDst, { bigint: true });
|
|
7629
7686
|
} catch {
|
|
7630
|
-
srcStat = await fs.stat(srcpath);
|
|
7687
|
+
srcStat = await fs.stat(srcpath, { bigint: true });
|
|
7631
7688
|
}
|
|
7632
7689
|
}
|
|
7633
7690
|
|
|
7634
|
-
const dstStat = await fs.stat(dstpath);
|
|
7691
|
+
const dstStat = await fs.stat(dstpath, { bigint: true });
|
|
7635
7692
|
if (areIdentical(srcStat, dstStat)) return
|
|
7636
7693
|
}
|
|
7637
7694
|
|
|
@@ -7657,18 +7714,18 @@ function requireSymlink () {
|
|
|
7657
7714
|
// (standard symlink behavior) or fall back to cwd if that doesn't exist
|
|
7658
7715
|
let srcStat;
|
|
7659
7716
|
if (path.isAbsolute(srcpath)) {
|
|
7660
|
-
srcStat = fs.statSync(srcpath);
|
|
7717
|
+
srcStat = fs.statSync(srcpath, { bigint: true });
|
|
7661
7718
|
} else {
|
|
7662
7719
|
const dstdir = path.dirname(dstpath);
|
|
7663
7720
|
const relativeToDst = path.join(dstdir, srcpath);
|
|
7664
7721
|
try {
|
|
7665
|
-
srcStat = fs.statSync(relativeToDst);
|
|
7722
|
+
srcStat = fs.statSync(relativeToDst, { bigint: true });
|
|
7666
7723
|
} catch {
|
|
7667
|
-
srcStat = fs.statSync(srcpath);
|
|
7724
|
+
srcStat = fs.statSync(srcpath, { bigint: true });
|
|
7668
7725
|
}
|
|
7669
7726
|
}
|
|
7670
7727
|
|
|
7671
|
-
const dstStat = fs.statSync(dstpath);
|
|
7728
|
+
const dstStat = fs.statSync(dstpath, { bigint: true });
|
|
7672
7729
|
if (areIdentical(srcStat, dstStat)) return
|
|
7673
7730
|
}
|
|
7674
7731
|
|
|
@@ -8224,7 +8281,7 @@ function createCookie(name, value) {
|
|
|
8224
8281
|
return `${name}=${value}`;
|
|
8225
8282
|
}
|
|
8226
8283
|
function isHeyboxAuthSession(value) {
|
|
8227
|
-
if (!isRecord$
|
|
8284
|
+
if (!isRecord$2(value)) {
|
|
8228
8285
|
return false;
|
|
8229
8286
|
}
|
|
8230
8287
|
return (typeof value.heyboxId === 'string' &&
|
|
@@ -8233,7 +8290,7 @@ function isHeyboxAuthSession(value) {
|
|
|
8233
8290
|
typeof value.cookieHeader === 'string' &&
|
|
8234
8291
|
typeof value.loggedInAt === 'string');
|
|
8235
8292
|
}
|
|
8236
|
-
function isRecord$
|
|
8293
|
+
function isRecord$2(value) {
|
|
8237
8294
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
8238
8295
|
}
|
|
8239
8296
|
|
|
@@ -59248,11 +59305,6 @@ function requireCompile () {
|
|
|
59248
59305
|
, defaultsHash = {}
|
|
59249
59306
|
, customRules = [];
|
|
59250
59307
|
|
|
59251
|
-
function patternCode(i, patterns) {
|
|
59252
|
-
var regExpCode = opts.regExp ? 'regExp' : 'new RegExp';
|
|
59253
|
-
return 'var pattern' + i + ' = ' + regExpCode + '(' + util.toQuotedString(patterns[i]) + ');';
|
|
59254
|
-
}
|
|
59255
|
-
|
|
59256
59308
|
root = root || { schema: schema, refVal: refVal, refs: refs };
|
|
59257
59309
|
|
|
59258
59310
|
var c = checkCompiling.call(this, schema, root, baseId);
|
|
@@ -59339,7 +59391,6 @@ function requireCompile () {
|
|
|
59339
59391
|
'equal',
|
|
59340
59392
|
'ucs2length',
|
|
59341
59393
|
'ValidationError',
|
|
59342
|
-
'regExp',
|
|
59343
59394
|
sourceCode
|
|
59344
59395
|
);
|
|
59345
59396
|
|
|
@@ -59353,8 +59404,7 @@ function requireCompile () {
|
|
|
59353
59404
|
customRules,
|
|
59354
59405
|
equal,
|
|
59355
59406
|
ucs2length,
|
|
59356
|
-
ValidationError
|
|
59357
|
-
opts.regExp
|
|
59407
|
+
ValidationError
|
|
59358
59408
|
);
|
|
59359
59409
|
|
|
59360
59410
|
refVal[0] = validate;
|
|
@@ -59571,6 +59621,11 @@ function requireCompile () {
|
|
|
59571
59621
|
}
|
|
59572
59622
|
|
|
59573
59623
|
|
|
59624
|
+
function patternCode(i, patterns) {
|
|
59625
|
+
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');';
|
|
59626
|
+
}
|
|
59627
|
+
|
|
59628
|
+
|
|
59574
59629
|
function defaultCode(i) {
|
|
59575
59630
|
return 'var default' + i + ' = defaults[' + i + '];';
|
|
59576
59631
|
}
|
|
@@ -61594,7 +61649,6 @@ function requirePattern () {
|
|
|
61594
61649
|
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
|
61595
61650
|
var $breakOnError = !it.opts.allErrors;
|
|
61596
61651
|
var $data = 'data' + ($dataLvl || '');
|
|
61597
|
-
var $valid = 'valid' + $lvl;
|
|
61598
61652
|
var $isData = it.opts.$data && $schema && $schema.$data,
|
|
61599
61653
|
$schemaValue;
|
|
61600
61654
|
if ($isData) {
|
|
@@ -61603,21 +61657,12 @@ function requirePattern () {
|
|
|
61603
61657
|
} else {
|
|
61604
61658
|
$schemaValue = $schema;
|
|
61605
61659
|
}
|
|
61606
|
-
var $
|
|
61660
|
+
var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema);
|
|
61661
|
+
out += 'if ( ';
|
|
61607
61662
|
if ($isData) {
|
|
61608
|
-
out += '
|
|
61609
|
-
if ($isData) {
|
|
61610
|
-
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || ';
|
|
61611
|
-
}
|
|
61612
|
-
out += ' !' + ($valid) + ') {';
|
|
61613
|
-
} else {
|
|
61614
|
-
var $regexp = it.usePattern($schema);
|
|
61615
|
-
out += ' if ( ';
|
|
61616
|
-
if ($isData) {
|
|
61617
|
-
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || ';
|
|
61618
|
-
}
|
|
61619
|
-
out += ' !' + ($regexp) + '.test(' + ($data) + ') ) {';
|
|
61663
|
+
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || ';
|
|
61620
61664
|
}
|
|
61665
|
+
out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { ';
|
|
61621
61666
|
var $$outStack = $$outStack || [];
|
|
61622
61667
|
$$outStack.push(out);
|
|
61623
61668
|
out = ''; /* istanbul ignore else */
|
|
@@ -75090,8 +75135,105 @@ function requireCosNodejsSdkV5 () {
|
|
|
75090
75135
|
var cosNodejsSdkV5Exports = requireCosNodejsSdkV5();
|
|
75091
75136
|
var COS = /*@__PURE__*/getDefaultExportFromCjs(cosNodejsSdkV5Exports);
|
|
75092
75137
|
|
|
75138
|
+
const SIGN_VERSION = '999.0.4';
|
|
75139
|
+
const SIGN_CHARSET = 'AB45STUVWZEFGJ6CH01D237IXYPQRKLMN89';
|
|
75140
|
+
function createHeyboxOpenPlatformSignParams(pathname, options = {}) {
|
|
75141
|
+
const now = options.now ?? new Date();
|
|
75142
|
+
const time = Math.trunc(now.getTime() / 1000);
|
|
75143
|
+
const nonce = options.nonce ?? md5(`${time}${Date.now()}${node_crypto.randomBytes(16).toString('hex')}`).toUpperCase();
|
|
75144
|
+
return {
|
|
75145
|
+
version: SIGN_VERSION,
|
|
75146
|
+
hkey: generateSignature(pathname, time + 1, nonce),
|
|
75147
|
+
_time: time,
|
|
75148
|
+
nonce,
|
|
75149
|
+
};
|
|
75150
|
+
}
|
|
75151
|
+
function generateSignature(path, time, nonce) {
|
|
75152
|
+
const normalizedPath = `/${path
|
|
75153
|
+
.split('/')
|
|
75154
|
+
.filter(Boolean)
|
|
75155
|
+
.join('/')}/`;
|
|
75156
|
+
const transformedTime = transformWithOffset(String(time), SIGN_CHARSET, -2);
|
|
75157
|
+
const transformedPath = transform(normalizedPath, SIGN_CHARSET);
|
|
75158
|
+
const transformedNonce = transform(nonce, SIGN_CHARSET);
|
|
75159
|
+
const combined = interleave([transformedTime, transformedPath, transformedNonce]).slice(0, 20);
|
|
75160
|
+
const hash = md5(combined);
|
|
75161
|
+
let sign = `${mixColumns(hash.slice(-6).split('').map((char) => char.charCodeAt(0))).reduce((sum, value) => sum + value, 0) % 100}`;
|
|
75162
|
+
sign = sign.length < 2 ? `0${sign}` : sign;
|
|
75163
|
+
return `${transformWithOffset(hash.substring(0, 5), SIGN_CHARSET, -4)}${sign}`;
|
|
75164
|
+
}
|
|
75165
|
+
function transformWithOffset(str, charset, offset) {
|
|
75166
|
+
return transform(str, charset.slice(0, offset));
|
|
75167
|
+
}
|
|
75168
|
+
function transform(str, charset) {
|
|
75169
|
+
let output = '';
|
|
75170
|
+
for (let index = 0; index < str.length; index += 1) {
|
|
75171
|
+
output += charset[str.charCodeAt(index) % charset.length];
|
|
75172
|
+
}
|
|
75173
|
+
return output;
|
|
75174
|
+
}
|
|
75175
|
+
function interleave(strings) {
|
|
75176
|
+
let output = '';
|
|
75177
|
+
const maxLength = Math.max(...strings.map((str) => str.length));
|
|
75178
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
75179
|
+
for (const str of strings) {
|
|
75180
|
+
if (index < str.length) {
|
|
75181
|
+
output += str[index];
|
|
75182
|
+
}
|
|
75183
|
+
}
|
|
75184
|
+
}
|
|
75185
|
+
return output;
|
|
75186
|
+
}
|
|
75187
|
+
function mixColumns(column) {
|
|
75188
|
+
const output = [...column];
|
|
75189
|
+
output[0] = multiplyE(column[0]) ^ multiply4(column[1]) ^ multiply3(column[2]) ^ multiply2(column[3]);
|
|
75190
|
+
output[1] = multiply2(column[0]) ^ multiplyE(column[1]) ^ multiply4(column[2]) ^ multiply3(column[3]);
|
|
75191
|
+
output[2] = multiply3(column[0]) ^ multiply2(column[1]) ^ multiplyE(column[2]) ^ multiply4(column[3]);
|
|
75192
|
+
output[3] = multiply4(column[0]) ^ multiply3(column[1]) ^ multiply2(column[2]) ^ multiplyE(column[3]);
|
|
75193
|
+
return output;
|
|
75194
|
+
}
|
|
75195
|
+
function multiply1(value) {
|
|
75196
|
+
if (value & 0x80) {
|
|
75197
|
+
return ((value << 1) ^ 0x1b) & 0xff;
|
|
75198
|
+
}
|
|
75199
|
+
return value << 1;
|
|
75200
|
+
}
|
|
75201
|
+
function multiply2(value) {
|
|
75202
|
+
return multiply1(value) ^ value;
|
|
75203
|
+
}
|
|
75204
|
+
function multiply3(value) {
|
|
75205
|
+
return multiply2(multiply1(value));
|
|
75206
|
+
}
|
|
75207
|
+
function multiply4(value) {
|
|
75208
|
+
return multiply3(multiply2(multiply1(value)));
|
|
75209
|
+
}
|
|
75210
|
+
function multiplyE(value) {
|
|
75211
|
+
return multiply4(value) ^ multiply3(value) ^ multiply2(value);
|
|
75212
|
+
}
|
|
75213
|
+
function md5(input) {
|
|
75214
|
+
return node_crypto.createHash('md5').update(input).digest('hex');
|
|
75215
|
+
}
|
|
75216
|
+
|
|
75217
|
+
const DEFAULT_PLATFORM_PARAMS = {
|
|
75218
|
+
os_type: 'web',
|
|
75219
|
+
app: 'heybox',
|
|
75220
|
+
x_client_type: 'web',
|
|
75221
|
+
x_os_type: 'Mac',
|
|
75222
|
+
x_app: 'heybox',
|
|
75223
|
+
x_client_version: '999.999.999',
|
|
75224
|
+
};
|
|
75093
75225
|
const HEYBOX_API_BASE_URL = 'https://api.xiaoheihe.cn';
|
|
75094
75226
|
const HEYBOX_WEB_REFERER = 'https://www.xiaoheihe.cn/';
|
|
75227
|
+
function resolveHeyboxId(session) {
|
|
75228
|
+
if (session.heyboxId.trim()) {
|
|
75229
|
+
return session.heyboxId.trim();
|
|
75230
|
+
}
|
|
75231
|
+
return session.cookieHeader
|
|
75232
|
+
.split(';')
|
|
75233
|
+
.map((part) => part.trim())
|
|
75234
|
+
.find((part) => part.startsWith('heybox_id='))
|
|
75235
|
+
?.slice('heybox_id='.length);
|
|
75236
|
+
}
|
|
75095
75237
|
function createHeyboxAuthHeaders(session, options = {}) {
|
|
75096
75238
|
return {
|
|
75097
75239
|
Cookie: session.cookieHeader,
|
|
@@ -75099,6 +75241,94 @@ function createHeyboxAuthHeaders(session, options = {}) {
|
|
|
75099
75241
|
...(options.contentType ? { 'Content-Type': options.contentType } : {}),
|
|
75100
75242
|
};
|
|
75101
75243
|
}
|
|
75244
|
+
function createHeyboxRequestContext(session, options = {}) {
|
|
75245
|
+
const heyboxId = resolveHeyboxId(session);
|
|
75246
|
+
return {
|
|
75247
|
+
baseUrl: HEYBOX_API_BASE_URL,
|
|
75248
|
+
headers: createHeyboxAuthHeaders(session, options),
|
|
75249
|
+
platformParams: {
|
|
75250
|
+
...DEFAULT_PLATFORM_PARAMS,
|
|
75251
|
+
...options.platformParams,
|
|
75252
|
+
...(heyboxId ? { heybox_id: heyboxId } : {}),
|
|
75253
|
+
},
|
|
75254
|
+
};
|
|
75255
|
+
}
|
|
75256
|
+
function createHeyboxOpenPlatformRequestContext(session, pathWithQuery, options = {}) {
|
|
75257
|
+
return createHeyboxRequestContext(session, {
|
|
75258
|
+
...options,
|
|
75259
|
+
platformParams: {
|
|
75260
|
+
x_app: 'heybox_website',
|
|
75261
|
+
...createHeyboxOpenPlatformSignParams(getApiPathname(pathWithQuery)),
|
|
75262
|
+
...options.platformParams,
|
|
75263
|
+
},
|
|
75264
|
+
});
|
|
75265
|
+
}
|
|
75266
|
+
function createHeyboxApiUrl(baseUrl, pathWithQuery, params) {
|
|
75267
|
+
const url = new URL(pathWithQuery, baseUrl);
|
|
75268
|
+
for (const [key, value] of Object.entries(params)) {
|
|
75269
|
+
if (value !== '') {
|
|
75270
|
+
url.searchParams.set(key, String(value));
|
|
75271
|
+
}
|
|
75272
|
+
}
|
|
75273
|
+
return url.toString();
|
|
75274
|
+
}
|
|
75275
|
+
function getApiPathname(pathWithQuery) {
|
|
75276
|
+
return new URL(pathWithQuery, HEYBOX_API_BASE_URL).pathname;
|
|
75277
|
+
}
|
|
75278
|
+
const ENVELOPE_BODY_PREVIEW_LENGTH = 1000;
|
|
75279
|
+
async function readHeyboxApiEnvelope(response, options) {
|
|
75280
|
+
const rawBody = await response.text();
|
|
75281
|
+
let envelope = null;
|
|
75282
|
+
let parseError = null;
|
|
75283
|
+
if (rawBody) {
|
|
75284
|
+
try {
|
|
75285
|
+
envelope = JSON.parse(rawBody);
|
|
75286
|
+
}
|
|
75287
|
+
catch (error) {
|
|
75288
|
+
parseError = error;
|
|
75289
|
+
}
|
|
75290
|
+
}
|
|
75291
|
+
const envelopeOk = envelope?.status === 'ok' && (!options.requireResult || envelope?.result !== undefined);
|
|
75292
|
+
if (response.ok && envelopeOk) {
|
|
75293
|
+
return envelope.result;
|
|
75294
|
+
}
|
|
75295
|
+
throw new Error(formatHeyboxEnvelopeError({ response, envelope, parseError, rawBody, pathWithQuery: options.pathWithQuery }));
|
|
75296
|
+
}
|
|
75297
|
+
function formatHeyboxEnvelopeError(input) {
|
|
75298
|
+
const parts = [`Heybox API ${input.pathWithQuery} failed`, `HTTP ${input.response.status}`];
|
|
75299
|
+
if (input.envelope) {
|
|
75300
|
+
const msg = typeof input.envelope.msg === 'string' ? input.envelope.msg.trim() : '';
|
|
75301
|
+
parts.push(`msg=${msg || '(empty)'}`);
|
|
75302
|
+
if (typeof input.envelope.status === 'string') {
|
|
75303
|
+
parts.push(`envelope.status=${input.envelope.status}`);
|
|
75304
|
+
}
|
|
75305
|
+
const { status: _s, msg: _m, result: _r, ...extras } = input.envelope;
|
|
75306
|
+
if (Object.keys(extras).length > 0) {
|
|
75307
|
+
parts.push(`extras=${truncate(safeJsonStringify(extras), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
75308
|
+
}
|
|
75309
|
+
if (input.envelope.result !== undefined) {
|
|
75310
|
+
parts.push(`result=${truncate(safeJsonStringify(input.envelope.result), ENVELOPE_BODY_PREVIEW_LENGTH)}`);
|
|
75311
|
+
}
|
|
75312
|
+
return parts.join(' ');
|
|
75313
|
+
}
|
|
75314
|
+
if (input.parseError) {
|
|
75315
|
+
const parseMsg = input.parseError instanceof Error ? input.parseError.message : String(input.parseError);
|
|
75316
|
+
parts.push(`parseError=${parseMsg}`);
|
|
75317
|
+
}
|
|
75318
|
+
parts.push(input.rawBody ? `body=${truncate(input.rawBody, ENVELOPE_BODY_PREVIEW_LENGTH)}` : 'body=(empty)');
|
|
75319
|
+
return parts.join(' ');
|
|
75320
|
+
}
|
|
75321
|
+
function truncate(value, max) {
|
|
75322
|
+
return value.length > max ? `${value.slice(0, max)}...(+${value.length - max} chars)` : value;
|
|
75323
|
+
}
|
|
75324
|
+
function safeJsonStringify(value) {
|
|
75325
|
+
try {
|
|
75326
|
+
return JSON.stringify(value);
|
|
75327
|
+
}
|
|
75328
|
+
catch {
|
|
75329
|
+
return String(value);
|
|
75330
|
+
}
|
|
75331
|
+
}
|
|
75102
75332
|
|
|
75103
75333
|
async function getCDNUploadInfo(options, runtime = {}) {
|
|
75104
75334
|
const body = new URLSearchParams();
|
|
@@ -75110,7 +75340,7 @@ async function getCDNUploadInfo(options, runtime = {}) {
|
|
|
75110
75340
|
async function getCDNUploadToken(options, runtime = {}) {
|
|
75111
75341
|
const body = new URLSearchParams();
|
|
75112
75342
|
body.set('bucket', options.bucket);
|
|
75113
|
-
body.set('
|
|
75343
|
+
body.set('keys', JSON.stringify(options.keys));
|
|
75114
75344
|
body.set('mimetypes', JSON.stringify(options.mimetypes));
|
|
75115
75345
|
body.set('is_multipart_upload', String(options.isMultipartUpload));
|
|
75116
75346
|
return postHeyboxApi('/bbs/app/api/qcloud/cos/upload/token/v2', body, options.session, runtime);
|
|
@@ -75123,17 +75353,14 @@ async function postCDNUploadCallback(options, runtime = {}) {
|
|
|
75123
75353
|
}
|
|
75124
75354
|
async function postHeyboxApi(pathWithQuery, body, session, runtime) {
|
|
75125
75355
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
75126
|
-
const
|
|
75127
|
-
const response = await fetchImpl(
|
|
75356
|
+
const context = createHeyboxRequestContext(session, { contentType: 'application/x-www-form-urlencoded' });
|
|
75357
|
+
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, pathWithQuery, context.platformParams), {
|
|
75128
75358
|
method: 'POST',
|
|
75129
|
-
headers:
|
|
75359
|
+
headers: context.headers,
|
|
75130
75360
|
body: body.toString(),
|
|
75131
75361
|
});
|
|
75132
|
-
const
|
|
75133
|
-
|
|
75134
|
-
throw new Error(envelope.msg || `Heybox API ${pathWithQuery} returned status ${envelope.status}`);
|
|
75135
|
-
}
|
|
75136
|
-
return envelope.result;
|
|
75362
|
+
const result = await readHeyboxApiEnvelope(response, { pathWithQuery, requireResult: true });
|
|
75363
|
+
return result;
|
|
75137
75364
|
}
|
|
75138
75365
|
|
|
75139
75366
|
const DEFAULT_CONCURRENCY = 4;
|
|
@@ -75146,8 +75373,6 @@ async function runUpload(options, runtime = {}) {
|
|
|
75146
75373
|
const getCDNUploadToken$1 = runtime.getCDNUploadToken ?? getCDNUploadToken;
|
|
75147
75374
|
const postCDNUploadCallback$1 = runtime.postCDNUploadCallback ?? postCDNUploadCallback;
|
|
75148
75375
|
const createReadStream = runtime.createReadStream ?? fs$4.createReadStream;
|
|
75149
|
-
const createCosClient = runtime.createCosClient ??
|
|
75150
|
-
(({ session }) => createDefaultCosClient(session, { baseUrl: runtime.baseUrl, fetchImpl, getCDNUploadToken: getCDNUploadToken$1 }));
|
|
75151
75376
|
const orderedFiles = [...options.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
75152
75377
|
const fileInfos = orderedFiles.map((file) => ({
|
|
75153
75378
|
name: file.relativePath.split('/').pop() ?? file.relativePath,
|
|
@@ -75161,8 +75386,16 @@ async function runUpload(options, runtime = {}) {
|
|
|
75161
75386
|
}));
|
|
75162
75387
|
log(`[hb-sdk] Uploading ${orderedFiles.length} files (${concurrency} concurrent) ...`);
|
|
75163
75388
|
const uploadInfo = await getCDNUploadInfo$1({ session: options.session, scope: MINIAPP_UPLOAD_SCOPE, fileInfos, needCache: false }, { baseUrl: runtime.baseUrl, fetchImpl });
|
|
75164
|
-
const cos = createCosClient({ session: options.session });
|
|
75165
75389
|
const indexedFiles = orderedFiles.map((file, index) => ({ file, key: uploadInfo.keys[index] }));
|
|
75390
|
+
const cos = runtime.createCosClient
|
|
75391
|
+
? runtime.createCosClient({ session: options.session })
|
|
75392
|
+
: createDefaultCosClient(await getCDNUploadToken$1({
|
|
75393
|
+
session: options.session,
|
|
75394
|
+
bucket: uploadInfo.bucket,
|
|
75395
|
+
keys: indexedFiles.map(({ key }) => key),
|
|
75396
|
+
mimetypes: indexedFiles.map(({ file }) => file.mimeType),
|
|
75397
|
+
isMultipartUpload: 0,
|
|
75398
|
+
}, { baseUrl: runtime.baseUrl, fetchImpl }));
|
|
75166
75399
|
const queue = indexedFiles.slice();
|
|
75167
75400
|
let completed = 0;
|
|
75168
75401
|
const workers = Array.from({ length: Math.min(concurrency, indexedFiles.length) }, async () => {
|
|
@@ -75185,7 +75418,7 @@ async function runUpload(options, runtime = {}) {
|
|
|
75185
75418
|
}
|
|
75186
75419
|
catch (error) {
|
|
75187
75420
|
completed += 1;
|
|
75188
|
-
log(`[hb-sdk] [${String(completed).padStart(2)}/${indexedFiles.length}] error ${task.file.relativePath} -> ${readErrorMessage$
|
|
75421
|
+
log(`[hb-sdk] [${String(completed).padStart(2)}/${indexedFiles.length}] error ${task.file.relativePath} -> ${readErrorMessage$2(error)}`);
|
|
75189
75422
|
throw error;
|
|
75190
75423
|
}
|
|
75191
75424
|
}
|
|
@@ -75194,28 +75427,15 @@ async function runUpload(options, runtime = {}) {
|
|
|
75194
75427
|
await postCDNUploadCallback$1({ session: options.session, keys: uploadInfo.keys, isFinished: true }, { baseUrl: runtime.baseUrl, fetchImpl });
|
|
75195
75428
|
log(`[hb-sdk] Upload finished: ${indexedFiles.length} files.`);
|
|
75196
75429
|
}
|
|
75197
|
-
function createDefaultCosClient(
|
|
75430
|
+
function createDefaultCosClient(uploadToken) {
|
|
75198
75431
|
const cos = new COS({
|
|
75199
|
-
getAuthorization(
|
|
75200
|
-
|
|
75201
|
-
.
|
|
75202
|
-
|
|
75203
|
-
|
|
75204
|
-
|
|
75205
|
-
|
|
75206
|
-
isMultipartUpload: 0,
|
|
75207
|
-
}, { baseUrl: options.baseUrl, fetchImpl: options.fetchImpl })
|
|
75208
|
-
.then((token) => {
|
|
75209
|
-
callback({
|
|
75210
|
-
TmpSecretId: token.credentials.tmpSecretId,
|
|
75211
|
-
TmpSecretKey: token.credentials.tmpSecretKey,
|
|
75212
|
-
XCosSecurityToken: token.credentials.sessionToken,
|
|
75213
|
-
StartTime: token.startTime,
|
|
75214
|
-
ExpiredTime: token.expiredTime,
|
|
75215
|
-
});
|
|
75216
|
-
})
|
|
75217
|
-
.catch((error) => {
|
|
75218
|
-
callback({ error });
|
|
75432
|
+
getAuthorization(_input, callback) {
|
|
75433
|
+
callback({
|
|
75434
|
+
TmpSecretId: uploadToken.credentials.tmpSecretId,
|
|
75435
|
+
TmpSecretKey: uploadToken.credentials.tmpSecretKey,
|
|
75436
|
+
XCosSecurityToken: uploadToken.credentials.sessionToken,
|
|
75437
|
+
StartTime: uploadToken.startTime,
|
|
75438
|
+
ExpiredTime: uploadToken.expiredTime,
|
|
75219
75439
|
});
|
|
75220
75440
|
},
|
|
75221
75441
|
});
|
|
@@ -75224,7 +75444,7 @@ function createDefaultCosClient(session, options) {
|
|
|
75224
75444
|
return new Promise((resolve, reject) => {
|
|
75225
75445
|
cos.putObject(params, (err, result) => {
|
|
75226
75446
|
if (err) {
|
|
75227
|
-
reject(err instanceof Error ? err : new Error(
|
|
75447
|
+
reject(err instanceof Error ? err : new Error(readErrorMessage$2(err)));
|
|
75228
75448
|
return;
|
|
75229
75449
|
}
|
|
75230
75450
|
resolve(result);
|
|
@@ -75242,26 +75462,51 @@ function formatSize(bytes) {
|
|
|
75242
75462
|
}
|
|
75243
75463
|
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
75244
75464
|
}
|
|
75245
|
-
function readErrorMessage$
|
|
75246
|
-
|
|
75465
|
+
function readErrorMessage$2(error) {
|
|
75466
|
+
if (error instanceof Error && error.message) {
|
|
75467
|
+
return error.message;
|
|
75468
|
+
}
|
|
75469
|
+
if (isRecord$1(error)) {
|
|
75470
|
+
const primary = readStringField(error, ['message', 'Message', 'errorMessage', 'msg']);
|
|
75471
|
+
const code = readStringField(error, ['code', 'Code', 'errorCode', 'name']);
|
|
75472
|
+
const statusCode = readStringField(error, ['statusCode']);
|
|
75473
|
+
return [code, statusCode, primary].filter(Boolean).join(' ') || JSON.stringify(error);
|
|
75474
|
+
}
|
|
75475
|
+
return String(error);
|
|
75476
|
+
}
|
|
75477
|
+
function readStringField(record, fields) {
|
|
75478
|
+
for (const field of fields) {
|
|
75479
|
+
const value = record[field];
|
|
75480
|
+
if (typeof value === 'string' && value.trim()) {
|
|
75481
|
+
return value.trim();
|
|
75482
|
+
}
|
|
75483
|
+
if (typeof value === 'number') {
|
|
75484
|
+
return String(value);
|
|
75485
|
+
}
|
|
75486
|
+
}
|
|
75487
|
+
return '';
|
|
75488
|
+
}
|
|
75489
|
+
function isRecord$1(value) {
|
|
75490
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
75247
75491
|
}
|
|
75248
75492
|
|
|
75249
75493
|
async function publishUserMiniprogram(options, runtime = {}) {
|
|
75250
75494
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
75251
|
-
const
|
|
75495
|
+
const context = createHeyboxOpenPlatformRequestContext(options.session, PUBLISH_USER_MINIPROGRAM_API_PATH, {
|
|
75496
|
+
contentType: 'application/x-www-form-urlencoded',
|
|
75497
|
+
});
|
|
75252
75498
|
const body = new URLSearchParams();
|
|
75253
75499
|
body.set('mini_program_id', options.miniProgramId);
|
|
75254
75500
|
body.set('manifest', JSON.stringify(options.manifest));
|
|
75255
|
-
const response = await fetchImpl(
|
|
75501
|
+
const response = await fetchImpl(createHeyboxApiUrl(runtime.baseUrl ?? context.baseUrl, PUBLISH_USER_MINIPROGRAM_API_PATH, context.platformParams), {
|
|
75256
75502
|
method: 'POST',
|
|
75257
|
-
headers:
|
|
75503
|
+
headers: context.headers,
|
|
75258
75504
|
body: body.toString(),
|
|
75259
75505
|
});
|
|
75260
|
-
const
|
|
75261
|
-
|
|
75262
|
-
|
|
75263
|
-
}
|
|
75264
|
-
return envelope.result ?? {};
|
|
75506
|
+
const result = await readHeyboxApiEnvelope(response, {
|
|
75507
|
+
pathWithQuery: PUBLISH_USER_MINIPROGRAM_API_PATH,
|
|
75508
|
+
});
|
|
75509
|
+
return result ?? {};
|
|
75265
75510
|
}
|
|
75266
75511
|
|
|
75267
75512
|
const SUPPORTED_PACKAGE_MANAGERS = [
|
|
@@ -75314,14 +75559,11 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
75314
75559
|
if (!fs$4.existsSync(entryHtmlPath)) {
|
|
75315
75560
|
throw new Error('未找到 dist/index.html,dist 目录残缺,请重新 build');
|
|
75316
75561
|
}
|
|
75317
|
-
const { manifest, hadBom } = await
|
|
75562
|
+
const { manifest, hadBom } = parseMiniappManifestJson(await fs$3.readFile(manifestPath, 'utf8'), 'dist/manifest.json');
|
|
75318
75563
|
if (hadBom) {
|
|
75319
75564
|
output.log('[hb-sdk] dist/manifest.json 包含 BOM,已自动剥离');
|
|
75320
75565
|
}
|
|
75321
|
-
const version = manifest
|
|
75322
|
-
if (typeof version !== 'string' || !isValidVersion(version)) {
|
|
75323
|
-
throw new Error(`manifest.version 格式错误,必须是 x.y.z:${String(version)}`);
|
|
75324
|
-
}
|
|
75566
|
+
const version = validateMiniappManifestForDeploy(manifest);
|
|
75325
75567
|
const allFiles = await walkDistFiles(distDir);
|
|
75326
75568
|
const blocked = allFiles.find((entry) => relativePathContainsNodeModulesSegment(entry.relativePath));
|
|
75327
75569
|
if (blocked) {
|
|
@@ -75332,8 +75574,14 @@ async function runDeployCommand(options, runtime = {}) {
|
|
|
75332
75574
|
if (pathError) {
|
|
75333
75575
|
throw new Error(pathError);
|
|
75334
75576
|
}
|
|
75335
|
-
|
|
75336
|
-
|
|
75577
|
+
let publishResult;
|
|
75578
|
+
try {
|
|
75579
|
+
await (runtime.runUpload ?? runUpload)({ session, miniProgramId, version, files: uploadFiles }, { console: output, fetchImpl: runtime.fetchImpl });
|
|
75580
|
+
publishResult = await (runtime.publishUserMiniprogram ?? publishUserMiniprogram)({ session, miniProgramId, manifest }, { fetchImpl: runtime.fetchImpl });
|
|
75581
|
+
}
|
|
75582
|
+
catch (error) {
|
|
75583
|
+
throw translateHeyboxDeployError(error, { projectRoot, version });
|
|
75584
|
+
}
|
|
75337
75585
|
output.log(`[hb-sdk] Publish ok: ${miniProgramId} ${version}`);
|
|
75338
75586
|
if (publishResult.publish_url) {
|
|
75339
75587
|
output.log(`[hb-sdk] Publish URL: ${publishResult.publish_url}`);
|
|
@@ -75381,17 +75629,6 @@ async function runBuildScript(pm, cwd, spawnImpl) {
|
|
|
75381
75629
|
});
|
|
75382
75630
|
});
|
|
75383
75631
|
}
|
|
75384
|
-
async function readManifest(manifestPath) {
|
|
75385
|
-
const raw = await fs$3.readFile(manifestPath, 'utf8');
|
|
75386
|
-
const hadBom = raw.charCodeAt(0) === 0xfeff;
|
|
75387
|
-
const text = hadBom ? raw.slice(1) : raw;
|
|
75388
|
-
try {
|
|
75389
|
-
return { manifest: JSON.parse(text), hadBom };
|
|
75390
|
-
}
|
|
75391
|
-
catch (error) {
|
|
75392
|
-
throw new Error(`dist/manifest.json 不是合法 JSON:${error instanceof Error ? error.message : String(error)}`);
|
|
75393
|
-
}
|
|
75394
|
-
}
|
|
75395
75632
|
async function walkDistFiles(distDir) {
|
|
75396
75633
|
const results = [];
|
|
75397
75634
|
await walk(distDir, '');
|
|
@@ -75425,6 +75662,39 @@ async function walkDistFiles(distDir) {
|
|
|
75425
75662
|
function inferMimeType(fileName) {
|
|
75426
75663
|
return MIME_BY_EXT[path.extname(fileName).toLowerCase()] || 'application/octet-stream';
|
|
75427
75664
|
}
|
|
75665
|
+
function translateHeyboxDeployError(error, options) {
|
|
75666
|
+
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
75667
|
+
if (isDuplicateUploadErrorMessage(message)) {
|
|
75668
|
+
const packageJsonPath = path.join(options.projectRoot, 'package.json');
|
|
75669
|
+
const nextVersion = suggestNextPatchVersion(options.version);
|
|
75670
|
+
return new Error([
|
|
75671
|
+
`当前小程序版本 ${options.version} 的上传文件已存在,不能覆盖同版本发布产物。`,
|
|
75672
|
+
`请升级 ${packageJsonPath} 中的 version${nextVersion ? `(例如 ${nextVersion})` : ''},重新 build 后再 deploy。`,
|
|
75673
|
+
`原始错误:${message}`,
|
|
75674
|
+
].join('\n'));
|
|
75675
|
+
}
|
|
75676
|
+
if (isAuthExpiredErrorMessage(message)) {
|
|
75677
|
+
return new Error([
|
|
75678
|
+
'Heybox 登录态已失效(服务端 session 已过期或被清除)。',
|
|
75679
|
+
'请运行 `hb-sdk login` 重新登录后再执行 deploy。',
|
|
75680
|
+
`原始错误:${message}`,
|
|
75681
|
+
].join('\n'));
|
|
75682
|
+
}
|
|
75683
|
+
return error instanceof Error ? error : new Error(message);
|
|
75684
|
+
}
|
|
75685
|
+
function isDuplicateUploadErrorMessage(message) {
|
|
75686
|
+
return /重名|duplicate|already exists|exists/i.test(message);
|
|
75687
|
+
}
|
|
75688
|
+
function isAuthExpiredErrorMessage(message) {
|
|
75689
|
+
return /请重新登录|未登录|登录已失效|登录态已失效|unauthorized|未授权/i.test(message);
|
|
75690
|
+
}
|
|
75691
|
+
function suggestNextPatchVersion(version) {
|
|
75692
|
+
const matched = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
75693
|
+
if (!matched) {
|
|
75694
|
+
return '';
|
|
75695
|
+
}
|
|
75696
|
+
return `${matched[1]}.${matched[2]}.${Number(matched[3]) + 1}`;
|
|
75697
|
+
}
|
|
75428
75698
|
|
|
75429
75699
|
class Locked extends Error {
|
|
75430
75700
|
constructor(port) {
|
|
@@ -75442,11 +75712,6 @@ const lockedPorts = {
|
|
|
75442
75712
|
// and a new young set for locked ports are created.
|
|
75443
75713
|
const releaseOldLockedPortsIntervalMs = 1000 * 15;
|
|
75444
75714
|
|
|
75445
|
-
// Keep `reserve` deliberately process-wide by port number.
|
|
75446
|
-
// It is meant to avoid in-process races, not to model every possible
|
|
75447
|
-
// IPv4/IPv6 or host-specific bind combination.
|
|
75448
|
-
const reservedPorts = new Set();
|
|
75449
|
-
|
|
75450
75715
|
// Lazily create timeout on first use
|
|
75451
75716
|
let timeout;
|
|
75452
75717
|
|
|
@@ -75498,8 +75763,6 @@ const getAvailablePort = async (options, hosts) => {
|
|
|
75498
75763
|
return options.port;
|
|
75499
75764
|
};
|
|
75500
75765
|
|
|
75501
|
-
const isLockedPort = port => lockedPorts.old.has(port) || lockedPorts.young.has(port) || reservedPorts.has(port);
|
|
75502
|
-
|
|
75503
75766
|
const portCheckSequence = function * (ports) {
|
|
75504
75767
|
if (ports) {
|
|
75505
75768
|
yield * ports;
|
|
@@ -75538,8 +75801,6 @@ async function getPorts(options) {
|
|
|
75538
75801
|
}
|
|
75539
75802
|
}
|
|
75540
75803
|
|
|
75541
|
-
const {reserve, ...netOptions} = options ?? {};
|
|
75542
|
-
|
|
75543
75804
|
if (timeout === undefined) {
|
|
75544
75805
|
timeout = setTimeout(() => {
|
|
75545
75806
|
timeout = undefined;
|
|
@@ -75562,20 +75823,16 @@ async function getPorts(options) {
|
|
|
75562
75823
|
continue;
|
|
75563
75824
|
}
|
|
75564
75825
|
|
|
75565
|
-
let availablePort = await getAvailablePort({...
|
|
75566
|
-
while (
|
|
75826
|
+
let availablePort = await getAvailablePort({...options, port}, hosts); // eslint-disable-line no-await-in-loop
|
|
75827
|
+
while (lockedPorts.old.has(availablePort) || lockedPorts.young.has(availablePort)) {
|
|
75567
75828
|
if (port !== 0) {
|
|
75568
75829
|
throw new Locked(port);
|
|
75569
75830
|
}
|
|
75570
75831
|
|
|
75571
|
-
availablePort = await getAvailablePort({...
|
|
75832
|
+
availablePort = await getAvailablePort({...options, port}, hosts); // eslint-disable-line no-await-in-loop
|
|
75572
75833
|
}
|
|
75573
75834
|
|
|
75574
|
-
|
|
75575
|
-
reservedPorts.add(availablePort);
|
|
75576
|
-
} else {
|
|
75577
|
-
lockedPorts.young.add(availablePort);
|
|
75578
|
-
}
|
|
75835
|
+
lockedPorts.young.add(availablePort);
|
|
75579
75836
|
|
|
75580
75837
|
return availablePort;
|
|
75581
75838
|
} catch (error) {
|
|
@@ -75588,6 +75845,337 @@ async function getPorts(options) {
|
|
|
75588
75845
|
throw new Error('No available ports found');
|
|
75589
75846
|
}
|
|
75590
75847
|
|
|
75848
|
+
const MINI_PROGRAM_URL_QUERY_PARAM = 'mini_url';
|
|
75849
|
+
const MOCK_NETWORK_PROXY_PATH = '/__hb_sdk_mock_network__';
|
|
75850
|
+
const MOCK_NETWORK_PROXY_BODY_LIMIT = 1024 * 1024;
|
|
75851
|
+
const MOCK_HOST_ROOT_CANDIDATES = [
|
|
75852
|
+
path.resolve(__dirname, 'devtools/mock-host'),
|
|
75853
|
+
path.resolve(__dirname, '../devtools/mock-host'),
|
|
75854
|
+
path.resolve(__dirname, '../../devtools/mock-host'),
|
|
75855
|
+
path.resolve(__dirname, '../../../devtools/mock-host'),
|
|
75856
|
+
];
|
|
75857
|
+
async function startMiniProgramMockHostServer(options) {
|
|
75858
|
+
const root = options.root ?? resolveMiniProgramMockHostRoot(options.rootCandidates);
|
|
75859
|
+
const server = createMiniProgramMockHostServer(root, {
|
|
75860
|
+
fetchImpl: options.fetchImpl ?? fetch,
|
|
75861
|
+
});
|
|
75862
|
+
const port = await listenHttpServer(server, {
|
|
75863
|
+
host: options.host,
|
|
75864
|
+
port: options.port,
|
|
75865
|
+
}, options.getPort ?? getPorts);
|
|
75866
|
+
return {
|
|
75867
|
+
close: () => new Promise((resolve) => {
|
|
75868
|
+
server.close(() => resolve());
|
|
75869
|
+
}),
|
|
75870
|
+
port,
|
|
75871
|
+
root,
|
|
75872
|
+
server,
|
|
75873
|
+
url: createMiniProgramMockHostUrl({
|
|
75874
|
+
appUrl: options.appUrl,
|
|
75875
|
+
host: options.host,
|
|
75876
|
+
port,
|
|
75877
|
+
}),
|
|
75878
|
+
};
|
|
75879
|
+
}
|
|
75880
|
+
function resolveMiniProgramMockHostRoot(candidates = MOCK_HOST_ROOT_CANDIDATES) {
|
|
75881
|
+
const found = candidates.find((candidate) => fs$4.existsSync(path.join(candidate, 'index.html')));
|
|
75882
|
+
if (!found) {
|
|
75883
|
+
throw new Error('未找到 hb-sdk mock host 静态产物。请先执行 @heybox/hb-sdk 的 build:mock-host。');
|
|
75884
|
+
}
|
|
75885
|
+
return found;
|
|
75886
|
+
}
|
|
75887
|
+
function createMiniProgramMockHostUrl(options) {
|
|
75888
|
+
const url = new URL(`http://${toDisplayHost$1(options.host)}:${options.port}/`);
|
|
75889
|
+
url.searchParams.set(MINI_PROGRAM_URL_QUERY_PARAM, options.appUrl);
|
|
75890
|
+
return url.toString();
|
|
75891
|
+
}
|
|
75892
|
+
function createMiniProgramMockHostServer(root, runtime) {
|
|
75893
|
+
return node_http.createServer(async (request, response) => {
|
|
75894
|
+
const requestUrl = new URL(request.url, 'http://localhost');
|
|
75895
|
+
const pathname = decodeURIComponent(requestUrl.pathname);
|
|
75896
|
+
if (pathname === MOCK_NETWORK_PROXY_PATH) {
|
|
75897
|
+
await handleMockNetworkProxy(request, response, runtime.fetchImpl);
|
|
75898
|
+
return;
|
|
75899
|
+
}
|
|
75900
|
+
const targetPath = resolveStaticPath(root, pathname);
|
|
75901
|
+
if (!targetPath) {
|
|
75902
|
+
response.writeHead(404);
|
|
75903
|
+
response.end('Not found');
|
|
75904
|
+
return;
|
|
75905
|
+
}
|
|
75906
|
+
try {
|
|
75907
|
+
const stat = fs$4.statSync(targetPath);
|
|
75908
|
+
if (stat.isDirectory()) {
|
|
75909
|
+
response.writeHead(404);
|
|
75910
|
+
response.end('Not found');
|
|
75911
|
+
return;
|
|
75912
|
+
}
|
|
75913
|
+
response.writeHead(200, {
|
|
75914
|
+
'content-type': readContentType(targetPath),
|
|
75915
|
+
'cache-control': 'no-store',
|
|
75916
|
+
});
|
|
75917
|
+
fs$4.createReadStream(targetPath).pipe(response);
|
|
75918
|
+
}
|
|
75919
|
+
catch {
|
|
75920
|
+
response.writeHead(404);
|
|
75921
|
+
response.end('Not found');
|
|
75922
|
+
}
|
|
75923
|
+
});
|
|
75924
|
+
}
|
|
75925
|
+
async function handleMockNetworkProxy(request, response, fetchImpl) {
|
|
75926
|
+
if (request.method === 'OPTIONS') {
|
|
75927
|
+
writeJsonResponse(response, 204, undefined);
|
|
75928
|
+
return;
|
|
75929
|
+
}
|
|
75930
|
+
if (request.method !== 'POST') {
|
|
75931
|
+
writeJsonResponse(response, 405, {
|
|
75932
|
+
code: 'METHOD_NOT_ALLOWED',
|
|
75933
|
+
message: 'mock network proxy only supports POST',
|
|
75934
|
+
});
|
|
75935
|
+
return;
|
|
75936
|
+
}
|
|
75937
|
+
try {
|
|
75938
|
+
const payload = await readJsonRequestBody(request);
|
|
75939
|
+
const result = await requestMockNetwork(payload, fetchImpl);
|
|
75940
|
+
writeJsonResponse(response, 200, result);
|
|
75941
|
+
}
|
|
75942
|
+
catch (error) {
|
|
75943
|
+
writeJsonResponse(response, readMockNetworkErrorStatus(error), toMockNetworkErrorPayload(error));
|
|
75944
|
+
}
|
|
75945
|
+
}
|
|
75946
|
+
async function requestMockNetwork(payload, fetchImpl) {
|
|
75947
|
+
if (!isRecord(payload) || typeof payload.url !== 'string' || !payload.url.trim()) {
|
|
75948
|
+
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request url 必须是非空字符串');
|
|
75949
|
+
}
|
|
75950
|
+
const url = createMockNetworkUrl(payload.url, payload.params);
|
|
75951
|
+
const method = typeof payload.method === 'string' && payload.method.trim() ? payload.method.trim().toUpperCase() : 'GET';
|
|
75952
|
+
const headers = normalizeMockNetworkHeaders(payload.headers);
|
|
75953
|
+
const controller = new AbortController();
|
|
75954
|
+
const timeout = Number(payload.timeout) > 0 ? Number(payload.timeout) : 10000;
|
|
75955
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
75956
|
+
try {
|
|
75957
|
+
const response = await fetchImpl(url.toString(), {
|
|
75958
|
+
method,
|
|
75959
|
+
headers,
|
|
75960
|
+
body: createMockNetworkBody(method, payload.data, headers),
|
|
75961
|
+
redirect: 'follow',
|
|
75962
|
+
signal: controller.signal,
|
|
75963
|
+
});
|
|
75964
|
+
const contentType = response.headers.get('content-type') || '';
|
|
75965
|
+
const text = await response.text();
|
|
75966
|
+
clearTimeout(timer);
|
|
75967
|
+
return {
|
|
75968
|
+
data: contentType.includes('application/json') ? safeJsonParse(text) : text,
|
|
75969
|
+
status: response.status,
|
|
75970
|
+
statusText: response.statusText,
|
|
75971
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
75972
|
+
};
|
|
75973
|
+
}
|
|
75974
|
+
catch (error) {
|
|
75975
|
+
clearTimeout(timer);
|
|
75976
|
+
throw createMockNetworkError(502, 'MOCK_NETWORK_REQUEST_FAILED', error instanceof Error && error.name === 'AbortError'
|
|
75977
|
+
? `network.request timeout after ${timeout}ms`
|
|
75978
|
+
: readErrorMessage$1(error));
|
|
75979
|
+
}
|
|
75980
|
+
}
|
|
75981
|
+
function createMockNetworkUrl(input, params) {
|
|
75982
|
+
let url;
|
|
75983
|
+
try {
|
|
75984
|
+
url = new URL(input);
|
|
75985
|
+
}
|
|
75986
|
+
catch {
|
|
75987
|
+
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request url 必须是合法 URL');
|
|
75988
|
+
}
|
|
75989
|
+
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
75990
|
+
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request 仅支持 HTTP(S) URL');
|
|
75991
|
+
}
|
|
75992
|
+
if (isRecord(params)) {
|
|
75993
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
75994
|
+
if (value !== undefined && value !== null) {
|
|
75995
|
+
url.searchParams.set(key, String(value));
|
|
75996
|
+
}
|
|
75997
|
+
});
|
|
75998
|
+
}
|
|
75999
|
+
return url;
|
|
76000
|
+
}
|
|
76001
|
+
function normalizeMockNetworkHeaders(headers) {
|
|
76002
|
+
const normalized = new Headers();
|
|
76003
|
+
if (!isRecord(headers)) {
|
|
76004
|
+
return normalized;
|
|
76005
|
+
}
|
|
76006
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
76007
|
+
if (typeof value === 'string' && !isBlockedMockNetworkHeader(key)) {
|
|
76008
|
+
normalized.set(key, value);
|
|
76009
|
+
}
|
|
76010
|
+
});
|
|
76011
|
+
return normalized;
|
|
76012
|
+
}
|
|
76013
|
+
function isBlockedMockNetworkHeader(key) {
|
|
76014
|
+
return [
|
|
76015
|
+
'connection',
|
|
76016
|
+
'content-length',
|
|
76017
|
+
'host',
|
|
76018
|
+
'keep-alive',
|
|
76019
|
+
'proxy-authenticate',
|
|
76020
|
+
'proxy-authorization',
|
|
76021
|
+
'te',
|
|
76022
|
+
'trailer',
|
|
76023
|
+
'transfer-encoding',
|
|
76024
|
+
'upgrade',
|
|
76025
|
+
].includes(key.toLowerCase());
|
|
76026
|
+
}
|
|
76027
|
+
function createMockNetworkBody(method, data, headers) {
|
|
76028
|
+
if (data === undefined || method === 'GET' || method === 'HEAD') {
|
|
76029
|
+
return undefined;
|
|
76030
|
+
}
|
|
76031
|
+
if (typeof data === 'string') {
|
|
76032
|
+
return data;
|
|
76033
|
+
}
|
|
76034
|
+
if (!headers.has('content-type')) {
|
|
76035
|
+
headers.set('content-type', 'application/json');
|
|
76036
|
+
}
|
|
76037
|
+
return JSON.stringify(data);
|
|
76038
|
+
}
|
|
76039
|
+
function readJsonRequestBody(request) {
|
|
76040
|
+
return new Promise((resolve, reject) => {
|
|
76041
|
+
const chunks = [];
|
|
76042
|
+
let size = 0;
|
|
76043
|
+
request.on('data', (chunk) => {
|
|
76044
|
+
const buffer = Buffer.from(chunk);
|
|
76045
|
+
size += buffer.byteLength;
|
|
76046
|
+
if (size > MOCK_NETWORK_PROXY_BODY_LIMIT) {
|
|
76047
|
+
reject(createMockNetworkError(413, 'REQUEST_ENTITY_TOO_LARGE', 'mock network proxy request body too large'));
|
|
76048
|
+
request.destroy();
|
|
76049
|
+
return;
|
|
76050
|
+
}
|
|
76051
|
+
chunks.push(buffer);
|
|
76052
|
+
});
|
|
76053
|
+
request.on('error', reject);
|
|
76054
|
+
request.on('aborted', () => {
|
|
76055
|
+
reject('mock network proxy request aborted');
|
|
76056
|
+
});
|
|
76057
|
+
request.on('end', () => {
|
|
76058
|
+
const rawBody = Buffer.concat(chunks).toString('utf8');
|
|
76059
|
+
if (!rawBody.trim()) {
|
|
76060
|
+
resolve({});
|
|
76061
|
+
return;
|
|
76062
|
+
}
|
|
76063
|
+
try {
|
|
76064
|
+
resolve(JSON.parse(rawBody));
|
|
76065
|
+
}
|
|
76066
|
+
catch {
|
|
76067
|
+
reject(createMockNetworkError(400, 'INVALID_JSON', 'mock network proxy received invalid JSON'));
|
|
76068
|
+
}
|
|
76069
|
+
});
|
|
76070
|
+
});
|
|
76071
|
+
}
|
|
76072
|
+
function writeJsonResponse(response, status, body) {
|
|
76073
|
+
response.writeHead(status, {
|
|
76074
|
+
'content-type': 'application/json; charset=utf-8',
|
|
76075
|
+
'cache-control': 'no-store',
|
|
76076
|
+
});
|
|
76077
|
+
response.end(body === undefined ? '' : JSON.stringify(body));
|
|
76078
|
+
}
|
|
76079
|
+
function safeJsonParse(text) {
|
|
76080
|
+
try {
|
|
76081
|
+
return JSON.parse(text);
|
|
76082
|
+
}
|
|
76083
|
+
catch {
|
|
76084
|
+
return text;
|
|
76085
|
+
}
|
|
76086
|
+
}
|
|
76087
|
+
function isRecord(value) {
|
|
76088
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
76089
|
+
}
|
|
76090
|
+
function createMockNetworkError(status, code, message) {
|
|
76091
|
+
const error = new Error(message);
|
|
76092
|
+
error.code = code;
|
|
76093
|
+
error.status = status;
|
|
76094
|
+
return error;
|
|
76095
|
+
}
|
|
76096
|
+
function readMockNetworkErrorStatus(error) {
|
|
76097
|
+
return isObjectLike(error) && typeof error.status === 'number' ? error.status : 500;
|
|
76098
|
+
}
|
|
76099
|
+
function toMockNetworkErrorPayload(error) {
|
|
76100
|
+
if (isObjectLike(error) && typeof error.code === 'string' && typeof error.message === 'string') {
|
|
76101
|
+
return {
|
|
76102
|
+
code: error.code,
|
|
76103
|
+
message: error.message,
|
|
76104
|
+
};
|
|
76105
|
+
}
|
|
76106
|
+
return {
|
|
76107
|
+
code: 'MOCK_NETWORK_ERROR',
|
|
76108
|
+
message: readErrorMessage$1(error),
|
|
76109
|
+
};
|
|
76110
|
+
}
|
|
76111
|
+
function isObjectLike(value) {
|
|
76112
|
+
return (typeof value === 'object' || typeof value === 'function') && value !== null;
|
|
76113
|
+
}
|
|
76114
|
+
function resolveStaticPath(root, pathname) {
|
|
76115
|
+
const safePathname = pathname === '/' ? '/index.html' : pathname;
|
|
76116
|
+
const normalizedRoot = path.normalize(root);
|
|
76117
|
+
const targetPath = path.normalize(path.join(normalizedRoot, safePathname));
|
|
76118
|
+
if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {
|
|
76119
|
+
return undefined;
|
|
76120
|
+
}
|
|
76121
|
+
return targetPath;
|
|
76122
|
+
}
|
|
76123
|
+
function readContentType(filePath) {
|
|
76124
|
+
if (filePath.endsWith('.html')) {
|
|
76125
|
+
return 'text/html; charset=utf-8';
|
|
76126
|
+
}
|
|
76127
|
+
if (filePath.endsWith('.js')) {
|
|
76128
|
+
return 'text/javascript; charset=utf-8';
|
|
76129
|
+
}
|
|
76130
|
+
if (filePath.endsWith('.css')) {
|
|
76131
|
+
return 'text/css; charset=utf-8';
|
|
76132
|
+
}
|
|
76133
|
+
if (filePath.endsWith('.json')) {
|
|
76134
|
+
return 'application/json; charset=utf-8';
|
|
76135
|
+
}
|
|
76136
|
+
if (filePath.endsWith('.svg')) {
|
|
76137
|
+
return 'image/svg+xml';
|
|
76138
|
+
}
|
|
76139
|
+
return 'application/octet-stream';
|
|
76140
|
+
}
|
|
76141
|
+
async function listenHttpServer(server, options, getPortImpl) {
|
|
76142
|
+
const maxAttempts = 20;
|
|
76143
|
+
const port = await getPortImpl({
|
|
76144
|
+
host: options.host,
|
|
76145
|
+
port: createPortCandidates(options.port, maxAttempts),
|
|
76146
|
+
});
|
|
76147
|
+
if (port < options.port || port >= options.port + maxAttempts) {
|
|
76148
|
+
throw new Error(`无法找到可用 mock host 端口,起始端口: ${options.port}`);
|
|
76149
|
+
}
|
|
76150
|
+
await new Promise((resolve, reject) => {
|
|
76151
|
+
const onError = (error) => {
|
|
76152
|
+
server.off('listening', onListening);
|
|
76153
|
+
reject(error);
|
|
76154
|
+
};
|
|
76155
|
+
const onListening = () => {
|
|
76156
|
+
server.off('error', onError);
|
|
76157
|
+
resolve();
|
|
76158
|
+
};
|
|
76159
|
+
server.once('error', onError);
|
|
76160
|
+
server.once('listening', onListening);
|
|
76161
|
+
server.listen(port, options.host);
|
|
76162
|
+
});
|
|
76163
|
+
const address = server.address();
|
|
76164
|
+
return address.port;
|
|
76165
|
+
}
|
|
76166
|
+
function createPortCandidates(startPort, count) {
|
|
76167
|
+
return Array.from({ length: count }, (_, index) => startPort + index);
|
|
76168
|
+
}
|
|
76169
|
+
function toDisplayHost$1(host) {
|
|
76170
|
+
if (!host || host === '0.0.0.0' || host === '::') {
|
|
76171
|
+
return 'localhost';
|
|
76172
|
+
}
|
|
76173
|
+
return host;
|
|
76174
|
+
}
|
|
76175
|
+
function readErrorMessage$1(error) {
|
|
76176
|
+
return error instanceof Error ? error.message : String(error);
|
|
76177
|
+
}
|
|
76178
|
+
|
|
75591
76179
|
let isDockerCached;
|
|
75592
76180
|
|
|
75593
76181
|
function hasDockerEnv() {
|
|
@@ -75651,20 +76239,11 @@ const isWsl = () => {
|
|
|
75651
76239
|
}
|
|
75652
76240
|
|
|
75653
76241
|
try {
|
|
75654
|
-
|
|
75655
|
-
|
|
75656
|
-
|
|
75657
|
-
|
|
75658
|
-
|
|
75659
|
-
// Fallback for custom kernels: check WSL-specific paths.
|
|
75660
|
-
if (
|
|
75661
|
-
fs$4.existsSync('/proc/sys/fs/binfmt_misc/WSLInterop')
|
|
75662
|
-
|| fs$4.existsSync('/run/WSL')
|
|
75663
|
-
) {
|
|
75664
|
-
return !isInsideContainer();
|
|
76242
|
+
return fs$4.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft')
|
|
76243
|
+
? !isInsideContainer() : false;
|
|
76244
|
+
} catch {
|
|
76245
|
+
return false;
|
|
75665
76246
|
}
|
|
75666
|
-
|
|
75667
|
-
return false;
|
|
75668
76247
|
};
|
|
75669
76248
|
|
|
75670
76249
|
var isWsl$1 = process$1.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
@@ -76221,9 +76800,6 @@ function readErrorMessage(error) {
|
|
|
76221
76800
|
|
|
76222
76801
|
const DEFAULT_APP_PORT = 5173;
|
|
76223
76802
|
const DEFAULT_MOCK_PORT = 5174;
|
|
76224
|
-
const MINI_PROGRAM_URL_QUERY_PARAM = 'mini_url';
|
|
76225
|
-
const MOCK_NETWORK_PROXY_PATH = '/__hb_sdk_mock_network__';
|
|
76226
|
-
const MOCK_NETWORK_PROXY_BODY_LIMIT = 1024 * 1024;
|
|
76227
76803
|
// Shared with Heybox H5 Vite plugins so hb-sdk can own the launch output.
|
|
76228
76804
|
const MANAGED_DEV_OUTPUT_ENV = 'HEYBOX_DEV_SERVER_MANAGED_OUTPUT';
|
|
76229
76805
|
const VITE_LOG_LEVEL = 'warn';
|
|
@@ -76237,26 +76813,29 @@ async function runDevCommand(options, runtime = {}) {
|
|
|
76237
76813
|
await appServer.listen(options.port ?? DEFAULT_APP_PORT);
|
|
76238
76814
|
const appUrl = await resolveViteAppUrl(appServer, options, fetchImpl);
|
|
76239
76815
|
const closers = [() => appServer.close()];
|
|
76240
|
-
|
|
76241
|
-
|
|
76242
|
-
|
|
76243
|
-
|
|
76244
|
-
|
|
76245
|
-
|
|
76246
|
-
|
|
76247
|
-
|
|
76248
|
-
|
|
76249
|
-
|
|
76250
|
-
|
|
76251
|
-
|
|
76252
|
-
|
|
76253
|
-
|
|
76816
|
+
let mockHost;
|
|
76817
|
+
try {
|
|
76818
|
+
mockHost = await startMiniProgramMockHostServer({
|
|
76819
|
+
appUrl,
|
|
76820
|
+
fetchImpl,
|
|
76821
|
+
getPort: runtime.getPort ?? getPorts,
|
|
76822
|
+
host: options.host,
|
|
76823
|
+
port: options.mockPort ?? DEFAULT_MOCK_PORT,
|
|
76824
|
+
root: runtime.mockHostRoot,
|
|
76825
|
+
rootCandidates: runtime.mockHostRootCandidates,
|
|
76826
|
+
});
|
|
76827
|
+
}
|
|
76828
|
+
catch (error) {
|
|
76829
|
+
await closeAll(closers);
|
|
76830
|
+
throw error;
|
|
76831
|
+
}
|
|
76832
|
+
closers.push(() => mockHost.close());
|
|
76254
76833
|
output.log(`\n[hb-sdk] Mock runtime host is ready`);
|
|
76255
|
-
output.log(`[hb-sdk] Mock runtime host: ${
|
|
76834
|
+
output.log(`[hb-sdk] Mock runtime host: ${mockHost.url}`);
|
|
76256
76835
|
output.log(`[hb-sdk] Mini program URL: ${appUrl}`);
|
|
76257
76836
|
output.log(`[hb-sdk] Mac APP: use the button in Mock runtime host`);
|
|
76258
76837
|
if (options.open !== false) {
|
|
76259
|
-
void openUrl(
|
|
76838
|
+
void openUrl(mockHost.url);
|
|
76260
76839
|
}
|
|
76261
76840
|
installShutdownHandlers(closers, runtime.process ?? process);
|
|
76262
76841
|
}
|
|
@@ -76276,6 +76855,10 @@ function findProjectRoot(startDir) {
|
|
|
76276
76855
|
async function loadProjectVite(projectRoot) {
|
|
76277
76856
|
const projectRequire = node_module.createRequire(path.join(projectRoot, 'package.json'));
|
|
76278
76857
|
try {
|
|
76858
|
+
const packageJson = JSON.parse(await fs$3.readFile(path.join(projectRoot, 'package.json'), 'utf8'));
|
|
76859
|
+
if (!hasPackageDependency(packageJson, 'vite')) {
|
|
76860
|
+
throw new Error('package.json 未声明 vite');
|
|
76861
|
+
}
|
|
76279
76862
|
const viteEntry = projectRequire.resolve('vite');
|
|
76280
76863
|
return (await import(node_url.pathToFileURL(viteEntry).href));
|
|
76281
76864
|
}
|
|
@@ -76283,6 +76866,12 @@ async function loadProjectVite(projectRoot) {
|
|
|
76283
76866
|
throw new Error(`当前项目未安装 vite。请先安装项目依赖,或将 vite 放到项目 devDependencies。原始错误: ${readErrorMessage(error)}`);
|
|
76284
76867
|
}
|
|
76285
76868
|
}
|
|
76869
|
+
function hasPackageDependency(packageJson, name) {
|
|
76870
|
+
return Boolean(packageJson.dependencies?.[name] ||
|
|
76871
|
+
packageJson.devDependencies?.[name] ||
|
|
76872
|
+
packageJson.optionalDependencies?.[name] ||
|
|
76873
|
+
packageJson.peerDependencies?.[name]);
|
|
76874
|
+
}
|
|
76286
76875
|
function createViteServerOptions(projectRoot, options) {
|
|
76287
76876
|
const configFile = resolveProjectViteConfig(projectRoot);
|
|
76288
76877
|
const server = {
|
|
@@ -76379,299 +76968,6 @@ async function canReachDocumentUrl(url, fetchImpl) {
|
|
|
76379
76968
|
function ensureTrailingSlash(value) {
|
|
76380
76969
|
return value.endsWith('/') ? value : `${value}/`;
|
|
76381
76970
|
}
|
|
76382
|
-
const MOCK_HOST_ROOT_CANDIDATES = [
|
|
76383
|
-
path.resolve(__dirname, 'devtools/mock-host'),
|
|
76384
|
-
path.resolve(__dirname, '../devtools/mock-host'),
|
|
76385
|
-
path.resolve(__dirname, '../../devtools/mock-host'),
|
|
76386
|
-
path.resolve(__dirname, '../../../devtools/mock-host'),
|
|
76387
|
-
];
|
|
76388
|
-
function resolveMockHostRoot(candidates = MOCK_HOST_ROOT_CANDIDATES) {
|
|
76389
|
-
const found = candidates.find((candidate) => fs$4.existsSync(path.join(candidate, 'index.html')));
|
|
76390
|
-
if (!found) {
|
|
76391
|
-
throw new Error(`未找到 hb-sdk mock host 静态产物。请先执行 @heybox/hb-sdk 的 build:mock-host。`);
|
|
76392
|
-
}
|
|
76393
|
-
return found;
|
|
76394
|
-
}
|
|
76395
|
-
function createMockHostServer(root, runtime) {
|
|
76396
|
-
return node_http.createServer(async (request, response) => {
|
|
76397
|
-
const requestUrl = new URL(request.url, 'http://localhost');
|
|
76398
|
-
const pathname = decodeURIComponent(requestUrl.pathname);
|
|
76399
|
-
if (pathname === MOCK_NETWORK_PROXY_PATH) {
|
|
76400
|
-
await handleMockNetworkProxy(request, response, runtime.fetchImpl);
|
|
76401
|
-
return;
|
|
76402
|
-
}
|
|
76403
|
-
const targetPath = resolveStaticPath(root, pathname);
|
|
76404
|
-
if (!targetPath) {
|
|
76405
|
-
response.writeHead(404);
|
|
76406
|
-
response.end('Not found');
|
|
76407
|
-
return;
|
|
76408
|
-
}
|
|
76409
|
-
try {
|
|
76410
|
-
const stat = fs$4.statSync(targetPath);
|
|
76411
|
-
if (stat.isDirectory()) {
|
|
76412
|
-
response.writeHead(404);
|
|
76413
|
-
response.end('Not found');
|
|
76414
|
-
return;
|
|
76415
|
-
}
|
|
76416
|
-
response.writeHead(200, {
|
|
76417
|
-
'content-type': readContentType(targetPath),
|
|
76418
|
-
'cache-control': 'no-store',
|
|
76419
|
-
});
|
|
76420
|
-
fs$4.createReadStream(targetPath).pipe(response);
|
|
76421
|
-
}
|
|
76422
|
-
catch {
|
|
76423
|
-
response.writeHead(404);
|
|
76424
|
-
response.end('Not found');
|
|
76425
|
-
}
|
|
76426
|
-
});
|
|
76427
|
-
}
|
|
76428
|
-
async function handleMockNetworkProxy(request, response, fetchImpl) {
|
|
76429
|
-
if (request.method === 'OPTIONS') {
|
|
76430
|
-
writeJsonResponse(response, 204, undefined);
|
|
76431
|
-
return;
|
|
76432
|
-
}
|
|
76433
|
-
if (request.method !== 'POST') {
|
|
76434
|
-
writeJsonResponse(response, 405, {
|
|
76435
|
-
code: 'METHOD_NOT_ALLOWED',
|
|
76436
|
-
message: 'mock network proxy only supports POST',
|
|
76437
|
-
});
|
|
76438
|
-
return;
|
|
76439
|
-
}
|
|
76440
|
-
try {
|
|
76441
|
-
const payload = await readJsonRequestBody(request);
|
|
76442
|
-
const result = await requestMockNetwork(payload, fetchImpl);
|
|
76443
|
-
writeJsonResponse(response, 200, result);
|
|
76444
|
-
}
|
|
76445
|
-
catch (error) {
|
|
76446
|
-
writeJsonResponse(response, readMockNetworkErrorStatus(error), toMockNetworkErrorPayload(error));
|
|
76447
|
-
}
|
|
76448
|
-
}
|
|
76449
|
-
async function requestMockNetwork(payload, fetchImpl) {
|
|
76450
|
-
if (!isRecord(payload) || typeof payload.url !== 'string' || !payload.url.trim()) {
|
|
76451
|
-
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request url 必须是非空字符串');
|
|
76452
|
-
}
|
|
76453
|
-
const url = createMockNetworkUrl(payload.url, payload.params);
|
|
76454
|
-
const method = typeof payload.method === 'string' && payload.method.trim() ? payload.method.trim().toUpperCase() : 'GET';
|
|
76455
|
-
const headers = normalizeMockNetworkHeaders(payload.headers);
|
|
76456
|
-
const controller = new AbortController();
|
|
76457
|
-
const timeout = Number(payload.timeout) > 0 ? Number(payload.timeout) : 10000;
|
|
76458
|
-
const timer = setTimeout(() => controller.abort(), timeout);
|
|
76459
|
-
try {
|
|
76460
|
-
const response = await fetchImpl(url.toString(), {
|
|
76461
|
-
method,
|
|
76462
|
-
headers,
|
|
76463
|
-
body: createMockNetworkBody(method, payload.data, headers),
|
|
76464
|
-
redirect: 'follow',
|
|
76465
|
-
signal: controller.signal,
|
|
76466
|
-
});
|
|
76467
|
-
const contentType = response.headers.get('content-type') || '';
|
|
76468
|
-
const text = await response.text();
|
|
76469
|
-
clearTimeout(timer);
|
|
76470
|
-
return {
|
|
76471
|
-
data: contentType.includes('application/json') ? safeJsonParse(text) : text,
|
|
76472
|
-
status: response.status,
|
|
76473
|
-
statusText: response.statusText,
|
|
76474
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
76475
|
-
};
|
|
76476
|
-
}
|
|
76477
|
-
catch (error) {
|
|
76478
|
-
clearTimeout(timer);
|
|
76479
|
-
throw createMockNetworkError(502, 'MOCK_NETWORK_REQUEST_FAILED', error instanceof Error && error.name === 'AbortError' ? `network.request timeout after ${timeout}ms` : readErrorMessage(error));
|
|
76480
|
-
}
|
|
76481
|
-
}
|
|
76482
|
-
function createMockNetworkUrl(input, params) {
|
|
76483
|
-
let url;
|
|
76484
|
-
try {
|
|
76485
|
-
url = new URL(input);
|
|
76486
|
-
}
|
|
76487
|
-
catch {
|
|
76488
|
-
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request url 必须是合法 URL');
|
|
76489
|
-
}
|
|
76490
|
-
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
76491
|
-
throw createMockNetworkError(400, 'INVALID_NETWORK_REQUEST', 'network.request 仅支持 HTTP(S) URL');
|
|
76492
|
-
}
|
|
76493
|
-
if (isRecord(params)) {
|
|
76494
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
76495
|
-
if (value !== undefined && value !== null) {
|
|
76496
|
-
url.searchParams.set(key, String(value));
|
|
76497
|
-
}
|
|
76498
|
-
});
|
|
76499
|
-
}
|
|
76500
|
-
return url;
|
|
76501
|
-
}
|
|
76502
|
-
function normalizeMockNetworkHeaders(headers) {
|
|
76503
|
-
const normalized = new Headers();
|
|
76504
|
-
if (!isRecord(headers)) {
|
|
76505
|
-
return normalized;
|
|
76506
|
-
}
|
|
76507
|
-
Object.entries(headers).forEach(([key, value]) => {
|
|
76508
|
-
if (typeof value === 'string' && !isBlockedMockNetworkHeader(key)) {
|
|
76509
|
-
normalized.set(key, value);
|
|
76510
|
-
}
|
|
76511
|
-
});
|
|
76512
|
-
return normalized;
|
|
76513
|
-
}
|
|
76514
|
-
function isBlockedMockNetworkHeader(key) {
|
|
76515
|
-
return [
|
|
76516
|
-
'connection',
|
|
76517
|
-
'content-length',
|
|
76518
|
-
'host',
|
|
76519
|
-
'keep-alive',
|
|
76520
|
-
'proxy-authenticate',
|
|
76521
|
-
'proxy-authorization',
|
|
76522
|
-
'te',
|
|
76523
|
-
'trailer',
|
|
76524
|
-
'transfer-encoding',
|
|
76525
|
-
'upgrade',
|
|
76526
|
-
].includes(key.toLowerCase());
|
|
76527
|
-
}
|
|
76528
|
-
function createMockNetworkBody(method, data, headers) {
|
|
76529
|
-
if (data === undefined || method === 'GET' || method === 'HEAD') {
|
|
76530
|
-
return undefined;
|
|
76531
|
-
}
|
|
76532
|
-
if (typeof data === 'string') {
|
|
76533
|
-
return data;
|
|
76534
|
-
}
|
|
76535
|
-
if (!headers.has('content-type')) {
|
|
76536
|
-
headers.set('content-type', 'application/json');
|
|
76537
|
-
}
|
|
76538
|
-
return JSON.stringify(data);
|
|
76539
|
-
}
|
|
76540
|
-
function readJsonRequestBody(request) {
|
|
76541
|
-
return new Promise((resolve, reject) => {
|
|
76542
|
-
const chunks = [];
|
|
76543
|
-
let size = 0;
|
|
76544
|
-
request.on('data', (chunk) => {
|
|
76545
|
-
const buffer = Buffer.from(chunk);
|
|
76546
|
-
size += buffer.byteLength;
|
|
76547
|
-
if (size > MOCK_NETWORK_PROXY_BODY_LIMIT) {
|
|
76548
|
-
reject(createMockNetworkError(413, 'REQUEST_ENTITY_TOO_LARGE', 'mock network proxy request body too large'));
|
|
76549
|
-
request.destroy();
|
|
76550
|
-
return;
|
|
76551
|
-
}
|
|
76552
|
-
chunks.push(buffer);
|
|
76553
|
-
});
|
|
76554
|
-
request.on('error', reject);
|
|
76555
|
-
request.on('aborted', () => {
|
|
76556
|
-
reject('mock network proxy request aborted');
|
|
76557
|
-
});
|
|
76558
|
-
request.on('end', () => {
|
|
76559
|
-
const rawBody = Buffer.concat(chunks).toString('utf8');
|
|
76560
|
-
if (!rawBody.trim()) {
|
|
76561
|
-
resolve({});
|
|
76562
|
-
return;
|
|
76563
|
-
}
|
|
76564
|
-
try {
|
|
76565
|
-
resolve(JSON.parse(rawBody));
|
|
76566
|
-
}
|
|
76567
|
-
catch {
|
|
76568
|
-
reject(createMockNetworkError(400, 'INVALID_JSON', 'mock network proxy received invalid JSON'));
|
|
76569
|
-
}
|
|
76570
|
-
});
|
|
76571
|
-
});
|
|
76572
|
-
}
|
|
76573
|
-
function writeJsonResponse(response, status, body) {
|
|
76574
|
-
response.writeHead(status, {
|
|
76575
|
-
'content-type': 'application/json; charset=utf-8',
|
|
76576
|
-
'cache-control': 'no-store',
|
|
76577
|
-
});
|
|
76578
|
-
response.end(body === undefined ? '' : JSON.stringify(body));
|
|
76579
|
-
}
|
|
76580
|
-
function safeJsonParse(text) {
|
|
76581
|
-
try {
|
|
76582
|
-
return JSON.parse(text);
|
|
76583
|
-
}
|
|
76584
|
-
catch {
|
|
76585
|
-
return text;
|
|
76586
|
-
}
|
|
76587
|
-
}
|
|
76588
|
-
function isRecord(value) {
|
|
76589
|
-
return Object.prototype.toString.call(value) === '[object Object]';
|
|
76590
|
-
}
|
|
76591
|
-
function createMockNetworkError(status, code, message) {
|
|
76592
|
-
const error = new Error(message);
|
|
76593
|
-
error.code = code;
|
|
76594
|
-
error.status = status;
|
|
76595
|
-
return error;
|
|
76596
|
-
}
|
|
76597
|
-
function readMockNetworkErrorStatus(error) {
|
|
76598
|
-
return isObjectLike(error) && typeof error.status === 'number' ? error.status : 500;
|
|
76599
|
-
}
|
|
76600
|
-
function toMockNetworkErrorPayload(error) {
|
|
76601
|
-
if (isObjectLike(error) && typeof error.code === 'string' && typeof error.message === 'string') {
|
|
76602
|
-
return {
|
|
76603
|
-
code: error.code,
|
|
76604
|
-
message: error.message,
|
|
76605
|
-
};
|
|
76606
|
-
}
|
|
76607
|
-
return {
|
|
76608
|
-
code: 'MOCK_NETWORK_ERROR',
|
|
76609
|
-
message: readErrorMessage(error),
|
|
76610
|
-
};
|
|
76611
|
-
}
|
|
76612
|
-
function isObjectLike(value) {
|
|
76613
|
-
return (typeof value === 'object' || typeof value === 'function') && value !== null;
|
|
76614
|
-
}
|
|
76615
|
-
function resolveStaticPath(root, pathname) {
|
|
76616
|
-
const safePathname = pathname === '/' ? '/index.html' : pathname;
|
|
76617
|
-
const normalizedRoot = path.normalize(root);
|
|
76618
|
-
const targetPath = path.normalize(path.join(normalizedRoot, safePathname));
|
|
76619
|
-
if (targetPath !== normalizedRoot && !targetPath.startsWith(`${normalizedRoot}${path.sep}`)) {
|
|
76620
|
-
return undefined;
|
|
76621
|
-
}
|
|
76622
|
-
return targetPath;
|
|
76623
|
-
}
|
|
76624
|
-
function readContentType(filePath) {
|
|
76625
|
-
if (filePath.endsWith('.html')) {
|
|
76626
|
-
return 'text/html; charset=utf-8';
|
|
76627
|
-
}
|
|
76628
|
-
if (filePath.endsWith('.js')) {
|
|
76629
|
-
return 'text/javascript; charset=utf-8';
|
|
76630
|
-
}
|
|
76631
|
-
if (filePath.endsWith('.css')) {
|
|
76632
|
-
return 'text/css; charset=utf-8';
|
|
76633
|
-
}
|
|
76634
|
-
if (filePath.endsWith('.json')) {
|
|
76635
|
-
return 'application/json; charset=utf-8';
|
|
76636
|
-
}
|
|
76637
|
-
if (filePath.endsWith('.svg')) {
|
|
76638
|
-
return 'image/svg+xml';
|
|
76639
|
-
}
|
|
76640
|
-
return 'application/octet-stream';
|
|
76641
|
-
}
|
|
76642
|
-
async function listenHttpServer(server, options, getPortImpl) {
|
|
76643
|
-
const maxAttempts = 20;
|
|
76644
|
-
const port = await getPortImpl({
|
|
76645
|
-
host: options.host,
|
|
76646
|
-
port: createPortCandidates(options.port, maxAttempts),
|
|
76647
|
-
});
|
|
76648
|
-
if (port < options.port || port >= options.port + maxAttempts) {
|
|
76649
|
-
throw new Error(`无法找到可用 mock host 端口,起始端口: ${options.port}`);
|
|
76650
|
-
}
|
|
76651
|
-
await new Promise((resolve, reject) => {
|
|
76652
|
-
const onError = (error) => {
|
|
76653
|
-
server.off('listening', onListening);
|
|
76654
|
-
reject(error);
|
|
76655
|
-
};
|
|
76656
|
-
const onListening = () => {
|
|
76657
|
-
server.off('error', onError);
|
|
76658
|
-
resolve();
|
|
76659
|
-
};
|
|
76660
|
-
server.once('error', onError);
|
|
76661
|
-
server.once('listening', onListening);
|
|
76662
|
-
server.listen(port, options.host);
|
|
76663
|
-
});
|
|
76664
|
-
const address = server.address();
|
|
76665
|
-
return address.port;
|
|
76666
|
-
}
|
|
76667
|
-
function createPortCandidates(startPort, count) {
|
|
76668
|
-
return Array.from({ length: count }, (_, index) => startPort + index);
|
|
76669
|
-
}
|
|
76670
|
-
function createMockHostUrl(options) {
|
|
76671
|
-
const url = new URL(`http://${toDisplayHost(options.host)}:${options.port}/`);
|
|
76672
|
-
url.searchParams.set(MINI_PROGRAM_URL_QUERY_PARAM, options.appUrl);
|
|
76673
|
-
return url.toString();
|
|
76674
|
-
}
|
|
76675
76971
|
async function withManagedDevOutputEnv(action, env = process.env) {
|
|
76676
76972
|
const previous = env[MANAGED_DEV_OUTPUT_ENV];
|
|
76677
76973
|
env[MANAGED_DEV_OUTPUT_ENV] = '1';
|
|
@@ -76695,7 +76991,7 @@ function toDisplayHost(host) {
|
|
|
76695
76991
|
}
|
|
76696
76992
|
function installShutdownHandlers(closers, processLike) {
|
|
76697
76993
|
const shutdown = async () => {
|
|
76698
|
-
await
|
|
76994
|
+
await closeAll(closers);
|
|
76699
76995
|
processLike.exit(0);
|
|
76700
76996
|
};
|
|
76701
76997
|
processLike.once('SIGINT', () => {
|
|
@@ -76705,13 +77001,18 @@ function installShutdownHandlers(closers, processLike) {
|
|
|
76705
77001
|
void shutdown();
|
|
76706
77002
|
});
|
|
76707
77003
|
}
|
|
77004
|
+
async function closeAll(closers) {
|
|
77005
|
+
await Promise.allSettled(closers.map((close) => close()));
|
|
77006
|
+
}
|
|
77007
|
+
|
|
77008
|
+
const HB_SDK_PACKAGE_NAME = '@heybox/hb-sdk';
|
|
77009
|
+
const HB_SDK_SKILL_NAME = 'hb-sdk';
|
|
77010
|
+
const HB_SDK_AGENT_SKILLS_BASE_URL = 'https://open.xiaoheihe.cn/agent-skills';
|
|
77011
|
+
const HB_SDK_SKILL_SOURCE = `${HB_SDK_AGENT_SKILLS_BASE_URL}/${HB_SDK_SKILL_NAME}`;
|
|
77012
|
+
const HB_SDK_SKILL_INDEX_URL = `${HB_SDK_AGENT_SKILLS_BASE_URL}/.well-known/agent-skills/index.json`;
|
|
77013
|
+
const HB_SDK_SKILL_INSTALL_COMMAND = `npx skills add ${HB_SDK_SKILL_SOURCE}`;
|
|
76708
77014
|
|
|
76709
|
-
const PACKAGE_NAME$1 = '@heybox/hb-sdk';
|
|
76710
|
-
const SKILL_NAME = 'hb-sdk';
|
|
76711
|
-
const DEFAULT_SKILL_SOURCE = 'https://open.xiaoheihe.cn/agent-skills/hb-sdk';
|
|
76712
|
-
const DEFAULT_REMOTE_INDEX_URL = 'https://open.xiaoheihe.cn/agent-skills/.well-known/agent-skills/index.json';
|
|
76713
77015
|
const DEFAULT_TIMEOUT_MS$1 = 3000;
|
|
76714
|
-
const SKILL_INSTALL_COMMAND = `npx skills add ${DEFAULT_SKILL_SOURCE}`;
|
|
76715
77016
|
const PACKAGE_JSON_CANDIDATES$2 = [
|
|
76716
77017
|
path.resolve(__dirname, '..', 'package.json'),
|
|
76717
77018
|
path.resolve(__dirname, '..', '..', 'package.json'),
|
|
@@ -76756,7 +77057,7 @@ async function getDoctorResult(runtime = {}) {
|
|
|
76756
77057
|
};
|
|
76757
77058
|
}
|
|
76758
77059
|
if (!localSkill.manifest ||
|
|
76759
|
-
localSkill.manifest.name !==
|
|
77060
|
+
localSkill.manifest.name !== HB_SDK_SKILL_NAME ||
|
|
76760
77061
|
localSkill.manifest.skillVersion !== remoteSkill.version ||
|
|
76761
77062
|
localSkill.manifest.sdk?.version !== remoteSkill.sdk?.version) {
|
|
76762
77063
|
return {
|
|
@@ -76788,26 +77089,26 @@ function printDoctorNextStep(result, output) {
|
|
|
76788
77089
|
return;
|
|
76789
77090
|
}
|
|
76790
77091
|
if (result.status === 'SDK_MISMATCH') {
|
|
76791
|
-
output.log(`[hb-sdk] Current SDK does not match the latest skill metadata. Upgrade with: npm i -D ${
|
|
77092
|
+
output.log(`[hb-sdk] Current SDK does not match the latest skill metadata. Upgrade with: npm i -D ${HB_SDK_PACKAGE_NAME}@latest`);
|
|
76792
77093
|
output.log(`[hb-sdk] Then install or refresh the skill manually: ${formatSkillInstallCommand(result)}`);
|
|
76793
77094
|
return;
|
|
76794
77095
|
}
|
|
76795
77096
|
if (result.status === 'REMOTE_UNAVAILABLE') {
|
|
76796
77097
|
output.log('[hb-sdk] Remote skill metadata is unavailable. Try again later.');
|
|
76797
|
-
output.log(`[hb-sdk] Manual install command: ${
|
|
77098
|
+
output.log(`[hb-sdk] Manual install command: ${HB_SDK_SKILL_INSTALL_COMMAND}`);
|
|
76798
77099
|
return;
|
|
76799
77100
|
}
|
|
76800
77101
|
output.log(`[hb-sdk] Install or refresh the skill manually: ${formatSkillInstallCommand(result)}`);
|
|
76801
77102
|
}
|
|
76802
77103
|
function formatSkillInstallCommand(result) {
|
|
76803
|
-
return `npx skills add ${result.remoteSkill?.source ||
|
|
77104
|
+
return `npx skills add ${result.remoteSkill?.source || HB_SDK_SKILL_SOURCE}`;
|
|
76804
77105
|
}
|
|
76805
77106
|
async function fetchRemoteSkill(runtime) {
|
|
76806
77107
|
const fetchImpl = runtime.fetchImpl ?? fetch;
|
|
76807
77108
|
const controller = new AbortController();
|
|
76808
77109
|
const timeout = setTimeout(() => controller.abort(), runtime.timeoutMs ?? DEFAULT_TIMEOUT_MS$1);
|
|
76809
77110
|
try {
|
|
76810
|
-
const response = await fetchImpl(runtime.remoteIndexUrl ??
|
|
77111
|
+
const response = await fetchImpl(runtime.remoteIndexUrl ?? HB_SDK_SKILL_INDEX_URL, {
|
|
76811
77112
|
headers: {
|
|
76812
77113
|
accept: 'application/json',
|
|
76813
77114
|
},
|
|
@@ -76817,8 +77118,8 @@ async function fetchRemoteSkill(runtime) {
|
|
|
76817
77118
|
throw new Error(`remote skill index returned ${response.status}`);
|
|
76818
77119
|
}
|
|
76819
77120
|
const index = (await response.json());
|
|
76820
|
-
const skill = index.skills?.find(item => item.name ===
|
|
76821
|
-
if (!skill?.version || skill.sdk?.package !==
|
|
77121
|
+
const skill = index.skills?.find(item => item.name === HB_SDK_SKILL_NAME);
|
|
77122
|
+
if (!skill?.version || skill.sdk?.package !== HB_SDK_PACKAGE_NAME || !skill.sdk.version) {
|
|
76822
77123
|
throw new Error('remote hb-sdk skill metadata is incomplete');
|
|
76823
77124
|
}
|
|
76824
77125
|
return skill;
|
|
@@ -76862,7 +77163,7 @@ function resolveLocalSkillJsonPath(runtime) {
|
|
|
76862
77163
|
return runtime.localSkillJsonPath;
|
|
76863
77164
|
}
|
|
76864
77165
|
const codexHome = runtime.codexHome ?? runtime.env?.CODEX_HOME ?? process.env.CODEX_HOME ?? path.join(os.homedir(), '.codex');
|
|
76865
|
-
return path.join(codexHome, 'skills',
|
|
77166
|
+
return path.join(codexHome, 'skills', HB_SDK_SKILL_NAME, 'skill.json');
|
|
76866
77167
|
}
|
|
76867
77168
|
async function pathExists$2(filePath) {
|
|
76868
77169
|
try {
|
|
@@ -77028,12 +77329,11 @@ async function clearLoginStatus(options = {}) {
|
|
|
77028
77329
|
output.log(`cache: ${getAuthCacheFilePath(options)}`);
|
|
77029
77330
|
}
|
|
77030
77331
|
|
|
77031
|
-
const PACKAGE_NAME = '@heybox/hb-sdk';
|
|
77032
77332
|
const UPDATE_CHECK_CACHE_VERSION = 1;
|
|
77033
77333
|
const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
|
|
77034
77334
|
const DEFAULT_TIMEOUT_MS = 1500;
|
|
77035
77335
|
const UPDATE_CHECK_CACHE_FILE = 'update-check.json';
|
|
77036
|
-
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(
|
|
77336
|
+
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(HB_SDK_PACKAGE_NAME)}`;
|
|
77037
77337
|
const paths = envPaths('hb-sdk', { suffix: '' });
|
|
77038
77338
|
const PACKAGE_JSON_CANDIDATES$1 = [
|
|
77039
77339
|
path.resolve(__dirname, '..', 'package.json'),
|
|
@@ -77082,7 +77382,7 @@ async function getUpdateReminder(options = {}) {
|
|
|
77082
77382
|
return createUpdateReminder(currentVersion, latestVersion);
|
|
77083
77383
|
}
|
|
77084
77384
|
function formatUpdateReminder(reminder) {
|
|
77085
|
-
return `[hb-sdk] New version available: ${reminder.currentVersion} -> ${reminder.latestVersion}. Upgrade with: npm i -D ${
|
|
77385
|
+
return `[hb-sdk] New version available: ${reminder.currentVersion} -> ${reminder.latestVersion}. Upgrade with: npm i -D ${HB_SDK_PACKAGE_NAME}@latest`;
|
|
77086
77386
|
}
|
|
77087
77387
|
function isVersionGreater(version, baseline) {
|
|
77088
77388
|
const compared = compareSemver(version, baseline);
|
|
@@ -77259,7 +77559,7 @@ async function pathExists$1(filePath) {
|
|
|
77259
77559
|
}
|
|
77260
77560
|
|
|
77261
77561
|
const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
|
|
77262
|
-
const BUILT_CLI_VERSION = '0.
|
|
77562
|
+
const BUILT_CLI_VERSION = '0.3.1';
|
|
77263
77563
|
const PACKAGE_JSON_CANDIDATES = [
|
|
77264
77564
|
path.resolve(__dirname, '..', '..', 'package.json'),
|
|
77265
77565
|
path.resolve(__dirname, '..', 'package.json'),
|