tt-minigame-ide-cli 0.0.1-beta.0
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/.yarnrc +1 -0
- package/LICENSE +21 -0
- package/README.en.md +119 -0
- package/README.md +120 -0
- package/bin/tmg.js +199 -0
- package/lib/auth.js +145 -0
- package/lib/build-npm.js +22 -0
- package/lib/create.js +106 -0
- package/lib/index.d.ts +23 -0
- package/lib/index.js +79 -0
- package/lib/preview.js +86 -0
- package/lib/upload.js +120 -0
- package/lib/util/check.js +84 -0
- package/lib/util/config.js +41 -0
- package/lib/util/cookie.js +36 -0
- package/lib/util/helper.js +242 -0
- package/lib/util/logger.js +54 -0
- package/lib/util/qrcode.js +19 -0
- package/lib/util/request.js +360 -0
- package/lib/util/version.js +27 -0
- package/package.json +35 -0
- package/template/app.js +5 -0
- package/template/app.json +11 -0
- package/template/app.ttss +0 -0
- package/template/pages/index/index.js +10 -0
- package/template/pages/index/index.ttml +1 -0
- package/template/pages/index/index.ttss +4 -0
@@ -0,0 +1,242 @@
|
|
1
|
+
const archiver = require('archiver');
|
2
|
+
const path = require('path');
|
3
|
+
const fs = require('fs-extra');
|
4
|
+
const glob = require('glob');
|
5
|
+
const {
|
6
|
+
getStoragePath
|
7
|
+
} = require('./config');
|
8
|
+
const previewFilePath = path.join(getStoragePath(), 'preview.json');
|
9
|
+
fs.ensureFileSync(previewFilePath);
|
10
|
+
|
11
|
+
function mixEncode(data) {
|
12
|
+
const str = data.toString();
|
13
|
+
const buff = [];
|
14
|
+
let i, len;
|
15
|
+
for (i = 0, len = str.length; i < len; i++) {
|
16
|
+
buff.push(str.charCodeAt(i));
|
17
|
+
}
|
18
|
+
const results = buff.map(b => b ^ 5);
|
19
|
+
const encode = [];
|
20
|
+
for (i = 0, len = results.length; i < len; i++) {
|
21
|
+
encode.push(results[i].toString(16));
|
22
|
+
}
|
23
|
+
return encode.join('');
|
24
|
+
}
|
25
|
+
|
26
|
+
async function zipFile(sourcePath, targetPath) {
|
27
|
+
const appJsonPath = path.join(sourcePath, 'app.json');
|
28
|
+
const isMiniProgram = await fs.pathExists(appJsonPath);
|
29
|
+
const subpackageInfoPath = path.join(sourcePath, `${isMiniProgram ? 'app.json' : 'game.json'}`);
|
30
|
+
const projectConfigJson = fs.readJSONSync(subpackageInfoPath);
|
31
|
+
const subPackagesArr = projectConfigJson.subPackages || projectConfigJson.subpackages;
|
32
|
+
const zipFileRet = {
|
33
|
+
filePath: null,
|
34
|
+
};
|
35
|
+
if (subPackagesArr && subPackagesArr.length > 0) {
|
36
|
+
const ifSubPackageUploadable = await verifySubPackageSize(projectConfigJson, isMiniProgram, sourcePath);
|
37
|
+
if (ifSubPackageUploadable) {
|
38
|
+
zipFileRet.filePath = await normalZipFile(sourcePath, targetPath, isMiniProgram, true);
|
39
|
+
}
|
40
|
+
} else {
|
41
|
+
zipFileRet.filePath = await normalZipFile(sourcePath, targetPath, isMiniProgram, false);
|
42
|
+
}
|
43
|
+
return zipFileRet;
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @description 校验分包大小, 小游戏和小程序的不同在于子包不同
|
48
|
+
*/
|
49
|
+
async function verifySubPackageSize(projectConfigJson, isMiniProgram, sourcePath) {
|
50
|
+
let subPackageTotalSize = 0; // 子包+主包
|
51
|
+
// 做大小比较全拿字节数,精确
|
52
|
+
const packageSizeConfig = {
|
53
|
+
mainPackageMaxSize: 4 * 1024 * 1024,
|
54
|
+
subPackageSize: (this.isGame ? 4 : 2) * 1024 * 1024,
|
55
|
+
totalSize: 16 * 1024 * 1024,
|
56
|
+
};
|
57
|
+
// console.log('校验', projectConfigJson, packageSizeConfig);
|
58
|
+
// 开放数据域文件校验,可以认为开放数据域也作为一个子包
|
59
|
+
if (isMiniProgram && projectConfigJson.openDataContext) {
|
60
|
+
const openDataContextPath = path.join(sourcePath, projectConfigJson.openDataContext);
|
61
|
+
const openDataContextSize = await getFolderSize(openDataContextPath);
|
62
|
+
if (openDataContextSize > packageSizeConfig.subPackageSize) {
|
63
|
+
console.error(
|
64
|
+
`开放数据域文件大小为 ${getFormattedSize(
|
65
|
+
openDataContextSize,
|
66
|
+
)} MB, 超过 ${getFormattedSize(packageSizeConfig.subPackageSize)} MB,请调整包大小后再进行上传`,
|
67
|
+
);
|
68
|
+
return false;
|
69
|
+
}
|
70
|
+
subPackageTotalSize += openDataContextSize;
|
71
|
+
}
|
72
|
+
const totalPackageSize = await getFolderSize(sourcePath);
|
73
|
+
if (totalPackageSize > packageSizeConfig.totalSize) {
|
74
|
+
console.error(
|
75
|
+
`小${this.isGame ? '游戏' : '程序'}包大小为 ${getFormattedSize(
|
76
|
+
totalPackageSize,
|
77
|
+
)} MB, 超过 16 MB,请调整包大小后再进行上传`,
|
78
|
+
);
|
79
|
+
return false;
|
80
|
+
}
|
81
|
+
const subPackagesArr = projectConfigJson.subPackages || projectConfigJson.subpackages;
|
82
|
+
// 遍历子包数组,比较大小
|
83
|
+
for (let subPackage of subPackagesArr) {
|
84
|
+
const subPackagePath = path.join(sourcePath, subPackage.root);
|
85
|
+
const subPackageSize = await getFolderSize(subPackagePath);
|
86
|
+
if (subPackageSize > packageSizeConfig.subPackageSize) {
|
87
|
+
console.error(
|
88
|
+
`${subPackage.root}子包大小为 ${getFormattedSize(
|
89
|
+
subPackageSize,
|
90
|
+
)}MB, 超过${getFormattedSize(packageSizeConfig.subPackageSize)}MB,请调整包大小后再进行上传`,
|
91
|
+
);
|
92
|
+
return false;
|
93
|
+
} else {
|
94
|
+
console.log(
|
95
|
+
`${subPackage.root}子包大小为 ${getFormattedSize(
|
96
|
+
subPackageSize,
|
97
|
+
)}MB, 符合上传 / 预览要求`,
|
98
|
+
);
|
99
|
+
}
|
100
|
+
subPackageTotalSize += subPackageSize;
|
101
|
+
}
|
102
|
+
|
103
|
+
const mainPackageSize = totalPackageSize - subPackageTotalSize;
|
104
|
+
if (mainPackageSize > packageSizeConfig.mainPackageMaxSize) {
|
105
|
+
console.error(
|
106
|
+
`主包大小为 ${getFormattedSize(mainPackageSize)}MB, 超过 4 MB,请调整包大小后再进行上传`,
|
107
|
+
);
|
108
|
+
return false;
|
109
|
+
}
|
110
|
+
console.log(`主包大小为 ${getFormattedSize(mainPackageSize)} MB, 符合上传 / 预览要求`)
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
|
114
|
+
async function normalZipFile(sourcePath, targetPath, isMiniProgram, isSubPackage) {
|
115
|
+
|
116
|
+
const packageSize = isMiniProgram ? 4 : 8;
|
117
|
+
const zipPath = path.join(targetPath, `${path.basename(sourcePath)}.zip`);
|
118
|
+
return new Promise(function (resolve, reject) {
|
119
|
+
const output = fs.createWriteStream(zipPath);
|
120
|
+
const archive = archiver('zip');
|
121
|
+
|
122
|
+
output.on('close', function () {
|
123
|
+
// zip包生成以后,填写appId,更新日志,上传,打包
|
124
|
+
if (!isSubPackage) {
|
125
|
+
const stats = fs.statSync(zipPath)
|
126
|
+
const fileSizeInBytes = stats["size"];
|
127
|
+
const fileSizeMb = fileSizeInBytes / 1000000.0;
|
128
|
+
if (fileSizeMb > packageSize) {
|
129
|
+
return reject(`zip file is larger than ${packageSize}MB`)
|
130
|
+
}
|
131
|
+
}
|
132
|
+
return resolve(zipPath);
|
133
|
+
});
|
134
|
+
|
135
|
+
archive.on('warning', function (err) {
|
136
|
+
if (err.code === 'ENOENT') {
|
137
|
+
// log warning
|
138
|
+
} else {
|
139
|
+
return reject(err)
|
140
|
+
}
|
141
|
+
});
|
142
|
+
|
143
|
+
archive.on('error', function (err) {
|
144
|
+
return reject(err)
|
145
|
+
});
|
146
|
+
|
147
|
+
archive.pipe(output);
|
148
|
+
|
149
|
+
archive.glob('**/*', {
|
150
|
+
cwd: sourcePath,
|
151
|
+
ignore: ['.*/**/*', 'node_modules/**/*']
|
152
|
+
}, {})
|
153
|
+
|
154
|
+
archive.finalize(function (err, bytes) {
|
155
|
+
if (err) {
|
156
|
+
return reject(err);
|
157
|
+
}
|
158
|
+
});
|
159
|
+
});
|
160
|
+
}
|
161
|
+
|
162
|
+
function compileErrFormat(errMsg = '') {
|
163
|
+
errMsg = errMsg.split('\n').filter(item => !item.trim().startsWith('at'));
|
164
|
+
return errMsg.join('\n');
|
165
|
+
}
|
166
|
+
|
167
|
+
function getPackageName() {
|
168
|
+
return require(`../../package.json`).name;
|
169
|
+
}
|
170
|
+
|
171
|
+
function savePreviewResult(url, type, hash) {
|
172
|
+
try {
|
173
|
+
const currentResult = JSON.parse(fs.readFileSync(previewFilePath, 'utf-8') || '{}');
|
174
|
+
currentResult[type] = url;
|
175
|
+
currentResult.time = Date.now();
|
176
|
+
currentResult.hash = hash;
|
177
|
+
fs.writeFileSync(previewFilePath, JSON.stringify(currentResult));
|
178
|
+
} catch (_) {
|
179
|
+
// do not report such error
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
/**
|
184
|
+
* @description 输入字节数,返回MB字符串
|
185
|
+
* @param [size] - number
|
186
|
+
*/
|
187
|
+
function getFormattedSize(size) {
|
188
|
+
const formattedSize = (size / 1024 / 1024).toFixed(2);
|
189
|
+
return formattedSize;
|
190
|
+
}
|
191
|
+
|
192
|
+
function getCachedPreviewResult(type, hash) {
|
193
|
+
try {
|
194
|
+
const currentResult = JSON.parse(fs.readFileSync(previewFilePath, 'utf-8') || '{}');
|
195
|
+
if (currentResult.hash === hash && currentResult[type]) {
|
196
|
+
const cacheTime = currentResult.time;
|
197
|
+
const daysPassed = (Date.now() - cacheTime || 0) / (60 * 60 * 1000 * 24);
|
198
|
+
if (daysPassed < 1) {
|
199
|
+
return currentResult[type];
|
200
|
+
}
|
201
|
+
}
|
202
|
+
} catch (_) {
|
203
|
+
// do not report such error
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
function getFolderSize(folderPath, options = {}) {
|
208
|
+
return new Promise((resolve, reject) => {
|
209
|
+
glob(
|
210
|
+
'**',
|
211
|
+
{
|
212
|
+
cwd: folderPath,
|
213
|
+
ignore: options.ignore || ['**/.*', '**/node_modules/**', '**/**.js.map'],
|
214
|
+
absolute: true,
|
215
|
+
},
|
216
|
+
(err, matches) => {
|
217
|
+
if (err) {
|
218
|
+
return reject(err);
|
219
|
+
}
|
220
|
+
try {
|
221
|
+
let totalSize = 0;
|
222
|
+
matches.forEach(file => {
|
223
|
+
const stat = fs.statSync(file);
|
224
|
+
if (!stat.isDirectory()) totalSize += stat.size;
|
225
|
+
});
|
226
|
+
resolve(totalSize);
|
227
|
+
} catch (err) {
|
228
|
+
reject(err);
|
229
|
+
}
|
230
|
+
},
|
231
|
+
);
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
module.exports = {
|
236
|
+
mixEncode,
|
237
|
+
zipFile,
|
238
|
+
compileErrFormat,
|
239
|
+
getPackageName,
|
240
|
+
savePreviewResult,
|
241
|
+
getCachedPreviewResult
|
242
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
const readline = require('readline');
|
2
|
+
const chalk = require('chalk');
|
3
|
+
|
4
|
+
function formatTitle(severity, message) {
|
5
|
+
return chalk[bgColor(severity)].black('', message, '');
|
6
|
+
}
|
7
|
+
|
8
|
+
function formatText(severity, message) {
|
9
|
+
return chalk[textColor(severity)](message);
|
10
|
+
}
|
11
|
+
|
12
|
+
function textColor(severity) {
|
13
|
+
switch (severity.toLowerCase()) {
|
14
|
+
case 'success': return 'green';
|
15
|
+
case 'info': return 'blue';
|
16
|
+
case 'note': return 'white';
|
17
|
+
case 'warning': return 'yellow';
|
18
|
+
case 'error': return 'red';
|
19
|
+
default: return 'red';
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
function bgColor(severity) {
|
24
|
+
const color = textColor(severity);
|
25
|
+
return 'bg'+ capitalizeFirstLetter(color)
|
26
|
+
}
|
27
|
+
|
28
|
+
function capitalizeFirstLetter(string) {
|
29
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
30
|
+
}
|
31
|
+
|
32
|
+
function outputResult(severity, title, subtitle) {
|
33
|
+
const titleFormatted = formatTitle(severity, title);
|
34
|
+
const subTitleFormatted = formatText(severity, subtitle);
|
35
|
+
const message = `${titleFormatted} ${subTitleFormatted}`;
|
36
|
+
console.log(message);
|
37
|
+
}
|
38
|
+
|
39
|
+
function clearConsole(title) {
|
40
|
+
if (process.stdout.isTTY) {
|
41
|
+
const blank = '\n'.repeat(process.stdout.rows);
|
42
|
+
console.log(blank);
|
43
|
+
readline.cursorTo(process.stdout, 0, 0);
|
44
|
+
readline.clearScreenDown(process.stdout);
|
45
|
+
if (title) {
|
46
|
+
console.log(title);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
module.exports = {
|
52
|
+
clearConsole,
|
53
|
+
outputResult
|
54
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
const qrcode = require('qrcode-terminal');
|
2
|
+
const chalk = require('chalk');
|
3
|
+
function generateQrCode(url, options) {
|
4
|
+
// sometimes can not use small type, see: https://github.com/gtanner/qrcode-terminal/issues/21
|
5
|
+
qrcode.generate(url, { small: options.small });
|
6
|
+
let copied = '';
|
7
|
+
if (options.copy) {
|
8
|
+
require('clipboardy').writeSync(url);
|
9
|
+
copied = chalk.dim('(copied to clipboard)');
|
10
|
+
}
|
11
|
+
if (options.small) {
|
12
|
+
console.log(`${chalk.yellow('small QR Code may not work in some environments')}\n`);
|
13
|
+
}
|
14
|
+
console.log(`${chalk.cyan(JSON.stringify(url))} ${copied}`);
|
15
|
+
}
|
16
|
+
|
17
|
+
module.exports = {
|
18
|
+
generateQrCode,
|
19
|
+
};
|
@@ -0,0 +1,360 @@
|
|
1
|
+
const axios = require('axios');
|
2
|
+
const FormData = require('form-data');
|
3
|
+
const querystring = require('querystring');
|
4
|
+
const url = require('url');
|
5
|
+
const fs = require('fs');
|
6
|
+
const execa = require('execa');
|
7
|
+
const {
|
8
|
+
getUserCookies
|
9
|
+
} = require('./cookie');
|
10
|
+
const {
|
11
|
+
compileErrFormat,
|
12
|
+
getPackageName
|
13
|
+
} = require('./helper');
|
14
|
+
const {
|
15
|
+
getVersion
|
16
|
+
} = require('./version');
|
17
|
+
const useBoeRequest = getVersion().includes('test');
|
18
|
+
const URL = require('url');
|
19
|
+
const baseParams = {
|
20
|
+
aid: 1365
|
21
|
+
};
|
22
|
+
const VERIFICATION_CODE_URL = '/passport/web/send_code';
|
23
|
+
const MOBILE_LOGIN_URL = '/passport/web/sms_login';
|
24
|
+
const EMAIL_LOGIN_URL = '/passport/web/email/login';
|
25
|
+
const GET_USER_INFO = '/api/v1/user';
|
26
|
+
const BASE_URL = useBoeRequest ? 'http://developer-boe.toutiao.com' : 'https://developer.toutiao.com';
|
27
|
+
const REFERER = 'developer.toutiao.com';
|
28
|
+
axios.defaults.baseURL = BASE_URL;
|
29
|
+
|
30
|
+
// 为请求添加referer
|
31
|
+
axios.interceptors.request.use(config => {
|
32
|
+
config.headers.Referer = REFERER;
|
33
|
+
if (config.data instanceof FormData) {
|
34
|
+
Object.assign(config.headers, config.data.getHeaders());
|
35
|
+
}
|
36
|
+
if(config.proxy) {
|
37
|
+
const parseURL = URL.parse(config.proxy.host);
|
38
|
+
config.httpsAgent = require('tunnel').httpsOverHttp({
|
39
|
+
proxy: {
|
40
|
+
host: parseURL.host,
|
41
|
+
port: config.proxy.port,
|
42
|
+
},
|
43
|
+
rejectUnauthorized: false
|
44
|
+
});
|
45
|
+
config.proxy = false;
|
46
|
+
}
|
47
|
+
return config;
|
48
|
+
})
|
49
|
+
|
50
|
+
exports.getMobileVerificationCode = function (mobile, proxy) {
|
51
|
+
const verificationOptions = {
|
52
|
+
method: 'get',
|
53
|
+
url: VERIFICATION_CODE_URL,
|
54
|
+
params: {
|
55
|
+
...baseParams,
|
56
|
+
type: 24,
|
57
|
+
mobile
|
58
|
+
},
|
59
|
+
headers: {
|
60
|
+
'User-Agent': 'bytedanceide'
|
61
|
+
}
|
62
|
+
}
|
63
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
64
|
+
const proxySplitArr = proxy.split(':');
|
65
|
+
const proxyPort = proxySplitArr.pop();
|
66
|
+
const proxyHost = proxySplitArr.join(':');
|
67
|
+
verificationOptions.proxy = {
|
68
|
+
host: proxyHost,
|
69
|
+
port: proxyPort
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return axios(verificationOptions).then(res => {
|
73
|
+
const isSuccess = res.data.message === 'success';
|
74
|
+
// Not send res.data.data.description temporarily,because the tip is not for i18n
|
75
|
+
return {
|
76
|
+
success: isSuccess,
|
77
|
+
// msg: !isSuccess ? (res.data.data.description || 'Get verification code fail, please try later') : ''
|
78
|
+
msg: !isSuccess ? 'Get verification code fail, please try later' : ''
|
79
|
+
}
|
80
|
+
}).catch(err => {
|
81
|
+
return {
|
82
|
+
success: false,
|
83
|
+
msg: err.message
|
84
|
+
}
|
85
|
+
});
|
86
|
+
}
|
87
|
+
|
88
|
+
exports.userLogin = function (type, params, proxy) {
|
89
|
+
const userLoginOptions = {
|
90
|
+
url: type === 'mobile' ? MOBILE_LOGIN_URL : EMAIL_LOGIN_URL,
|
91
|
+
method: 'POST',
|
92
|
+
data: querystring.stringify({
|
93
|
+
...baseParams,
|
94
|
+
...params
|
95
|
+
}),
|
96
|
+
headers: {
|
97
|
+
'content-type': 'application/x-www-form-urlencoded'
|
98
|
+
}
|
99
|
+
}
|
100
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
101
|
+
const proxySplitArr = proxy.split(':');
|
102
|
+
const proxyPort = proxySplitArr.pop();
|
103
|
+
const proxyHost = proxySplitArr.join(':');
|
104
|
+
userLoginOptions.proxy = {
|
105
|
+
host: proxyHost,
|
106
|
+
port: proxyPort
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return axios(userLoginOptions).then(res => {
|
110
|
+
const isSuccess = res.data.message === 'success';
|
111
|
+
return {
|
112
|
+
success: isSuccess,
|
113
|
+
cookies: res.headers['set-cookie'],
|
114
|
+
msg: !isSuccess ? (res.data.data.description || 'Login failed, please try again') : ''
|
115
|
+
}
|
116
|
+
}).catch(err => {
|
117
|
+
return {
|
118
|
+
success: false,
|
119
|
+
msg: err.message
|
120
|
+
}
|
121
|
+
});
|
122
|
+
}
|
123
|
+
|
124
|
+
exports.getUserData = function (proxy) {
|
125
|
+
const userDataOption = {
|
126
|
+
params: {},
|
127
|
+
headers: {
|
128
|
+
Cookie: getUserCookies()
|
129
|
+
}
|
130
|
+
}
|
131
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
132
|
+
const proxySplitArr = proxy.split(':');
|
133
|
+
const proxyPort = proxySplitArr.pop();
|
134
|
+
const proxyHost = proxySplitArr.join(':');
|
135
|
+
userDataOption.proxy = {
|
136
|
+
host: proxyHost,
|
137
|
+
port: proxyPort
|
138
|
+
}
|
139
|
+
}
|
140
|
+
return axios.get(GET_USER_INFO, userDataOption).then(res => {
|
141
|
+
const isSuccess = !res.data.error;
|
142
|
+
const userData = {
|
143
|
+
username: res.data.name || '',
|
144
|
+
avatar: res.data.avatar || '',
|
145
|
+
developerId: res.data.developer_id || '',
|
146
|
+
mobile: res.data.mobile || '',
|
147
|
+
email: res.data.email || '',
|
148
|
+
auditStatus: res.data.audit_status || 0,
|
149
|
+
uid: res.data.uid
|
150
|
+
};
|
151
|
+
return {
|
152
|
+
success: isSuccess,
|
153
|
+
userData,
|
154
|
+
msg: !isSuccess ? 'Login fail, please try later' : ''
|
155
|
+
}
|
156
|
+
}).catch(err => {
|
157
|
+
return {
|
158
|
+
success: false,
|
159
|
+
msg: err.message
|
160
|
+
}
|
161
|
+
});
|
162
|
+
}
|
163
|
+
|
164
|
+
exports.uploadProject = function ({
|
165
|
+
type,
|
166
|
+
appId,
|
167
|
+
zipPath,
|
168
|
+
versionInfo,
|
169
|
+
updateInfo,
|
170
|
+
proxy
|
171
|
+
}) {
|
172
|
+
return new Promise(function (resolve, reject) {
|
173
|
+
let path;
|
174
|
+
const form = new FormData();
|
175
|
+
if (type === 'preview') {
|
176
|
+
// path = `/api/v2/app/${appId}/preview`
|
177
|
+
path = `/api/developer/ide/microgame/v1/preview?appid=${appId}`
|
178
|
+
} else {
|
179
|
+
// path = `/api/v2/app/${appId}/testing`
|
180
|
+
path = `/api/developer/ide/microgame/v1/testing?appid=${appId}`
|
181
|
+
form.append('version', versionInfo);
|
182
|
+
form.append('intro', updateInfo);
|
183
|
+
}
|
184
|
+
// form.append('render_type', 3);
|
185
|
+
form.append('source', fs.createReadStream(zipPath));
|
186
|
+
form.append('local_compile_version', '4.0.0-rc.12.ide');
|
187
|
+
const uploadOptions = {
|
188
|
+
method: 'put',
|
189
|
+
headers: {
|
190
|
+
'Cookie': getUserCookies()
|
191
|
+
},
|
192
|
+
url: path,
|
193
|
+
form,
|
194
|
+
}
|
195
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
196
|
+
const proxySplitArr = proxy.split(':');
|
197
|
+
const proxyPort = proxySplitArr.pop();
|
198
|
+
const proxyHost = proxySplitArr.join(':');
|
199
|
+
uploadOptions.proxy = {
|
200
|
+
host: proxyHost,
|
201
|
+
port: proxyPort
|
202
|
+
}
|
203
|
+
}
|
204
|
+
axios.put(path, form, uploadOptions).then(res => {
|
205
|
+
if (res.data && res.data.error === 0) {
|
206
|
+
resolve();
|
207
|
+
} else {
|
208
|
+
reject(res.data.message)
|
209
|
+
}
|
210
|
+
}).catch(err => {
|
211
|
+
reject(err.message);
|
212
|
+
});
|
213
|
+
})
|
214
|
+
}
|
215
|
+
|
216
|
+
exports.getCompileProgress = function (appId, proxy) {
|
217
|
+
const compileProgressOption = {
|
218
|
+
headers: {
|
219
|
+
Cookie: getUserCookies()
|
220
|
+
}
|
221
|
+
}
|
222
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
223
|
+
const proxySplitArr = proxy.split(':');
|
224
|
+
const proxyPort = proxySplitArr.pop();
|
225
|
+
const proxyHost = proxySplitArr.join(':');
|
226
|
+
compileProgressOption.proxy = {
|
227
|
+
host: proxyHost,
|
228
|
+
port: proxyPort
|
229
|
+
}
|
230
|
+
}
|
231
|
+
// return axios.get(`/api/v1/app/${appId}/compile_progress`, compileProgressOption).then(res => {
|
232
|
+
return axios.get(`/api/developer/ide/microgame/v1/compile_progress?appid=${appId}`, compileProgressOption).then(res => {
|
233
|
+
const {
|
234
|
+
error,
|
235
|
+
status,
|
236
|
+
message = ''
|
237
|
+
} = res.data || {};
|
238
|
+
if (error === 1) {
|
239
|
+
msg = message ? compileErrFormat(message) : 'Preview failed, please try later';
|
240
|
+
return {
|
241
|
+
success: false,
|
242
|
+
msg
|
243
|
+
}
|
244
|
+
}
|
245
|
+
return {
|
246
|
+
success: true,
|
247
|
+
done: error === 0 && status === 2,
|
248
|
+
msg: ''
|
249
|
+
}
|
250
|
+
}).catch(err => {
|
251
|
+
return {
|
252
|
+
success: false,
|
253
|
+
msg: err.message
|
254
|
+
}
|
255
|
+
});
|
256
|
+
}
|
257
|
+
|
258
|
+
exports.getQrCode = function (appId, proxy, type = 'preview') {
|
259
|
+
const requestHeader = {
|
260
|
+
Cookie: getUserCookies()
|
261
|
+
}
|
262
|
+
if (useBoeRequest) {
|
263
|
+
requestHeader['X-TT-ENV'] = 'test';
|
264
|
+
}
|
265
|
+
const qrCodeOptions = {
|
266
|
+
params: {
|
267
|
+
t: Date.now()
|
268
|
+
},
|
269
|
+
headers: requestHeader
|
270
|
+
}
|
271
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
272
|
+
const proxySplitArr = proxy.split(':');
|
273
|
+
const proxyPort = proxySplitArr.pop();
|
274
|
+
const proxyHost = proxySplitArr.join(':');
|
275
|
+
qrCodeOptions.proxy = {
|
276
|
+
host: proxyHost,
|
277
|
+
port: proxyPort
|
278
|
+
}
|
279
|
+
}
|
280
|
+
return axios.get(`/api/v1/app/${appId}/${type}/qrcode_url`, qrCodeOptions).then(res => {
|
281
|
+
return {
|
282
|
+
success: true,
|
283
|
+
url: res.data,
|
284
|
+
msg: ''
|
285
|
+
}
|
286
|
+
}).catch(err => {
|
287
|
+
return {
|
288
|
+
success: false,
|
289
|
+
msg: err.message
|
290
|
+
}
|
291
|
+
});
|
292
|
+
}
|
293
|
+
|
294
|
+
exports.checkUserPermissions = function (appId, proxy) {
|
295
|
+
const permissionsOptions = {
|
296
|
+
headers: {
|
297
|
+
Cookie: getUserCookies()
|
298
|
+
}
|
299
|
+
}
|
300
|
+
if (proxy && proxy.indexOf(':') > -1) {
|
301
|
+
const proxySplitArr = proxy.split(':');
|
302
|
+
const proxyPort = proxySplitArr.pop();
|
303
|
+
const proxyHost = proxySplitArr.join(':');
|
304
|
+
permissionsOptions.proxy = {
|
305
|
+
host: proxyHost,
|
306
|
+
port: proxyPort
|
307
|
+
}
|
308
|
+
}
|
309
|
+
return axios.get(`/api/v1/app/${appId}/permissions`, permissionsOptions).then(res => {
|
310
|
+
const {
|
311
|
+
error,
|
312
|
+
message,
|
313
|
+
data
|
314
|
+
} = res.data || {};
|
315
|
+
if (error) {
|
316
|
+
const msg = message || 'Upload failed,please check if your appId is valid';
|
317
|
+
return {
|
318
|
+
success: false,
|
319
|
+
msg
|
320
|
+
};
|
321
|
+
}
|
322
|
+
if (data.is_admin || data.publish === 2) {
|
323
|
+
return {
|
324
|
+
success: true,
|
325
|
+
msg: ''
|
326
|
+
};
|
327
|
+
} else {
|
328
|
+
return {
|
329
|
+
success: false,
|
330
|
+
msg: 'You do not have permission to upload app'
|
331
|
+
};
|
332
|
+
}
|
333
|
+
}).catch(err => {
|
334
|
+
console.log(err)
|
335
|
+
return {
|
336
|
+
success: false,
|
337
|
+
msg: err.message
|
338
|
+
}
|
339
|
+
});
|
340
|
+
}
|
341
|
+
// 该方法暂无调用
|
342
|
+
exports.checkRemoteVersion = async function () {
|
343
|
+
const registry = (await execa('npm', ['config', 'get', 'registry'])).stdout;
|
344
|
+
return axios.get(`${registry}${getPackageName()}`, {
|
345
|
+
params: {},
|
346
|
+
headers: {
|
347
|
+
Accept: 'application/vnd.npm.install-v1+json'
|
348
|
+
}
|
349
|
+
}).then(res => {
|
350
|
+
return {
|
351
|
+
version: res.data['dist-tags'].latest,
|
352
|
+
success: true
|
353
|
+
}
|
354
|
+
}).catch(err => {
|
355
|
+
return {
|
356
|
+
success: false,
|
357
|
+
msg: err.message
|
358
|
+
}
|
359
|
+
});
|
360
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
const fs = require('fs-extra');
|
2
|
+
const path = require('path');
|
3
|
+
const { getStoragePath } = require('./config');
|
4
|
+
const versionFilePath = path.join(getStoragePath(), 'version.json');
|
5
|
+
fs.ensureFileSync(versionFilePath);
|
6
|
+
|
7
|
+
function getVersion() {
|
8
|
+
return require(`../../package.json`).version;
|
9
|
+
}
|
10
|
+
|
11
|
+
async function saveLatestVersionToLocal(version, time) {
|
12
|
+
await fs.writeFile(versionFilePath, JSON.stringify({
|
13
|
+
"version": version,
|
14
|
+
"time": time
|
15
|
+
}));
|
16
|
+
}
|
17
|
+
|
18
|
+
async function getLatestVersionFromLocal() {
|
19
|
+
const fileData = await fs.readFile(versionFilePath, 'utf-8');
|
20
|
+
return JSON.parse(fileData || "{}");
|
21
|
+
}
|
22
|
+
|
23
|
+
module.exports = {
|
24
|
+
getVersion,
|
25
|
+
saveLatestVersionToLocal,
|
26
|
+
getLatestVersionFromLocal
|
27
|
+
}
|