@ttmg/cli 0.3.2-beta.9 → 0.3.3
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/CHANGELOG.md +4 -1
- package/dist/index.js +166 -23
- package/dist/index.js.map +1 -1
- package/dist/package.json +2 -2
- package/dist/public/assets/{index-DCvzzS3c.js → index-BBJshfB_.js} +1 -1
- package/dist/public/assets/index-BBJshfB_.js.br +0 -0
- package/dist/public/assets/{index-CZeMe3yb.js → index-Bxrlcdy9.js} +1 -1
- package/dist/public/assets/index-Bxrlcdy9.js.br +0 -0
- package/dist/public/assets/{index-BGB_3rmy.js → index-CgXh9-IR.js} +2 -2
- package/dist/public/assets/index-CgXh9-IR.js.br +0 -0
- package/dist/public/assets/{index-B7gDE9jg.js → index-CnpdpEXV.js} +1 -1
- package/dist/public/assets/{index-BGxy8aq-.js → index-DZ4Lot5a.js} +1 -1
- package/dist/public/assets/index-DZ4Lot5a.js.br +0 -0
- package/dist/public/assets/index-DZSJz0Hu.js +1 -0
- package/dist/public/assets/{index-DZh72DCT.js → index-D_UafQRj.js} +1 -1
- package/dist/public/assets/{index-dPxUjVAV.js → index-DqhIu6n9.js} +1 -1
- package/dist/public/assets/{index-C-hKdJe4.js → index-Dwl4ZYBR.js} +1 -1
- package/dist/public/assets/{index-Be7GH3NR.js → index-IjT-c81T.js} +1 -1
- package/dist/public/assets/{index-NjsKimh-.js → index-liPKaTSM.js} +1 -1
- package/dist/public/assets/{index-DTYGiGBE.js → index-maYHtPXK.js} +1 -1
- package/dist/public/index.html +1 -1
- package/package.json +2 -2
- package/dist/public/assets/index-BGB_3rmy.js.br +0 -0
- package/dist/public/assets/index-BGxy8aq-.js.br +0 -0
- package/dist/public/assets/index-CZeMe3yb.js.br +0 -0
- package/dist/public/assets/index-DCvzzS3c.js.br +0 -0
- package/dist/public/assets/index-sz2rmYug.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -198,4 +198,7 @@ API 预检建议文案统一收敛,避免重复提示,阅读更清晰
|
|
|
198
198
|
顶部区域透出项目预检错误与警告信息,便于开发者及时发现问题并修复
|
|
199
199
|
语言选择策略优化:优先使用 CLI 本地设置,未设置时自动回退浏览器语言
|
|
200
200
|
启动校验增强:检查是否在小游戏根目录执行,对于分包配置 subPackages 给出明确报错,引导开发者修改为 subpackages
|
|
201
|
-
修复项目详情中展示的主包大小限制和代码预检不一致的情况
|
|
201
|
+
修复项目详情中展示的主包大小限制和代码预检不一致的情况
|
|
202
|
+
|
|
203
|
+
## 0.3.3
|
|
204
|
+
升级 ttmg-pack 到 0.4.5,解决安卓无法调试 unity 项目问题
|
package/dist/index.js
CHANGED
|
@@ -6507,7 +6507,14 @@ const getCurrentUser = () => {
|
|
|
6507
6507
|
// ppe_dev_tool
|
|
6508
6508
|
function getAxiosProxyConfig() {
|
|
6509
6509
|
const config = getTTMGRC();
|
|
6510
|
-
|
|
6510
|
+
// 优先级: http-proxy > socks-proxy > proxy (老字段兼容)
|
|
6511
|
+
let proxyUrl = config?.['http-proxy'];
|
|
6512
|
+
if (!proxyUrl) {
|
|
6513
|
+
proxyUrl = config?.['socks-proxy'];
|
|
6514
|
+
}
|
|
6515
|
+
if (!proxyUrl) {
|
|
6516
|
+
proxyUrl = config?.proxy;
|
|
6517
|
+
}
|
|
6511
6518
|
if (proxyUrl) {
|
|
6512
6519
|
let agent;
|
|
6513
6520
|
if (proxyUrl.startsWith('socks')) {
|
|
@@ -6779,6 +6786,7 @@ const messages = {
|
|
|
6779
6786
|
'cli.option.dev.h5': 'Debug TikTok Mini Games for Web',
|
|
6780
6787
|
'cli.command.login.desc': 'Login with developer account',
|
|
6781
6788
|
'cli.command.login.verbose': 'Print verbose logs for debugging',
|
|
6789
|
+
'cli.command.logout.desc': 'Logout and clear local user data',
|
|
6782
6790
|
'cli.command.setup.desc': 'Initialize ttmg environment',
|
|
6783
6791
|
'cli.command.setup.lang': 'Language (only supports): en-US | zh-CN',
|
|
6784
6792
|
'cli.command.reset.desc': 'Reset local CLI state',
|
|
@@ -6789,6 +6797,10 @@ const messages = {
|
|
|
6789
6797
|
'cli.command.config.set.desc': 'Set a configuration value',
|
|
6790
6798
|
'cli.command.config.get.desc': 'Get a configuration value',
|
|
6791
6799
|
'cli.command.config.delete.desc': 'Delete a configuration value',
|
|
6800
|
+
'cli.command.upload.desc': 'Upload Mini Game to Developer Platform',
|
|
6801
|
+
'cli.command.upload.clientKey': 'Client Key of the Mini Game',
|
|
6802
|
+
'cli.command.upload.note': 'Note for the upload',
|
|
6803
|
+
'cli.command.upload.dir': 'Game project directory (default: current directory)',
|
|
6792
6804
|
'cli.option.h5': 'H5 Mini Game',
|
|
6793
6805
|
'cli.native.init.placeholder': 'Native Mini Game initialize',
|
|
6794
6806
|
'cli.native.build.placeholder': 'Native Mini Game bundle',
|
|
@@ -6830,9 +6842,12 @@ const messages = {
|
|
|
6830
6842
|
'login.error.withCode': 'Login failed: {message}, error_code: {code}',
|
|
6831
6843
|
'login.error.withMessage': 'Login failed: {message}',
|
|
6832
6844
|
'login.error.noUserId': 'Login failed. No user_id in response.',
|
|
6833
|
-
'login.warning.proxyIssue': 'The response does not look like the login API (e.g. proxy returned "Connection established" instead of forwarding the real response).\n\nThe API is not reachable from mainland without proxy. Please ensure your proxy correctly forwards HTTPS to developers.tiktok.com: try another proxy node, or
|
|
6845
|
+
'login.warning.proxyIssue': 'The response does not look like the login API (e.g. proxy returned "Connection established" instead of forwarding the real response).\n\nThe API is not reachable from mainland without proxy. Please ensure your proxy correctly forwards HTTPS to developers.tiktok.com: try another proxy node, or configure the CLI internal proxy using `ttmg config set proxy socks5://...`.\n\nProxy troubleshooting doc:\nhttps://bytedance.larkoffice.com/wiki/PeIawT4M4ia9R8kYyLMcjwHknOg',
|
|
6834
6846
|
'login.error.connectService': 'Failed to connect to login service',
|
|
6835
|
-
'login.error.networkBlocked': "
|
|
6847
|
+
'login.error.networkBlocked': "Network connection failed. This is usually caused by advanced proxy settings (e.g., fake-ip mode) or incorrect terminal proxy environment variables.\n\nWe strongly recommend turning off global proxy mode and configuring the CLI internal proxy using:\n ttmg config set proxy socks5://127.0.0.1:<your_socks_port>\n\nFor detailed solutions, please refer to the proxy troubleshooting doc:\nhttps://bytedance.larkoffice.com/wiki/PeIawT4M4ia9R8kYyLMcjwHknOg",
|
|
6848
|
+
'logout.spinner.loggingOut': 'Logging out...',
|
|
6849
|
+
'logout.success': 'Logged out successfully!',
|
|
6850
|
+
'logout.fail': 'Logout failed: {error}',
|
|
6836
6851
|
'h5.dev.configMissing': '{file} is not exist, please run minis game init first',
|
|
6837
6852
|
'h5.dev.precheckTips': '⚠️ Before dev, please ensure:\n 1. The account used to login www.tiktok.com is in the sandbox target user range of Minis developer platform, otherwise login authorization will throw an error.\n 2. The browser allows www.tiktok.com <popup and redirect>, because the authorization login linkage needs to open a new tab popup for operation, otherwise the authorization login linkage will not be able to debug normally.',
|
|
6838
6853
|
'h5.dev.startingBanner': '\n \n============== start dev your game, it will take a few seconds ============ \n \n',
|
|
@@ -6884,8 +6899,16 @@ const messages = {
|
|
|
6884
6899
|
'native.tips.3': ' After scanning the QR code with your phone for Test User authentication,',
|
|
6885
6900
|
'native.tips.3.sub1': ' the compiled code package will be uploaded to the client automatically.',
|
|
6886
6901
|
'native.tips.3.sub2': ' Game debugging will start right away.',
|
|
6887
|
-
'native.tips.4': '
|
|
6888
|
-
'native.tips.4.sub1': '
|
|
6902
|
+
'native.tips.4': ' How to ensure a smooth connection?',
|
|
6903
|
+
'native.tips.4.sub1': ' https://bytedance.larkoffice.com/wiki/WvifwWjGri7bTzkPbqKcqVi5ntc',
|
|
6904
|
+
'upload.spinner.fetchInfo': 'Fetching game info for client key {clientKey} ...',
|
|
6905
|
+
'upload.spinner.zipping': 'Zipping game assets in directory: {dir} ...',
|
|
6906
|
+
'upload.spinner.uploading': 'Uploading game to platform (size: {size} MB)...',
|
|
6907
|
+
'upload.success': 'Upload success! View version at: {url}',
|
|
6908
|
+
'upload.fail': 'Upload failed: {error}',
|
|
6909
|
+
'upload.error.noClientKey': 'Client Key is required for upload. Use --client-key <key>',
|
|
6910
|
+
'upload.error.notLoggedIn': 'Not logged in. Please run `ttmg login` first.',
|
|
6911
|
+
'upload.error.dirNotExist': 'The specified directory does not exist: {dir}',
|
|
6889
6912
|
},
|
|
6890
6913
|
'zh-CN': {
|
|
6891
6914
|
'cli.description': 'TikTok 小游戏命令行工具',
|
|
@@ -6894,6 +6917,7 @@ const messages = {
|
|
|
6894
6917
|
'cli.option.dev.h5': 'Web 调试 TikTok 小游戏',
|
|
6895
6918
|
'cli.command.login.desc': '使用开发者账号登录',
|
|
6896
6919
|
'cli.command.login.verbose': '输出调试用详细日志',
|
|
6920
|
+
'cli.command.logout.desc': '退出登录并清除本地用户信息',
|
|
6897
6921
|
'cli.command.setup.desc': '初始化 ttmg 环境',
|
|
6898
6922
|
'cli.command.setup.lang': '语言(仅支持):en-US | zh-CN',
|
|
6899
6923
|
'cli.command.reset.desc': '重置本地 CLI 状态',
|
|
@@ -6904,6 +6928,10 @@ const messages = {
|
|
|
6904
6928
|
'cli.command.config.set.desc': '设置配置项',
|
|
6905
6929
|
'cli.command.config.get.desc': '获取配置项',
|
|
6906
6930
|
'cli.command.config.delete.desc': '删除配置项',
|
|
6931
|
+
'cli.command.upload.desc': '上传小游戏到开发者平台',
|
|
6932
|
+
'cli.command.upload.clientKey': '小游戏的 Client Key',
|
|
6933
|
+
'cli.command.upload.note': '上传备注',
|
|
6934
|
+
'cli.command.upload.dir': '小游戏项目根目录(默认为当前目录)',
|
|
6907
6935
|
'cli.option.h5': 'H5 小游戏',
|
|
6908
6936
|
'cli.native.init.placeholder': 'Native 小游戏初始化',
|
|
6909
6937
|
'cli.native.build.placeholder': 'Native 小游戏打包',
|
|
@@ -6945,9 +6973,12 @@ const messages = {
|
|
|
6945
6973
|
'login.error.withCode': '登录失败:{message},错误码:{code}',
|
|
6946
6974
|
'login.error.withMessage': '登录失败:{message}',
|
|
6947
6975
|
'login.error.noUserId': '登录失败,响应中未返回 user_id。',
|
|
6948
|
-
'login.warning.proxyIssue': '当前响应看起来不是登录接口返回(例如代理返回了 "Connection established",而不是转发真实响应)。\n\n该接口在大陆网络通常需要代理。请确认代理可正确转发 developers.tiktok.com 的 HTTPS
|
|
6976
|
+
'login.warning.proxyIssue': '当前响应看起来不是登录接口返回(例如代理返回了 "Connection established",而不是转发真实响应)。\n\n该接口在大陆网络通常需要代理。请确认代理可正确转发 developers.tiktok.com 的 HTTPS 请求:尝试切换节点,或者使用 `ttmg config set proxy socks5://...` 配置 CLI 内置代理。\n\n代理排查文档:\nhttps://bytedance.larkoffice.com/wiki/PeIawT4M4ia9R8kYyLMcjwHknOg',
|
|
6949
6977
|
'login.error.connectService': '连接登录服务失败',
|
|
6950
|
-
'login.error.networkBlocked': '
|
|
6978
|
+
'login.error.networkBlocked': '网络连接失败。这通常是由于代理软件的高级设置(如 fake-ip 模式)或终端残留了错误的代理环境变量导致的。\n\n我们强烈建议你关闭全局代理,并为 CLI 配置内置 SOCKS5 代理:\n ttmg config set proxy socks5://127.0.0.1:<你的socks端口>\n\n详细排查方案请参考最新代理设置文档:\nhttps://bytedance.larkoffice.com/wiki/PeIawT4M4ia9R8kYyLMcjwHknOg',
|
|
6979
|
+
'logout.spinner.loggingOut': '正在退出登录...',
|
|
6980
|
+
'logout.success': '退出登录成功!',
|
|
6981
|
+
'logout.fail': '退出登录失败:{error}',
|
|
6951
6982
|
'h5.dev.configMissing': '{file} 不存在,请先执行 minis game init',
|
|
6952
6983
|
'h5.dev.precheckTips': '⚠️ 开始调试前请确认:\n 1. 当前登录 www.tiktok.com 的账号在小程序开发者平台沙盒目标用户范围内,否则登录授权会报错。\n 2. 浏览器允许 www.tiktok.com 弹窗与重定向,授权登录链路需要新开标签页进行操作,否则无法正常调试。',
|
|
6953
6984
|
'h5.dev.startingBanner': '\n \n============== 已开始调试你的游戏,通常需要几秒钟 ============ \n \n',
|
|
@@ -6999,8 +7030,16 @@ const messages = {
|
|
|
6999
7030
|
'native.tips.3': ' 手机扫码通过 Test User 认证后,',
|
|
7000
7031
|
'native.tips.3.sub1': ' 编译后的代码包会自动上传到客户端。',
|
|
7001
7032
|
'native.tips.3.sub2': ' 随即开始游戏调试。',
|
|
7002
|
-
'native.tips.4': '
|
|
7003
|
-
'native.tips.4.sub1': '
|
|
7033
|
+
'native.tips.4': ' 如何保证可以顺利连接?',
|
|
7034
|
+
'native.tips.4.sub1': ' https://bytedance.larkoffice.com/wiki/WvifwWjGri7bTzkPbqKcqVi5ntc',
|
|
7035
|
+
'upload.spinner.fetchInfo': '正在获取游戏信息 (client key: {clientKey}) ...',
|
|
7036
|
+
'upload.spinner.zipping': '正在压缩游戏资源目录: {dir} ...',
|
|
7037
|
+
'upload.spinner.uploading': '正在上传游戏到平台 (大小: {size} MB) ...',
|
|
7038
|
+
'upload.success': '上传成功!可在以下地址查看版本:{url}',
|
|
7039
|
+
'upload.fail': '上传失败:{error}',
|
|
7040
|
+
'upload.error.noClientKey': '上传必须提供 Client Key,请使用 --client-key <key> 参数',
|
|
7041
|
+
'upload.error.notLoggedIn': '未登录,请先执行 `ttmg login` 登录开发者平台账号。',
|
|
7042
|
+
'upload.error.dirNotExist': '指定的项目目录不存在:{dir}',
|
|
7004
7043
|
},
|
|
7005
7044
|
};
|
|
7006
7045
|
|
|
@@ -8458,15 +8497,16 @@ function showTips(context) {
|
|
|
8458
8497
|
console.log('');
|
|
8459
8498
|
console.log(chalk.red.bold('4. ⚠️') +
|
|
8460
8499
|
t('native.tips.4'));
|
|
8461
|
-
console.log(t('native.tips.4.sub1'));
|
|
8500
|
+
console.log(chalk.cyan.underline(t('native.tips.4.sub1')));
|
|
8462
8501
|
console.log(chalk.gray('─────────────────────────────────────────────'));
|
|
8463
8502
|
}
|
|
8464
8503
|
|
|
8465
8504
|
/**
|
|
8466
|
-
*
|
|
8505
|
+
* 辅助函数:将指定目录(默认为当前工作目录)打包为 Buffer
|
|
8467
8506
|
* @param customIgnores - 可选的自定义忽略规则数组 (支持 glob 模式,如 ['dist/**', '*.log'])
|
|
8507
|
+
* @param targetDir - 可选的目标目录,默认为 process.cwd()
|
|
8468
8508
|
*/
|
|
8469
|
-
const zipCwdToBuffer = (customIgnores = []) => {
|
|
8509
|
+
const zipCwdToBuffer = (customIgnores = [], targetDir = process.cwd()) => {
|
|
8470
8510
|
return new Promise((resolve, reject) => {
|
|
8471
8511
|
const chunks = [];
|
|
8472
8512
|
const output = new require$$2$1.Writable({
|
|
@@ -8483,7 +8523,6 @@ const zipCwdToBuffer = (customIgnores = []) => {
|
|
|
8483
8523
|
reject(err);
|
|
8484
8524
|
});
|
|
8485
8525
|
archive.pipe(output);
|
|
8486
|
-
const cwd = process.cwd();
|
|
8487
8526
|
// 1. 基础忽略列表 (建议保留这些基础规则,防止包过大)
|
|
8488
8527
|
const defaultIgnores = [
|
|
8489
8528
|
'node_modules/**',
|
|
@@ -8498,7 +8537,7 @@ const zipCwdToBuffer = (customIgnores = []) => {
|
|
|
8498
8537
|
// 3. 执行打包
|
|
8499
8538
|
// 注意:ignore 规则必须使用正斜杠 /,即使在 Windows 下
|
|
8500
8539
|
archive.glob('**/*', {
|
|
8501
|
-
cwd:
|
|
8540
|
+
cwd: targetDir,
|
|
8502
8541
|
ignore: finalIgnores,
|
|
8503
8542
|
dot: true, // 包含 .env 等点文件
|
|
8504
8543
|
});
|
|
@@ -10281,6 +10320,7 @@ async function login(options) {
|
|
|
10281
10320
|
headers,
|
|
10282
10321
|
maxRedirects: 20,
|
|
10283
10322
|
timeout: 30000,
|
|
10323
|
+
...getAxiosProxyConfig(),
|
|
10284
10324
|
});
|
|
10285
10325
|
log('Response status', response.status);
|
|
10286
10326
|
log('Response data', response?.data);
|
|
@@ -10345,6 +10385,30 @@ async function login(options) {
|
|
|
10345
10385
|
}
|
|
10346
10386
|
}
|
|
10347
10387
|
|
|
10388
|
+
async function logout() {
|
|
10389
|
+
const ora = await import('ora');
|
|
10390
|
+
const spinner = ora.default({
|
|
10391
|
+
text: chalk.cyan.bold(t('logout.spinner.loggingOut')),
|
|
10392
|
+
spinner: 'dots',
|
|
10393
|
+
}).start();
|
|
10394
|
+
try {
|
|
10395
|
+
const config = getTTMGRC();
|
|
10396
|
+
if (config) {
|
|
10397
|
+
// Remove sensitive user info
|
|
10398
|
+
delete config.email;
|
|
10399
|
+
delete config.user_id;
|
|
10400
|
+
delete config.cookie;
|
|
10401
|
+
resetTTMGRC(config);
|
|
10402
|
+
}
|
|
10403
|
+
spinner.succeed(chalk.green.bold(t('logout.success')));
|
|
10404
|
+
process.exit(0);
|
|
10405
|
+
}
|
|
10406
|
+
catch (err) {
|
|
10407
|
+
spinner.fail(chalk.red.bold(t('logout.fail', { error: err.message || String(err) })));
|
|
10408
|
+
process.exit(1);
|
|
10409
|
+
}
|
|
10410
|
+
}
|
|
10411
|
+
|
|
10348
10412
|
const supportedLangs$1 = ['en-US', 'zh-CN'];
|
|
10349
10413
|
function isSupportedLang$1(lang) {
|
|
10350
10414
|
return supportedLangs$1.includes(lang);
|
|
@@ -10448,9 +10512,9 @@ const config = {
|
|
|
10448
10512
|
spinner.fail(chalk.red(`Value is required for config key: ${key}`));
|
|
10449
10513
|
process.exit(1);
|
|
10450
10514
|
}
|
|
10451
|
-
if (key === 'proxy') {
|
|
10452
|
-
setTTMGRC({
|
|
10453
|
-
spinner.succeed(chalk.green(`Set
|
|
10515
|
+
if (key === 'proxy' || key === 'http-proxy' || key === 'socks-proxy') {
|
|
10516
|
+
setTTMGRC({ [key]: value });
|
|
10517
|
+
spinner.succeed(chalk.green(`Set ${key} to ${value}`));
|
|
10454
10518
|
}
|
|
10455
10519
|
else if (key === 'lang') {
|
|
10456
10520
|
if (!isSupportedLang(value)) {
|
|
@@ -10476,8 +10540,8 @@ const config = {
|
|
|
10476
10540
|
const spinner = ora(`Getting ${key}...`).start();
|
|
10477
10541
|
try {
|
|
10478
10542
|
const rc = getTTMGRC();
|
|
10479
|
-
if (key === 'proxy') {
|
|
10480
|
-
spinner.succeed(chalk.green(
|
|
10543
|
+
if (key === 'proxy' || key === 'http-proxy' || key === 'socks-proxy') {
|
|
10544
|
+
spinner.succeed(chalk.green(`${key}=${rc?.[key] || ''}`));
|
|
10481
10545
|
}
|
|
10482
10546
|
else if (key === 'lang') {
|
|
10483
10547
|
spinner.succeed(chalk.green(`lang=${rc?.lang || ''}`));
|
|
@@ -10496,9 +10560,9 @@ const config = {
|
|
|
10496
10560
|
const ora = (oraModule.default || oraModule);
|
|
10497
10561
|
const spinner = ora(`Deleting ${key}...`).start();
|
|
10498
10562
|
try {
|
|
10499
|
-
if (key === 'proxy') {
|
|
10500
|
-
setTTMGRC({
|
|
10501
|
-
spinner.succeed(chalk.green(`Deleted
|
|
10563
|
+
if (key === 'proxy' || key === 'http-proxy' || key === 'socks-proxy') {
|
|
10564
|
+
setTTMGRC({ [key]: undefined });
|
|
10565
|
+
spinner.succeed(chalk.green(`Deleted ${key} config`));
|
|
10502
10566
|
}
|
|
10503
10567
|
else if (key === 'lang') {
|
|
10504
10568
|
setTTMGRC({ lang: undefined });
|
|
@@ -10515,7 +10579,71 @@ const config = {
|
|
|
10515
10579
|
}
|
|
10516
10580
|
};
|
|
10517
10581
|
|
|
10518
|
-
|
|
10582
|
+
async function upload({ clientKey, note = '--', dir, }) {
|
|
10583
|
+
const ora = await import('ora');
|
|
10584
|
+
const spinner = ora.default({
|
|
10585
|
+
text: chalk.cyan.bold(t('upload.spinner.fetchInfo', { clientKey: clientKey || 'unknown' })),
|
|
10586
|
+
spinner: 'dots',
|
|
10587
|
+
}).start();
|
|
10588
|
+
try {
|
|
10589
|
+
console.log(chalk.gray(`[upload] Start uploading process...`));
|
|
10590
|
+
console.log(chalk.gray(`[upload] Parameters: clientKey=${clientKey}, note=${note}, dir=${dir || process.cwd()}`));
|
|
10591
|
+
const user = getCurrentUser();
|
|
10592
|
+
if (!user || !user.cookie) {
|
|
10593
|
+
throw new Error(t('upload.error.notLoggedIn'));
|
|
10594
|
+
}
|
|
10595
|
+
if (!clientKey) {
|
|
10596
|
+
throw new Error(t('upload.error.noClientKey'));
|
|
10597
|
+
}
|
|
10598
|
+
// 1. 获取游戏信息,主要是为了拿 appId
|
|
10599
|
+
console.log(chalk.gray(`[upload] Step 1: Fetching game info for clientKey ${clientKey}`));
|
|
10600
|
+
const infoRes = await fetchGameInfo(clientKey);
|
|
10601
|
+
console.log(chalk.gray(`[upload] Game info response: ${JSON.stringify(infoRes)}`));
|
|
10602
|
+
if (infoRes.error) {
|
|
10603
|
+
throw new Error(infoRes.error.errorMsg || 'Failed to fetch game info');
|
|
10604
|
+
}
|
|
10605
|
+
const appId = infoRes.data?.app_id;
|
|
10606
|
+
const name = infoRes.data?.name || 'game';
|
|
10607
|
+
if (!appId) {
|
|
10608
|
+
throw new Error('No appId found for this client key');
|
|
10609
|
+
}
|
|
10610
|
+
// 2. 打包指定或当前目录
|
|
10611
|
+
const targetDir = dir ? path.resolve(process.cwd(), dir) : process.cwd();
|
|
10612
|
+
// 检查目录是否存在
|
|
10613
|
+
if (!fs.existsSync(targetDir)) {
|
|
10614
|
+
throw new Error(t('upload.error.dirNotExist', { dir: targetDir }));
|
|
10615
|
+
}
|
|
10616
|
+
console.log(chalk.gray(`[upload] Step 2: Zipping directory ${targetDir}`));
|
|
10617
|
+
spinner.text = chalk.cyan.bold(t('upload.spinner.zipping', { dir: targetDir }));
|
|
10618
|
+
const zipBuffer = await zipCwdToBuffer([], targetDir);
|
|
10619
|
+
// 计算文件大小 (MB)
|
|
10620
|
+
const fileSizeMB = (zipBuffer.length / (1024 * 1024)).toFixed(2);
|
|
10621
|
+
console.log(chalk.gray(`[upload] Zipping completed. File size: ${fileSizeMB} MB`));
|
|
10622
|
+
// 3. 上传到平台
|
|
10623
|
+
console.log(chalk.gray(`[upload] Step 3: Uploading to platform...`));
|
|
10624
|
+
spinner.text = chalk.cyan.bold(t('upload.spinner.uploading', { size: fileSizeMB }));
|
|
10625
|
+
const uploadRes = await uploadGameToPlatform({
|
|
10626
|
+
data: zipBuffer.buffer.slice(zipBuffer.byteOffset, zipBuffer.byteOffset + zipBuffer.byteLength),
|
|
10627
|
+
name,
|
|
10628
|
+
clientKey,
|
|
10629
|
+
note,
|
|
10630
|
+
appId,
|
|
10631
|
+
});
|
|
10632
|
+
console.log(chalk.gray(`[upload] Upload response: ${JSON.stringify({ ...uploadRes, data: uploadRes.data ? { ...uploadRes.data, detail: uploadRes.data.detail } : null })}`));
|
|
10633
|
+
if (uploadRes.error) {
|
|
10634
|
+
throw new Error(uploadRes.error.message || 'Upload failed');
|
|
10635
|
+
}
|
|
10636
|
+
console.log(chalk.gray(`[upload] Upload finished successfully.`));
|
|
10637
|
+
spinner.succeed(chalk.green.bold(t('upload.success', { url: uploadRes.data?.detail || '' })));
|
|
10638
|
+
process.exit(0);
|
|
10639
|
+
}
|
|
10640
|
+
catch (error) {
|
|
10641
|
+
spinner.fail(chalk.red.bold(t('upload.fail', { error: error.message || String(error) })));
|
|
10642
|
+
process.exit(1);
|
|
10643
|
+
}
|
|
10644
|
+
}
|
|
10645
|
+
|
|
10646
|
+
var version = "0.3.3";
|
|
10519
10647
|
var pkg = {
|
|
10520
10648
|
version: version};
|
|
10521
10649
|
|
|
@@ -10534,6 +10662,21 @@ program
|
|
|
10534
10662
|
.action(async (cmd) => {
|
|
10535
10663
|
await login({ verbose: cmd.verbose });
|
|
10536
10664
|
});
|
|
10665
|
+
program
|
|
10666
|
+
.command('logout')
|
|
10667
|
+
.description(t('cli.command.logout.desc'))
|
|
10668
|
+
.action(async () => {
|
|
10669
|
+
await logout();
|
|
10670
|
+
});
|
|
10671
|
+
program
|
|
10672
|
+
.command('upload')
|
|
10673
|
+
.description(t('cli.command.upload.desc'))
|
|
10674
|
+
.option('-ck, --client-key <clientKey>', t('cli.command.upload.clientKey'))
|
|
10675
|
+
.option('-n, --note <note>', t('cli.command.upload.note'))
|
|
10676
|
+
.option('-d, --dir <dir>', t('cli.command.upload.dir'))
|
|
10677
|
+
.action(async (cmd) => {
|
|
10678
|
+
await upload({ clientKey: cmd.clientKey, note: cmd.note, dir: cmd.dir });
|
|
10679
|
+
});
|
|
10537
10680
|
program
|
|
10538
10681
|
.command('setup')
|
|
10539
10682
|
.description(t('cli.command.setup.desc'))
|