@ttmg/cli 0.3.6-beta.3 → 0.3.7-beta.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/CHANGELOG.md +4 -1
- package/dist/index.js +551 -66
- package/dist/index.js.map +1 -1
- package/dist/package.json +2 -2
- package/dist/public/assets/Detail-BInCTDTx.js +1 -0
- package/dist/public/assets/Detail-BInCTDTx.js.br +0 -0
- package/dist/public/assets/Detail-BaQ9eM95.css +1 -0
- package/dist/public/assets/{baseForm-Dnb99UJB.js → baseForm-B7tArmif.js} +4 -4
- package/dist/public/assets/baseForm-B7tArmif.js.br +0 -0
- package/dist/public/assets/{index-UihZn1LL.css → index-6LE--ADL.css} +1 -1
- package/dist/public/assets/index-6LE--ADL.css.br +0 -0
- package/dist/public/assets/index-AtMMzkp0.css +1 -0
- package/dist/public/assets/index-B-rc2X1H.js +1 -0
- package/dist/public/assets/index-B0CT2rYr.js +1 -0
- package/dist/public/assets/index-BACeBrQR.css +1 -0
- package/dist/public/assets/index-BOiN8aIS.js +1 -0
- package/dist/public/assets/index-BVi9swz_.js +1 -0
- package/dist/public/assets/index-BVi9swz_.js.br +0 -0
- package/dist/public/assets/index-BlXhGm9R.js +1 -0
- package/dist/public/assets/{index-BkiB8M4Y.css → index-BnU4EHWL.css} +1 -1
- package/dist/public/assets/index-BnU4EHWL.css.br +0 -0
- package/dist/public/assets/index-BswgGVlz.js +1 -0
- package/dist/public/assets/index-BswgGVlz.js.br +0 -0
- package/dist/public/assets/index-C4wGgEDm.css +1 -0
- package/dist/public/assets/{index-DHyyb3Gw.js → index-CDrq3KnY.js} +1 -1
- package/dist/public/assets/index-CH7igbHY.css +1 -0
- package/dist/public/assets/index-Cj-lTEG1.js +1 -0
- package/dist/public/assets/index-Cj-lTEG1.js.br +0 -0
- package/dist/public/assets/index-D35C4ac4.js +1 -0
- package/dist/public/assets/index-DQqzytdw.js +1 -0
- package/dist/public/assets/index-DQqzytdw.js.br +0 -0
- package/dist/public/assets/index-DbiZkOAh.css +1 -0
- package/dist/public/assets/{index-CqK4Ymjd.js → index-DdH9Yin-.js} +1 -1
- package/dist/public/assets/index-DkXWo3Jg.js +14 -0
- package/dist/public/assets/index-DkXWo3Jg.js.br +0 -0
- package/dist/public/assets/index-OIQapQiA.js +1 -0
- package/dist/public/assets/{index-BGkIaNEY.js → index-Sk6u8HWP.js} +1 -1
- package/dist/public/assets/index-TYa4eXxF.css +1 -0
- package/dist/public/assets/{index-DKKMC8UM.js → index-aD1InxYk.js} +1 -1
- package/dist/public/assets/index-jaMAKGHW.css +1 -0
- package/dist/public/assets/{index-C5pU_dUf.js → index-tXDZpXMk.js} +1 -1
- package/dist/public/assets/index-tXDZpXMk.js.br +0 -0
- package/dist/public/assets/times-CCIAbLYL.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/scripts/docs/capture.js +255 -0
- package/dist/scripts/docs/render.js +199 -0
- package/dist/scripts/docs/server.js +164 -0
- package/package.json +2 -2
- package/dist/public/assets/baseForm-Dnb99UJB.js.br +0 -0
- package/dist/public/assets/index-B8aFXzhN.js +0 -1
- package/dist/public/assets/index-BB5kLk47.css +0 -1
- package/dist/public/assets/index-BaXjsvp9.js +0 -1
- package/dist/public/assets/index-BedicqfR.css +0 -1
- package/dist/public/assets/index-BkiB8M4Y.css.br +0 -0
- package/dist/public/assets/index-BmSg7a2H.js +0 -14
- package/dist/public/assets/index-BmSg7a2H.js.br +0 -0
- package/dist/public/assets/index-Bovw-Ai8.js +0 -1
- package/dist/public/assets/index-Bovw-Ai8.js.br +0 -0
- package/dist/public/assets/index-Bq6YxKLX.css +0 -1
- package/dist/public/assets/index-BwbPFgZF.css +0 -1
- package/dist/public/assets/index-C5pU_dUf.js.br +0 -0
- package/dist/public/assets/index-C8f539tK.css +0 -1
- package/dist/public/assets/index-CJtCELuI.js +0 -1
- package/dist/public/assets/index-CPEErQsP.js +0 -1
- package/dist/public/assets/index-CkcOz6VJ.js +0 -1
- package/dist/public/assets/index-D0piMtcL.js +0 -1
- package/dist/public/assets/index-DNZgHncv.js +0 -1
- package/dist/public/assets/index-DhmPFuxl.css +0 -1
- package/dist/public/assets/index-OPfpZTmc.js +0 -1
- package/dist/public/assets/index-OPfpZTmc.js.br +0 -0
- package/dist/public/assets/index-UihZn1LL.css.br +0 -0
- package/dist/public/assets/index-vPoeqDW1.js +0 -1
- package/dist/public/assets/index-vPoeqDW1.js.br +0 -0
- package/dist/public/assets/index-yh4tKekV.css +0 -1
- package/dist/public/assets/isPlainObject-CKjwQ9bg.js +0 -1
- package/dist/public/assets/times-BsXqTKq4.js +0 -1
- /package/dist/public/assets/{index-C7C5ulLg.css → times-C7C5ulLg.css} +0 -0
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var inquirer = require('inquirer');
|
|
|
6
6
|
var path = require('path');
|
|
7
7
|
var os = require('os');
|
|
8
8
|
var axios = require('axios');
|
|
9
|
+
var chalk = require('chalk');
|
|
9
10
|
var net = require('net');
|
|
10
11
|
var require$$1$2 = require('tls');
|
|
11
12
|
var require$$2 = require('url');
|
|
@@ -21,7 +22,6 @@ var dns = require('dns');
|
|
|
21
22
|
var fs = require('fs');
|
|
22
23
|
var handlebars = require('handlebars');
|
|
23
24
|
var esbuild = require('esbuild');
|
|
24
|
-
var chalk = require('chalk');
|
|
25
25
|
var boxen = require('boxen');
|
|
26
26
|
var semver = require('semver');
|
|
27
27
|
var jsdom = require('jsdom');
|
|
@@ -6504,6 +6504,9 @@ const getCurrentUser = () => {
|
|
|
6504
6504
|
}
|
|
6505
6505
|
};
|
|
6506
6506
|
|
|
6507
|
+
function isVerboseEnabled() {
|
|
6508
|
+
return process.argv.includes('--verbose');
|
|
6509
|
+
}
|
|
6507
6510
|
// ppe_dev_tool
|
|
6508
6511
|
function getAxiosProxyConfig() {
|
|
6509
6512
|
const config = getTTMGRC();
|
|
@@ -6532,25 +6535,134 @@ function getAxiosProxyConfig() {
|
|
|
6532
6535
|
}
|
|
6533
6536
|
return {};
|
|
6534
6537
|
}
|
|
6538
|
+
function getRequestParams(params, data) {
|
|
6539
|
+
const hasQueryParams = !!params && Object.keys(params).length > 0;
|
|
6540
|
+
const normalizeRequestData = () => {
|
|
6541
|
+
if (!data) {
|
|
6542
|
+
return undefined;
|
|
6543
|
+
}
|
|
6544
|
+
if (Buffer.isBuffer(data)) {
|
|
6545
|
+
return `[Buffer ${data.length} bytes]`;
|
|
6546
|
+
}
|
|
6547
|
+
if (typeof data?.pipe === 'function') {
|
|
6548
|
+
return '[ReadableStream]';
|
|
6549
|
+
}
|
|
6550
|
+
if (typeof FormData !== 'undefined' && data instanceof FormData) {
|
|
6551
|
+
const entries = Array.from(data.entries()).map(([key, value]) => {
|
|
6552
|
+
if (typeof File !== 'undefined' && value instanceof File) {
|
|
6553
|
+
return [key, `[File ${value.name}, ${value.size} bytes]`];
|
|
6554
|
+
}
|
|
6555
|
+
return [key, value];
|
|
6556
|
+
});
|
|
6557
|
+
return Object.fromEntries(entries);
|
|
6558
|
+
}
|
|
6559
|
+
return data;
|
|
6560
|
+
};
|
|
6561
|
+
const normalizedData = normalizeRequestData();
|
|
6562
|
+
if (hasQueryParams && normalizedData !== undefined) {
|
|
6563
|
+
return {
|
|
6564
|
+
query: params,
|
|
6565
|
+
body: normalizedData,
|
|
6566
|
+
};
|
|
6567
|
+
}
|
|
6568
|
+
if (hasQueryParams) {
|
|
6569
|
+
return params;
|
|
6570
|
+
}
|
|
6571
|
+
if (normalizedData !== undefined) {
|
|
6572
|
+
return normalizedData;
|
|
6573
|
+
}
|
|
6574
|
+
return undefined;
|
|
6575
|
+
}
|
|
6576
|
+
function safeStringify(value) {
|
|
6577
|
+
if (typeof value === 'string') {
|
|
6578
|
+
return value;
|
|
6579
|
+
}
|
|
6580
|
+
if (value === undefined) {
|
|
6581
|
+
return '-';
|
|
6582
|
+
}
|
|
6583
|
+
const seen = new WeakSet();
|
|
6584
|
+
try {
|
|
6585
|
+
return JSON.stringify(value, (_key, currentValue) => {
|
|
6586
|
+
if (typeof currentValue === 'bigint') {
|
|
6587
|
+
return currentValue.toString();
|
|
6588
|
+
}
|
|
6589
|
+
if (Buffer.isBuffer(currentValue)) {
|
|
6590
|
+
return `[Buffer ${currentValue.length} bytes]`;
|
|
6591
|
+
}
|
|
6592
|
+
if (currentValue && typeof currentValue === 'object') {
|
|
6593
|
+
if (typeof currentValue.pipe === 'function') {
|
|
6594
|
+
return '[ReadableStream]';
|
|
6595
|
+
}
|
|
6596
|
+
if (seen.has(currentValue)) {
|
|
6597
|
+
return '[Circular]';
|
|
6598
|
+
}
|
|
6599
|
+
seen.add(currentValue);
|
|
6600
|
+
}
|
|
6601
|
+
return currentValue;
|
|
6602
|
+
}, 2);
|
|
6603
|
+
}
|
|
6604
|
+
catch {
|
|
6605
|
+
return String(value);
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6608
|
+
function getToneColor(tone) {
|
|
6609
|
+
if (tone === 'success') {
|
|
6610
|
+
return chalk.green;
|
|
6611
|
+
}
|
|
6612
|
+
if (tone === 'error') {
|
|
6613
|
+
return chalk.red;
|
|
6614
|
+
}
|
|
6615
|
+
return chalk.cyan;
|
|
6616
|
+
}
|
|
6617
|
+
function formatLogField(label, value) {
|
|
6618
|
+
const renderedValue = safeStringify(value);
|
|
6619
|
+
const lines = renderedValue.split('\n');
|
|
6620
|
+
const formattedLabel = chalk.whiteBright.bold(label.padEnd(12, ' '));
|
|
6621
|
+
if (lines.length === 1) {
|
|
6622
|
+
return [`│ ${formattedLabel} ${chalk.white(renderedValue)}`];
|
|
6623
|
+
}
|
|
6624
|
+
return [
|
|
6625
|
+
`│ ${formattedLabel}`,
|
|
6626
|
+
...lines.map(line => `│ ${chalk.dim(' '.repeat(13))}${chalk.white(line)}`),
|
|
6627
|
+
];
|
|
6628
|
+
}
|
|
6629
|
+
function printApiSection(title, tone, fields) {
|
|
6630
|
+
const color = getToneColor(tone);
|
|
6631
|
+
const topBorder = color.bold(`┌─ ${title}`);
|
|
6632
|
+
const bottomBorder = color.bold('└' + '─'.repeat(Math.max(title.length + 2, 28)));
|
|
6633
|
+
console.log('');
|
|
6634
|
+
console.log(topBorder);
|
|
6635
|
+
fields.forEach(([label, value]) => {
|
|
6636
|
+
formatLogField(label, value).forEach(line => console.log(line));
|
|
6637
|
+
});
|
|
6638
|
+
console.log(bottomBorder);
|
|
6639
|
+
console.log('');
|
|
6640
|
+
}
|
|
6641
|
+
function printApiRequestLog(payload) {
|
|
6642
|
+
printApiSection('API Request', 'request', [
|
|
6643
|
+
['URL', payload.url],
|
|
6644
|
+
['Method', payload.method],
|
|
6645
|
+
['Params', payload.params],
|
|
6646
|
+
]);
|
|
6647
|
+
}
|
|
6648
|
+
function printApiResponseLog(title, result) {
|
|
6649
|
+
printApiSection(title, title === 'API Response' ? 'success' : 'error', [
|
|
6650
|
+
['Status', result.status ?? '-'],
|
|
6651
|
+
['LogID', result.logid || '-'],
|
|
6652
|
+
['Return Value', result.data],
|
|
6653
|
+
]);
|
|
6654
|
+
}
|
|
6535
6655
|
async function request({ url, method, data, headers, params, }) {
|
|
6536
6656
|
const config = getTTMGRC();
|
|
6537
6657
|
const cookie = config?.cookie;
|
|
6538
6658
|
const proxyConfig = getAxiosProxyConfig();
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
}, null, 2));
|
|
6547
|
-
if (params) {
|
|
6548
|
-
console.log('Query Params:', JSON.stringify(params, null, 2));
|
|
6549
|
-
}
|
|
6550
|
-
if (data) {
|
|
6551
|
-
console.log('Request Body:', JSON.stringify(data, null, 2));
|
|
6552
|
-
}
|
|
6553
|
-
console.log('=================================\n');
|
|
6659
|
+
if (isVerboseEnabled()) {
|
|
6660
|
+
printApiRequestLog({
|
|
6661
|
+
url,
|
|
6662
|
+
method,
|
|
6663
|
+
params: getRequestParams(params, data),
|
|
6664
|
+
});
|
|
6665
|
+
}
|
|
6554
6666
|
try {
|
|
6555
6667
|
const res = await axios({
|
|
6556
6668
|
url,
|
|
@@ -6565,12 +6677,13 @@ async function request({ url, method, data, headers, params, }) {
|
|
|
6565
6677
|
},
|
|
6566
6678
|
...proxyConfig,
|
|
6567
6679
|
});
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6680
|
+
if (isVerboseEnabled()) {
|
|
6681
|
+
printApiResponseLog('API Response', {
|
|
6682
|
+
status: res?.status,
|
|
6683
|
+
logid: res?.headers['x-tt-logid'],
|
|
6684
|
+
data: res.data,
|
|
6685
|
+
});
|
|
6686
|
+
}
|
|
6574
6687
|
// @ts-ignore
|
|
6575
6688
|
return {
|
|
6576
6689
|
data: res.data,
|
|
@@ -6582,12 +6695,13 @@ async function request({ url, method, data, headers, params, }) {
|
|
|
6582
6695
|
};
|
|
6583
6696
|
}
|
|
6584
6697
|
catch (err) {
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6698
|
+
if (isVerboseEnabled()) {
|
|
6699
|
+
printApiResponseLog('API Error', {
|
|
6700
|
+
status: err?.response?.status,
|
|
6701
|
+
logid: err?.response?.headers['x-tt-logid'],
|
|
6702
|
+
data: err?.response?.data,
|
|
6703
|
+
});
|
|
6704
|
+
}
|
|
6591
6705
|
// @ts-ignore
|
|
6592
6706
|
return {
|
|
6593
6707
|
data: null,
|
|
@@ -6658,6 +6772,46 @@ function isAxiosError(e) {
|
|
|
6658
6772
|
return !!e?.isAxiosError;
|
|
6659
6773
|
}
|
|
6660
6774
|
|
|
6775
|
+
const GET_GAME_ASSET_PREVIEW_URL = 'https://developers.tiktok.com/tiktok/v4/devportal/mini_game/asset/preview_url';
|
|
6776
|
+
async function fetchGameAssetPreviewUrl({ assetId, }) {
|
|
6777
|
+
return request({
|
|
6778
|
+
url: GET_GAME_ASSET_PREVIEW_URL,
|
|
6779
|
+
method: 'GET',
|
|
6780
|
+
params: {
|
|
6781
|
+
asset_id: assetId,
|
|
6782
|
+
},
|
|
6783
|
+
});
|
|
6784
|
+
}
|
|
6785
|
+
|
|
6786
|
+
const GET_DIRECT_FEED_CARD_ASSET_PREVIEW_URL = 'https://developers.tiktok.com/tiktok/v4/devportal/mini_game/fyf_card/get_direct_feed_card_asset_preview_url';
|
|
6787
|
+
const DIRECT_FEED_CARD_HEADERS = {
|
|
6788
|
+
'Content-Type': 'application/json',
|
|
6789
|
+
'x-use-ppe': '1',
|
|
6790
|
+
'x-tt-env': 'ppe_feed_play',
|
|
6791
|
+
};
|
|
6792
|
+
async function fetchDirectFeedCardAssetPreviewUrl({ assetId, contentId, }) {
|
|
6793
|
+
return request({
|
|
6794
|
+
url: GET_DIRECT_FEED_CARD_ASSET_PREVIEW_URL,
|
|
6795
|
+
method: 'POST',
|
|
6796
|
+
headers: DIRECT_FEED_CARD_HEADERS,
|
|
6797
|
+
data: {
|
|
6798
|
+
asset_id: assetId,
|
|
6799
|
+
content_id: contentId,
|
|
6800
|
+
},
|
|
6801
|
+
});
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6804
|
+
const GAME_ASSETS_URL = 'https://developers.tiktok.com/tiktok/v4/devportal/mini_game/assets';
|
|
6805
|
+
async function fetchGameAssets({ miniGameId, }) {
|
|
6806
|
+
return request({
|
|
6807
|
+
url: GAME_ASSETS_URL,
|
|
6808
|
+
method: 'GET',
|
|
6809
|
+
params: {
|
|
6810
|
+
mini_game_id: miniGameId,
|
|
6811
|
+
},
|
|
6812
|
+
});
|
|
6813
|
+
}
|
|
6814
|
+
|
|
6661
6815
|
async function fetchGameInfo(clientKey) {
|
|
6662
6816
|
// 访问 V4 接口
|
|
6663
6817
|
const response = await request({
|
|
@@ -6694,6 +6848,24 @@ async function fetchGameInfo(clientKey) {
|
|
|
6694
6848
|
}
|
|
6695
6849
|
}
|
|
6696
6850
|
|
|
6851
|
+
const LIST_DIRECT_FEED_CARD_URL = 'https://developers.tiktok.com/tiktok/v4/devportal/mini_game/fyf_card/list_direct_feed_card';
|
|
6852
|
+
const LIST_DIRECT_FEED_CARD_HEADERS = {
|
|
6853
|
+
'Content-Type': 'application/json',
|
|
6854
|
+
'x-use-ppe': '1',
|
|
6855
|
+
'x-tt-env': 'ppe_feed_play',
|
|
6856
|
+
};
|
|
6857
|
+
async function listDirectFeedCards({ appId, clientKey, }) {
|
|
6858
|
+
return request({
|
|
6859
|
+
url: LIST_DIRECT_FEED_CARD_URL,
|
|
6860
|
+
method: 'POST',
|
|
6861
|
+
headers: LIST_DIRECT_FEED_CARD_HEADERS,
|
|
6862
|
+
data: {
|
|
6863
|
+
app_id: appId,
|
|
6864
|
+
client_key: clientKey,
|
|
6865
|
+
},
|
|
6866
|
+
});
|
|
6867
|
+
}
|
|
6868
|
+
|
|
6697
6869
|
async function uploadGameToPlatform({ data, name, clientKey, note = '--', appId, }) {
|
|
6698
6870
|
if (!appId) {
|
|
6699
6871
|
return {
|
|
@@ -6809,10 +6981,10 @@ const messages = {
|
|
|
6809
6981
|
'en-US': {
|
|
6810
6982
|
'cli.description': 'TikTok Mini Games Command Line Tool',
|
|
6811
6983
|
'cli.version.desc': 'Show version',
|
|
6984
|
+
'cli.option.verbose': 'Print detailed debug logs',
|
|
6812
6985
|
'cli.option.dev.client': 'Debug TikTok Mini Games for Client',
|
|
6813
6986
|
'cli.option.dev.h5': 'Debug TikTok Mini Games for Web',
|
|
6814
6987
|
'cli.command.login.desc': 'Login with developer account',
|
|
6815
|
-
'cli.command.login.verbose': 'Print verbose logs for debugging',
|
|
6816
6988
|
'cli.command.logout.desc': 'Logout and clear local user data',
|
|
6817
6989
|
'cli.command.setup.desc': 'Initialize ttmg environment',
|
|
6818
6990
|
'cli.command.setup.lang': 'Language (only supports): en-US | zh-CN',
|
|
@@ -6940,10 +7112,10 @@ const messages = {
|
|
|
6940
7112
|
'zh-CN': {
|
|
6941
7113
|
'cli.description': 'TikTok 小游戏命令行工具',
|
|
6942
7114
|
'cli.version.desc': '显示版本号',
|
|
7115
|
+
'cli.option.verbose': '输出详细调试日志',
|
|
6943
7116
|
'cli.option.dev.client': '客户端调试 TikTok 小游戏',
|
|
6944
7117
|
'cli.option.dev.h5': 'Web 调试 TikTok 小游戏',
|
|
6945
7118
|
'cli.command.login.desc': '使用开发者账号登录',
|
|
6946
|
-
'cli.command.login.verbose': '输出调试用详细日志',
|
|
6947
7119
|
'cli.command.logout.desc': '退出登录并清除本地用户信息',
|
|
6948
7120
|
'cli.command.setup.desc': '初始化 ttmg 环境',
|
|
6949
7121
|
'cli.command.setup.lang': '语言(仅支持):en-US | zh-CN',
|
|
@@ -7807,17 +7979,6 @@ class WsServer {
|
|
|
7807
7979
|
else {
|
|
7808
7980
|
const method = clientMessage.method;
|
|
7809
7981
|
switch (method) {
|
|
7810
|
-
/**
|
|
7811
|
-
* 客户端完成扫码成功,返回客户端的 host 和 port
|
|
7812
|
-
*/
|
|
7813
|
-
case 'startScanQRcode': {
|
|
7814
|
-
const payload = clientMessage.payload;
|
|
7815
|
-
console.log('startQRcode', payload);
|
|
7816
|
-
this.send({
|
|
7817
|
-
method: 'startScanQRcode',
|
|
7818
|
-
});
|
|
7819
|
-
break;
|
|
7820
|
-
}
|
|
7821
7982
|
case 'scanQRCodeResult': {
|
|
7822
7983
|
const payload = clientMessage.payload || {};
|
|
7823
7984
|
const { host, port, wsPort, errMsg, isSuccess } = payload;
|
|
@@ -8740,6 +8901,159 @@ function setupMiddlewares(app, options) {
|
|
|
8740
8901
|
const successCode = 0;
|
|
8741
8902
|
const errorCode = -1;
|
|
8742
8903
|
|
|
8904
|
+
const gameAssetPreviewUrlRoute = {
|
|
8905
|
+
method: 'post',
|
|
8906
|
+
path: '/game/asset/preview-url',
|
|
8907
|
+
handler: async (req, res) => {
|
|
8908
|
+
const body = req.body;
|
|
8909
|
+
const assetId = body?.assetId?.trim() || body?.asset_id?.trim() || '';
|
|
8910
|
+
if (!assetId) {
|
|
8911
|
+
res.send({
|
|
8912
|
+
code: errorCode,
|
|
8913
|
+
error: 'Missing required field `assetId`.',
|
|
8914
|
+
data: null,
|
|
8915
|
+
});
|
|
8916
|
+
return;
|
|
8917
|
+
}
|
|
8918
|
+
const response = await fetchGameAssetPreviewUrl({
|
|
8919
|
+
assetId,
|
|
8920
|
+
});
|
|
8921
|
+
if (response.error) {
|
|
8922
|
+
res.send({
|
|
8923
|
+
code: errorCode,
|
|
8924
|
+
error: response.error,
|
|
8925
|
+
ctx: response.ctx,
|
|
8926
|
+
});
|
|
8927
|
+
return;
|
|
8928
|
+
}
|
|
8929
|
+
res.send({
|
|
8930
|
+
code: successCode,
|
|
8931
|
+
data: response.data,
|
|
8932
|
+
ctx: response.ctx,
|
|
8933
|
+
});
|
|
8934
|
+
},
|
|
8935
|
+
};
|
|
8936
|
+
|
|
8937
|
+
function getAssetStatusValue(asset) {
|
|
8938
|
+
if (!asset) {
|
|
8939
|
+
return '';
|
|
8940
|
+
}
|
|
8941
|
+
return String(asset.status ?? asset.cdn_deploy_status ?? asset.live_status ?? '').toLowerCase();
|
|
8942
|
+
}
|
|
8943
|
+
function isUsableAsset(asset) {
|
|
8944
|
+
if (!asset) {
|
|
8945
|
+
return false;
|
|
8946
|
+
}
|
|
8947
|
+
if (Number(asset.cdn_deploy_status) === 2) {
|
|
8948
|
+
return true;
|
|
8949
|
+
}
|
|
8950
|
+
const rawStatus = getAssetStatusValue(asset);
|
|
8951
|
+
return ['ready', 'success', 'succeeded', 'available'].includes(rawStatus);
|
|
8952
|
+
}
|
|
8953
|
+
function filterAssetList(assets, { includePending, pinnedAssetId, }) {
|
|
8954
|
+
if (!Array.isArray(assets)) {
|
|
8955
|
+
return [];
|
|
8956
|
+
}
|
|
8957
|
+
return assets.filter(item => {
|
|
8958
|
+
const asset = item;
|
|
8959
|
+
if (isUsableAsset(asset)) {
|
|
8960
|
+
return true;
|
|
8961
|
+
}
|
|
8962
|
+
if (!includePending || !pinnedAssetId) {
|
|
8963
|
+
return false;
|
|
8964
|
+
}
|
|
8965
|
+
return String(asset.asset_id || '') === pinnedAssetId;
|
|
8966
|
+
});
|
|
8967
|
+
}
|
|
8968
|
+
async function resolveMiniGameId(body) {
|
|
8969
|
+
let miniGameId = body?.miniGameId?.trim() ||
|
|
8970
|
+
body?.mini_game_id?.trim() ||
|
|
8971
|
+
body?.appId?.trim() ||
|
|
8972
|
+
body?.app_id?.trim() ||
|
|
8973
|
+
store.getState().appId?.trim();
|
|
8974
|
+
const clientKey = body?.clientKey?.trim() ||
|
|
8975
|
+
body?.client_key?.trim() ||
|
|
8976
|
+
getClientKey().clientKey?.trim();
|
|
8977
|
+
if (!miniGameId && clientKey) {
|
|
8978
|
+
const gameInfoResponse = await fetchGameInfo(clientKey);
|
|
8979
|
+
if (gameInfoResponse.error) {
|
|
8980
|
+
return {
|
|
8981
|
+
miniGameId: '',
|
|
8982
|
+
error: gameInfoResponse.error,
|
|
8983
|
+
};
|
|
8984
|
+
}
|
|
8985
|
+
miniGameId = gameInfoResponse.data?.app_id?.trim() || '';
|
|
8986
|
+
if (miniGameId) {
|
|
8987
|
+
store.setState({ appId: miniGameId });
|
|
8988
|
+
}
|
|
8989
|
+
}
|
|
8990
|
+
if (!miniGameId) {
|
|
8991
|
+
return {
|
|
8992
|
+
miniGameId: '',
|
|
8993
|
+
error: 'Missing mini game id. Please open project detail first or pass `miniGameId` / `appId` from IDE.',
|
|
8994
|
+
};
|
|
8995
|
+
}
|
|
8996
|
+
return {
|
|
8997
|
+
miniGameId,
|
|
8998
|
+
error: null,
|
|
8999
|
+
};
|
|
9000
|
+
}
|
|
9001
|
+
const gameAssetsRoute = {
|
|
9002
|
+
method: 'post',
|
|
9003
|
+
path: '/game/assets',
|
|
9004
|
+
handler: async (req, res) => {
|
|
9005
|
+
const body = req.body;
|
|
9006
|
+
const identity = await resolveMiniGameId(body);
|
|
9007
|
+
if (identity.error) {
|
|
9008
|
+
res.send({
|
|
9009
|
+
code: errorCode,
|
|
9010
|
+
error: identity.error,
|
|
9011
|
+
data: null,
|
|
9012
|
+
});
|
|
9013
|
+
return;
|
|
9014
|
+
}
|
|
9015
|
+
const response = await fetchGameAssets({
|
|
9016
|
+
miniGameId: identity.miniGameId,
|
|
9017
|
+
});
|
|
9018
|
+
if (response.error) {
|
|
9019
|
+
res.send({
|
|
9020
|
+
code: errorCode,
|
|
9021
|
+
error: response.error,
|
|
9022
|
+
ctx: response.ctx,
|
|
9023
|
+
});
|
|
9024
|
+
return;
|
|
9025
|
+
}
|
|
9026
|
+
const pinnedAssetId = body?.assetId?.trim() || body?.asset_id?.trim() || '';
|
|
9027
|
+
const includePending = body?.includePending === true || body?.include_pending === true;
|
|
9028
|
+
const filteredData = response.data
|
|
9029
|
+
? {
|
|
9030
|
+
...response.data,
|
|
9031
|
+
preview_assets: filterAssetList(response.data.preview_assets, {
|
|
9032
|
+
includePending,
|
|
9033
|
+
pinnedAssetId,
|
|
9034
|
+
}),
|
|
9035
|
+
in_review_assets: filterAssetList(response.data.in_review_assets, {
|
|
9036
|
+
includePending,
|
|
9037
|
+
pinnedAssetId,
|
|
9038
|
+
}),
|
|
9039
|
+
live_assets: filterAssetList(response.data.live_assets, {
|
|
9040
|
+
includePending,
|
|
9041
|
+
pinnedAssetId,
|
|
9042
|
+
}),
|
|
9043
|
+
assets: filterAssetList(response.data.assets, {
|
|
9044
|
+
includePending,
|
|
9045
|
+
pinnedAssetId,
|
|
9046
|
+
}),
|
|
9047
|
+
}
|
|
9048
|
+
: null;
|
|
9049
|
+
res.send({
|
|
9050
|
+
code: successCode,
|
|
9051
|
+
data: filteredData,
|
|
9052
|
+
ctx: response.ctx,
|
|
9053
|
+
});
|
|
9054
|
+
},
|
|
9055
|
+
};
|
|
9056
|
+
|
|
8743
9057
|
function buildCheckPkgsOptions(outputDir) {
|
|
8744
9058
|
return {
|
|
8745
9059
|
entry: process.cwd(),
|
|
@@ -8843,6 +9157,168 @@ const gameCheckRoute = {
|
|
|
8843
9157
|
},
|
|
8844
9158
|
};
|
|
8845
9159
|
|
|
9160
|
+
const gameDirectFeedCardAssetPreviewRoute = {
|
|
9161
|
+
method: 'post',
|
|
9162
|
+
path: '/game/direct-feed-card/asset-preview',
|
|
9163
|
+
handler: async (req, res) => {
|
|
9164
|
+
const body = req.body;
|
|
9165
|
+
const assetId = body?.assetId?.trim() || body?.asset_id?.trim() || '';
|
|
9166
|
+
const contentId = body?.contentId?.trim() || body?.content_id?.trim() || '';
|
|
9167
|
+
if (!assetId || !contentId) {
|
|
9168
|
+
res.send({
|
|
9169
|
+
code: errorCode,
|
|
9170
|
+
error: 'Missing required fields. Please pass both `assetId` and `contentId` from IDE.',
|
|
9171
|
+
data: null,
|
|
9172
|
+
});
|
|
9173
|
+
return;
|
|
9174
|
+
}
|
|
9175
|
+
const response = await fetchDirectFeedCardAssetPreviewUrl({
|
|
9176
|
+
assetId,
|
|
9177
|
+
contentId,
|
|
9178
|
+
});
|
|
9179
|
+
if (response.error) {
|
|
9180
|
+
res.send({
|
|
9181
|
+
code: errorCode,
|
|
9182
|
+
error: response.error,
|
|
9183
|
+
ctx: response.ctx,
|
|
9184
|
+
});
|
|
9185
|
+
return;
|
|
9186
|
+
}
|
|
9187
|
+
res.send({
|
|
9188
|
+
code: successCode,
|
|
9189
|
+
data: response.data,
|
|
9190
|
+
ctx: response.ctx,
|
|
9191
|
+
});
|
|
9192
|
+
},
|
|
9193
|
+
};
|
|
9194
|
+
|
|
9195
|
+
function hasBlockingCardStatus(value) {
|
|
9196
|
+
if (value === null || value === undefined || value === '') {
|
|
9197
|
+
return false;
|
|
9198
|
+
}
|
|
9199
|
+
if (typeof value === 'number') {
|
|
9200
|
+
return value <= 0;
|
|
9201
|
+
}
|
|
9202
|
+
const normalized = String(value).toLowerCase();
|
|
9203
|
+
return [
|
|
9204
|
+
'pending',
|
|
9205
|
+
'review',
|
|
9206
|
+
'reviewing',
|
|
9207
|
+
'processing',
|
|
9208
|
+
'reject',
|
|
9209
|
+
'rejected',
|
|
9210
|
+
'fail',
|
|
9211
|
+
'failed',
|
|
9212
|
+
'disable',
|
|
9213
|
+
'disabled',
|
|
9214
|
+
'offline',
|
|
9215
|
+
'draft',
|
|
9216
|
+
'delete',
|
|
9217
|
+
'deleted',
|
|
9218
|
+
].some(keyword => normalized.includes(keyword));
|
|
9219
|
+
}
|
|
9220
|
+
function isUsableDirectFeedCard(card) {
|
|
9221
|
+
if (!card?.content_id) {
|
|
9222
|
+
return false;
|
|
9223
|
+
}
|
|
9224
|
+
if (hasBlockingCardStatus(card.status)) {
|
|
9225
|
+
return false;
|
|
9226
|
+
}
|
|
9227
|
+
if (typeof card.audit_status === 'number') {
|
|
9228
|
+
if (card.audit_status <= 1) {
|
|
9229
|
+
return false;
|
|
9230
|
+
}
|
|
9231
|
+
}
|
|
9232
|
+
else if (hasBlockingCardStatus(card.audit_status)) {
|
|
9233
|
+
return false;
|
|
9234
|
+
}
|
|
9235
|
+
return true;
|
|
9236
|
+
}
|
|
9237
|
+
async function resolveAppIdentity(body) {
|
|
9238
|
+
const clientKey = body?.clientKey?.trim() ||
|
|
9239
|
+
body?.client_key?.trim() ||
|
|
9240
|
+
getClientKey().clientKey?.trim();
|
|
9241
|
+
let appId = body?.appId?.trim() ||
|
|
9242
|
+
body?.app_id?.trim() ||
|
|
9243
|
+
store.getState().appId?.trim();
|
|
9244
|
+
if (!clientKey) {
|
|
9245
|
+
return {
|
|
9246
|
+
clientKey: '',
|
|
9247
|
+
appId,
|
|
9248
|
+
error: 'Missing client key. Please run `ttmg init` or pass `clientKey` from IDE.',
|
|
9249
|
+
};
|
|
9250
|
+
}
|
|
9251
|
+
if (!appId) {
|
|
9252
|
+
const gameInfoResponse = await fetchGameInfo(clientKey);
|
|
9253
|
+
if (gameInfoResponse.error) {
|
|
9254
|
+
return {
|
|
9255
|
+
clientKey,
|
|
9256
|
+
appId: '',
|
|
9257
|
+
error: gameInfoResponse.error,
|
|
9258
|
+
};
|
|
9259
|
+
}
|
|
9260
|
+
appId = gameInfoResponse.data?.app_id?.trim() || '';
|
|
9261
|
+
if (appId) {
|
|
9262
|
+
store.setState({ appId });
|
|
9263
|
+
}
|
|
9264
|
+
}
|
|
9265
|
+
if (!appId) {
|
|
9266
|
+
return {
|
|
9267
|
+
clientKey,
|
|
9268
|
+
appId: '',
|
|
9269
|
+
error: 'Missing app id. Please open project detail first or pass `appId` from IDE.',
|
|
9270
|
+
};
|
|
9271
|
+
}
|
|
9272
|
+
return {
|
|
9273
|
+
clientKey,
|
|
9274
|
+
appId,
|
|
9275
|
+
error: null,
|
|
9276
|
+
};
|
|
9277
|
+
}
|
|
9278
|
+
const gameDirectFeedCardListRoute = {
|
|
9279
|
+
method: 'post',
|
|
9280
|
+
path: '/game/direct-feed-card/list',
|
|
9281
|
+
handler: async (req, res) => {
|
|
9282
|
+
const identity = await resolveAppIdentity(req.body);
|
|
9283
|
+
if (identity.error) {
|
|
9284
|
+
res.send({
|
|
9285
|
+
code: errorCode,
|
|
9286
|
+
error: identity.error,
|
|
9287
|
+
data: null,
|
|
9288
|
+
});
|
|
9289
|
+
return;
|
|
9290
|
+
}
|
|
9291
|
+
const response = await listDirectFeedCards({
|
|
9292
|
+
appId: identity.appId,
|
|
9293
|
+
clientKey: identity.clientKey,
|
|
9294
|
+
});
|
|
9295
|
+
if (response.error) {
|
|
9296
|
+
res.send({
|
|
9297
|
+
code: errorCode,
|
|
9298
|
+
error: response.error,
|
|
9299
|
+
ctx: response.ctx,
|
|
9300
|
+
});
|
|
9301
|
+
return;
|
|
9302
|
+
}
|
|
9303
|
+
const filteredCards = Array.isArray(response.data?.cards)
|
|
9304
|
+
? (response.data.cards || []).filter(isUsableDirectFeedCard)
|
|
9305
|
+
: [];
|
|
9306
|
+
const total = filteredCards.length;
|
|
9307
|
+
const data = response.data
|
|
9308
|
+
? {
|
|
9309
|
+
...response.data,
|
|
9310
|
+
cards: filteredCards,
|
|
9311
|
+
total,
|
|
9312
|
+
}
|
|
9313
|
+
: null;
|
|
9314
|
+
res.send({
|
|
9315
|
+
code: successCode,
|
|
9316
|
+
data,
|
|
9317
|
+
ctx: response.ctx,
|
|
9318
|
+
});
|
|
9319
|
+
},
|
|
9320
|
+
};
|
|
9321
|
+
|
|
8846
9322
|
const gameDetailRoute = {
|
|
8847
9323
|
method: 'get',
|
|
8848
9324
|
path: '/game/detail',
|
|
@@ -9423,6 +9899,11 @@ function updateSubpackageConfigSync() {
|
|
|
9423
9899
|
const gameJsonPath = path__namespace.join(process.cwd(), SUBPACKAGE_CONFIG_FILE_NAME);
|
|
9424
9900
|
const raw = fs__namespace.readFileSync(gameJsonPath, 'utf-8');
|
|
9425
9901
|
const gameJson = JSON.parse(raw);
|
|
9902
|
+
/**
|
|
9903
|
+
* wasm 分包完整流程完成后,删除一次性校验字段,
|
|
9904
|
+
* 避免后续调试阶段继续触发 wasmFuncCount 的提示。
|
|
9905
|
+
*/
|
|
9906
|
+
delete gameJson.wasmFuncCount;
|
|
9426
9907
|
const fieldName = SUBPACKAGE_FIELD_NAMES.find(k => k in gameJson) ??
|
|
9427
9908
|
SUBPACKAGE_FIELD_NAMES[0];
|
|
9428
9909
|
if (!gameJson[fieldName])
|
|
@@ -10217,10 +10698,14 @@ function getGameFallbackRoute(publicPath) {
|
|
|
10217
10698
|
}
|
|
10218
10699
|
|
|
10219
10700
|
const routes = [
|
|
10701
|
+
gameAssetPreviewUrlRoute,
|
|
10702
|
+
gameAssetsRoute,
|
|
10220
10703
|
gameConfigRoute,
|
|
10221
10704
|
gameConfigFillbackRoute,
|
|
10222
10705
|
gameDetailRoute,
|
|
10223
10706
|
gameCheckRoute,
|
|
10707
|
+
gameDirectFeedCardAssetPreviewRoute,
|
|
10708
|
+
gameDirectFeedCardListRoute,
|
|
10224
10709
|
gameUploadRoute,
|
|
10225
10710
|
gameWasmSplitConfigRoute,
|
|
10226
10711
|
gameWasmSplitOptionsRoute,
|
|
@@ -10679,78 +11164,78 @@ async function upload({ clientKey, note = '--', dir, }) {
|
|
|
10679
11164
|
}
|
|
10680
11165
|
}
|
|
10681
11166
|
|
|
10682
|
-
var version = "0.3.
|
|
11167
|
+
var version = "0.3.7-beta.1";
|
|
10683
11168
|
var pkg = {
|
|
10684
11169
|
version: version};
|
|
10685
11170
|
|
|
10686
11171
|
const program = new commander.Command();
|
|
11172
|
+
const withVerboseOption = (command) => command.option('--verbose', t('cli.option.verbose'));
|
|
10687
11173
|
maybeShowPostInstallNotice(pkg.version);
|
|
10688
|
-
program
|
|
11174
|
+
withVerboseOption(program)
|
|
10689
11175
|
.name('ttmg')
|
|
10690
11176
|
.description(t('cli.description'))
|
|
10691
11177
|
.version(pkg.version, '-v, --version', t('cli.version.desc'))
|
|
10692
11178
|
.option('dev', t('cli.option.dev.client'))
|
|
10693
11179
|
.option('dev --h5', t('cli.option.dev.h5'));
|
|
10694
|
-
program
|
|
11180
|
+
withVerboseOption(program
|
|
10695
11181
|
.command('login')
|
|
10696
|
-
.description(t('cli.command.login.desc'))
|
|
10697
|
-
.option('--verbose', t('cli.command.login.verbose'))
|
|
11182
|
+
.description(t('cli.command.login.desc')))
|
|
10698
11183
|
.action(async (cmd) => {
|
|
10699
11184
|
await login({ verbose: cmd.verbose });
|
|
10700
11185
|
});
|
|
10701
|
-
program
|
|
11186
|
+
withVerboseOption(program
|
|
10702
11187
|
.command('logout')
|
|
10703
|
-
.description(t('cli.command.logout.desc'))
|
|
11188
|
+
.description(t('cli.command.logout.desc')))
|
|
10704
11189
|
.action(async () => {
|
|
10705
11190
|
await logout();
|
|
10706
11191
|
});
|
|
10707
|
-
program
|
|
11192
|
+
withVerboseOption(program
|
|
10708
11193
|
.command('upload')
|
|
10709
11194
|
.description(t('cli.command.upload.desc'))
|
|
10710
11195
|
.option('-ck, --client-key <clientKey>', t('cli.command.upload.clientKey'))
|
|
10711
11196
|
.option('-n, --note <note>', t('cli.command.upload.note'))
|
|
10712
|
-
.option('-d, --dir <dir>', t('cli.command.upload.dir'))
|
|
11197
|
+
.option('-d, --dir <dir>', t('cli.command.upload.dir')))
|
|
10713
11198
|
.action(async (cmd) => {
|
|
10714
11199
|
await upload({ clientKey: cmd.clientKey, note: cmd.note, dir: cmd.dir });
|
|
10715
11200
|
});
|
|
10716
|
-
program
|
|
11201
|
+
withVerboseOption(program
|
|
10717
11202
|
.command('setup')
|
|
10718
11203
|
.description(t('cli.command.setup.desc'))
|
|
10719
|
-
.option('--lang <lang>', t('cli.command.setup.lang'))
|
|
11204
|
+
.option('--lang <lang>', t('cli.command.setup.lang')))
|
|
10720
11205
|
.action(async (cmd) => {
|
|
10721
11206
|
await setup({ lang: cmd.lang });
|
|
10722
11207
|
});
|
|
10723
|
-
program
|
|
11208
|
+
withVerboseOption(program
|
|
10724
11209
|
.command('reset')
|
|
10725
|
-
.description(t('cli.command.reset.desc'))
|
|
11210
|
+
.description(t('cli.command.reset.desc')))
|
|
10726
11211
|
.action(async () => {
|
|
10727
11212
|
await reset();
|
|
10728
11213
|
});
|
|
10729
11214
|
const configCmd = program
|
|
10730
11215
|
.command('config')
|
|
10731
11216
|
.description(t('cli.command.config.desc'));
|
|
10732
|
-
configCmd
|
|
11217
|
+
withVerboseOption(configCmd
|
|
10733
11218
|
.command('set <key> [value]')
|
|
10734
|
-
.description(t('cli.command.config.set.desc'))
|
|
11219
|
+
.description(t('cli.command.config.set.desc')))
|
|
10735
11220
|
.action(async (key, value) => {
|
|
10736
11221
|
await config.set(key, value);
|
|
10737
11222
|
});
|
|
10738
|
-
configCmd
|
|
11223
|
+
withVerboseOption(configCmd
|
|
10739
11224
|
.command('get <key>')
|
|
10740
|
-
.description(t('cli.command.config.get.desc'))
|
|
11225
|
+
.description(t('cli.command.config.get.desc')))
|
|
10741
11226
|
.action(async (key) => {
|
|
10742
11227
|
await config.get(key);
|
|
10743
11228
|
});
|
|
10744
|
-
configCmd
|
|
11229
|
+
withVerboseOption(configCmd
|
|
10745
11230
|
.command('delete <key>')
|
|
10746
|
-
.description(t('cli.command.config.delete.desc'))
|
|
11231
|
+
.description(t('cli.command.config.delete.desc')))
|
|
10747
11232
|
.action(async (key) => {
|
|
10748
11233
|
await config.delete(key);
|
|
10749
11234
|
});
|
|
10750
|
-
program
|
|
11235
|
+
withVerboseOption(program
|
|
10751
11236
|
.option('--h5', t('cli.option.h5'))
|
|
10752
11237
|
.command('init')
|
|
10753
|
-
.description(t('cli.command.init.desc'))
|
|
11238
|
+
.description(t('cli.command.init.desc')))
|
|
10754
11239
|
.action(() => {
|
|
10755
11240
|
const options = program.opts(); // 获取 options
|
|
10756
11241
|
if (options.h5) {
|
|
@@ -10763,10 +11248,10 @@ program
|
|
|
10763
11248
|
/**
|
|
10764
11249
|
* ttmg dev 命令
|
|
10765
11250
|
*/
|
|
10766
|
-
program
|
|
11251
|
+
withVerboseOption(program
|
|
10767
11252
|
.option('--h5', t('cli.option.h5'))
|
|
10768
11253
|
.command('dev')
|
|
10769
|
-
.description(t('cli.command.dev.desc'))
|
|
11254
|
+
.description(t('cli.command.dev.desc')))
|
|
10770
11255
|
.action(async () => {
|
|
10771
11256
|
const options = program.opts();
|
|
10772
11257
|
if (options.h5) {
|
|
@@ -10780,10 +11265,10 @@ program
|
|
|
10780
11265
|
/**
|
|
10781
11266
|
* ttmg build 命令
|
|
10782
11267
|
*/
|
|
10783
|
-
program
|
|
11268
|
+
withVerboseOption(program
|
|
10784
11269
|
.option('--h5', t('cli.option.h5'))
|
|
10785
11270
|
.command('build')
|
|
10786
|
-
.description(t('cli.command.build.desc'))
|
|
11271
|
+
.description(t('cli.command.build.desc')))
|
|
10787
11272
|
.action(() => {
|
|
10788
11273
|
const options = program.opts(); // 获取 options
|
|
10789
11274
|
if (options.h5) {
|