@lazycatcloud/lzc-cli 1.3.12 → 1.3.13
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 +9 -0
- package/lib/app/apkshell.js +37 -40
- package/lib/app/index.js +187 -186
- package/lib/app/lpk_build.js +341 -358
- package/lib/app/lpk_create.js +135 -155
- package/lib/app/lpk_create_generator.js +74 -66
- package/lib/app/lpk_devshell.js +444 -533
- package/lib/app/lpk_devshell_docker.js +48 -47
- package/lib/app/lpk_installer.js +119 -123
- package/lib/appstore/index.js +205 -214
- package/lib/appstore/login.js +146 -143
- package/lib/appstore/prePublish.js +101 -100
- package/lib/appstore/publish.js +253 -256
- package/lib/box/index.js +82 -77
- package/lib/config/index.js +58 -54
- package/lib/debug_bridge.js +280 -330
- package/lib/docker/index.js +84 -86
- package/lib/i18n/README.md +25 -0
- package/lib/i18n/index.js +37 -0
- package/lib/i18n/locales/en/translation.json +251 -0
- package/lib/i18n/locales/zh/translation.json +251 -0
- package/lib/shellapi.js +122 -146
- package/lib/utils.js +536 -552
- package/package.json +6 -8
- package/scripts/cli.js +81 -77
- package/scripts/lzc-docker-compose.js +34 -33
- package/scripts/lzc-docker.js +34 -33
package/lib/appstore/login.js
CHANGED
|
@@ -1,176 +1,179 @@
|
|
|
1
|
-
import fetch from
|
|
2
|
-
import path from
|
|
3
|
-
import url from
|
|
4
|
-
import logger from
|
|
5
|
-
import env from
|
|
6
|
-
import inquirer from
|
|
7
|
-
import { accountServerUrl } from
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import url from 'url';
|
|
4
|
+
import logger from 'loglevel';
|
|
5
|
+
import env from '../config/env.js';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import { accountServerUrl } from './env.js';
|
|
8
|
+
import { t } from '../i18n/index.js';
|
|
8
9
|
|
|
9
10
|
function join(...params) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
let x = '';
|
|
12
|
+
try {
|
|
13
|
+
// fix: url path join failed for windows
|
|
14
|
+
const u = new url.URL(params[0]);
|
|
15
|
+
params.splice(0, 1);
|
|
16
|
+
u.pathname = path.posix.join(u.pathname, ...params);
|
|
17
|
+
x = u.toString();
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.warn(error);
|
|
20
|
+
x = path.join(...params);
|
|
21
|
+
}
|
|
22
|
+
return x;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
async function login(username, password) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
26
|
+
return fetch(join(accountServerUrl, '/api/login/signin'), {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
body: new URLSearchParams({
|
|
29
|
+
username: username,
|
|
30
|
+
password: password,
|
|
31
|
+
}),
|
|
32
|
+
})
|
|
33
|
+
.then(async (res) => {
|
|
34
|
+
let bodyText = await res.text();
|
|
35
|
+
try {
|
|
36
|
+
let body = JSON.parse(bodyText);
|
|
37
|
+
if (body.success) {
|
|
38
|
+
return Promise.resolve(body.data);
|
|
39
|
+
}
|
|
40
|
+
throw body;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
error.responseStatus = res.status;
|
|
43
|
+
error.responseBody = bodyText;
|
|
44
|
+
return Promise.reject(error);
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
.then((data) => {
|
|
48
|
+
env.set({ token: data.token }, true);
|
|
49
|
+
logger.info(t('lzc_cli.lib.appstore.login.login_success_tips', '登录成功!'));
|
|
50
|
+
});
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
async function isLogin() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
54
|
+
try {
|
|
55
|
+
let token = env.get('token');
|
|
56
|
+
if (!token) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return fetch(join(accountServerUrl, '/api/user/current'), {
|
|
60
|
+
method: 'GET',
|
|
61
|
+
headers: {
|
|
62
|
+
'X-User-Token': token,
|
|
63
|
+
},
|
|
64
|
+
}).then(async (res) => {
|
|
65
|
+
let bodyText = await res.text();
|
|
66
|
+
let body = JSON.parse(bodyText);
|
|
67
|
+
if (body.success) {
|
|
68
|
+
return token;
|
|
69
|
+
}
|
|
70
|
+
logger.debug(body.message);
|
|
71
|
+
return false;
|
|
72
|
+
});
|
|
73
|
+
} catch (e) {
|
|
74
|
+
logger.trace(e);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
async function askUserInfo() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
const noEmpty = (value) => value != '';
|
|
81
|
+
return await inquirer.prompt([
|
|
82
|
+
{
|
|
83
|
+
type: 'input',
|
|
84
|
+
name: 'username',
|
|
85
|
+
message: t('lzc_cli.lib.login.ask_user_info_username_prompt', '请输入登录用户名'),
|
|
86
|
+
validate: noEmpty,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: 'password',
|
|
90
|
+
mask: '*',
|
|
91
|
+
name: 'password',
|
|
92
|
+
message: t('lzc_cli.lib.login.ask_user_info_password_prompt', '请输入登录密码'),
|
|
93
|
+
validate: noEmpty,
|
|
94
|
+
},
|
|
95
|
+
]);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
async function interactiveLogin() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
try {
|
|
100
|
+
let info = await askUserInfo();
|
|
101
|
+
await login(info.username, info.password);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
logger.debug('login error: ', e);
|
|
104
|
+
if (e?.errorCode == 0 || e?.message == '密码错误') {
|
|
105
|
+
logger.error(t('lzc_cli.lib.login.interactive_login_user_passwd_error_tips', '帐号或者密码错误,请重新输入!'));
|
|
106
|
+
} else {
|
|
107
|
+
logger.error(
|
|
108
|
+
t('lzc_cli.lib.login.interactive_login_fail_tips', `登录失败,{{message}}`, {
|
|
109
|
+
message: e?.message ?? e,
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return interactiveLogin();
|
|
114
|
+
}
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
function tipsFirstLogin() {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
}
|
|
118
|
+
let token = env.get('token');
|
|
119
|
+
if (!token) {
|
|
120
|
+
// 还没登录过的用户提示用户前往 https://developer.lazycat.cloud/manage 注册开发者账号
|
|
121
|
+
logger.info(t('lzc_cli.lib.login.tips_first_login_tips', '请登录懒猫微服社区账号,账号注册以及开发者权限申请地址: https://developer.lazycat.cloud/manage'));
|
|
122
|
+
}
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
export async function reLogin() {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
126
|
+
let token = await isLogin();
|
|
127
|
+
if (token) {
|
|
128
|
+
const questions = [
|
|
129
|
+
{
|
|
130
|
+
name: 'relogin',
|
|
131
|
+
type: 'input',
|
|
132
|
+
default: 'n',
|
|
133
|
+
message: t('lzc_cli.lib.login.re_login_message_prompt', '检测到已经登录,是否重新登录(y/n):'),
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
const answers = await inquirer.prompt(questions);
|
|
137
|
+
if (answers.relogin.toLowerCase() === 'n') {
|
|
138
|
+
logger.info(`token: ${token}`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
tipsFirstLogin();
|
|
143
|
+
}
|
|
144
|
+
await interactiveLogin();
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
export async function autoLogin() {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
let token = await isLogin();
|
|
149
|
+
if (token) {
|
|
150
|
+
logger.debug(t('lzc_cli.lib.login.auto_login_success', 'appstore 已经登录'));
|
|
151
|
+
return;
|
|
152
|
+
} else {
|
|
153
|
+
tipsFirstLogin();
|
|
154
|
+
}
|
|
152
155
|
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
logger.debug(t('lzc_cli.lib.login.auto_login_interactive_login', 'token错误,尝试自动登录'));
|
|
157
|
+
await interactiveLogin();
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
export async function request(url, options = {}) {
|
|
158
|
-
|
|
161
|
+
await autoLogin();
|
|
159
162
|
|
|
160
|
-
|
|
163
|
+
const token = env.get('token');
|
|
161
164
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
let headers = {
|
|
166
|
+
'X-User-Token': token,
|
|
167
|
+
cookie: `userToken=${token}`,
|
|
168
|
+
};
|
|
169
|
+
if (options.headers) {
|
|
170
|
+
headers = Object.assign({}, options.headers, headers);
|
|
171
|
+
}
|
|
169
172
|
|
|
170
|
-
|
|
173
|
+
// logger.debug("token", token)
|
|
171
174
|
|
|
172
|
-
|
|
173
|
-
|
|
175
|
+
options = Object.assign({}, options, { headers });
|
|
176
|
+
logger.trace(`fetch ${url}`, options);
|
|
174
177
|
|
|
175
|
-
|
|
178
|
+
return fetch(url, options);
|
|
176
179
|
}
|
|
@@ -1,115 +1,116 @@
|
|
|
1
|
-
import { request, autoLogin } from
|
|
2
|
-
import logger from
|
|
3
|
-
import FormData from
|
|
4
|
-
import fs from
|
|
5
|
-
import inquirer from
|
|
6
|
-
import path from
|
|
7
|
-
import { isFileExist, isPngWithFile, unzipSync } from "../utils.js"
|
|
8
|
-
import env from
|
|
9
|
-
import {
|
|
1
|
+
import { request, autoLogin } from './login.js';
|
|
2
|
+
import logger from 'loglevel';
|
|
3
|
+
import FormData from 'form-data';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
// import path from 'node:path';
|
|
7
|
+
// import { isFileExist, isPngWithFile, unzipSync } from "../utils.js"
|
|
8
|
+
import env from '../config/env.js';
|
|
9
|
+
import { t } from '../i18n/index.js';
|
|
10
|
+
import { Publish } from './publish.js';
|
|
10
11
|
|
|
11
12
|
async function askChangeLog() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
const noEmpty = (value) => value != '';
|
|
14
|
+
return await inquirer.prompt([
|
|
15
|
+
{
|
|
16
|
+
name: 'changelog',
|
|
17
|
+
type: 'editor',
|
|
18
|
+
message: t('lzc_cli.lib.pre_publish.ask_changelog_prompt', '填写 changelog 内容'),
|
|
19
|
+
validate: noEmpty,
|
|
20
|
+
},
|
|
21
|
+
]);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
async function askGroup(choices) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
return (
|
|
26
|
+
await inquirer.prompt([
|
|
27
|
+
{
|
|
28
|
+
name: 'type',
|
|
29
|
+
message: t('lzc_cli.lib.pre_publish.ask_group_prompt', '选择内测组'),
|
|
30
|
+
type: 'list',
|
|
31
|
+
choices,
|
|
32
|
+
},
|
|
33
|
+
])
|
|
34
|
+
)['type'];
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export class PrePublish {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
constructor(baseUrl = 'https://testflight.lazycat.cloud/api') {
|
|
39
|
+
this.baseUrl = baseUrl;
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
async getDict() {
|
|
43
|
+
const url = this.baseUrl + '/groups/dict';
|
|
44
|
+
const token = env.get('token');
|
|
45
|
+
const res = await request(url, {
|
|
46
|
+
method: 'GET',
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: `Bearer ${token}`,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const text = (await res.text()).trim();
|
|
52
|
+
if (!Publish.isJSON(text)) {
|
|
53
|
+
logger.error(`parse error: dict resp text not is json`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const respJson = await JSON.parse(text);
|
|
57
|
+
return respJson.data || [];
|
|
58
|
+
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
async upload(groupId, changelog, pkgPath) {
|
|
61
|
+
const form = new FormData();
|
|
62
|
+
form.append('type', 'Lpk');
|
|
63
|
+
form.append('changelog', changelog);
|
|
64
|
+
form.append('file', fs.createReadStream(pkgPath));
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
66
|
+
const url = this.baseUrl + `/group/${groupId}/upload`;
|
|
67
|
+
const token = env.get('token');
|
|
68
|
+
const res = await request(url, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
body: form,
|
|
71
|
+
headers: {
|
|
72
|
+
Authorization: `Bearer ${token}`,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const text = (await res.text()).trim();
|
|
76
|
+
if (!Publish.isJSON(text)) {
|
|
77
|
+
logger.error(`parse error: upload resp text not is json`, text);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const respJson = await JSON.parse(text);
|
|
81
|
+
logger.debug('upload lpk response', respJson);
|
|
82
|
+
return respJson;
|
|
83
|
+
}
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
/**
|
|
86
|
+
* @param {string} pkgPath
|
|
87
|
+
* @param {string} changelog
|
|
88
|
+
*/
|
|
89
|
+
async publish(pkgPath, changelog, gid) {
|
|
90
|
+
if (!Publish.preCheck(pkgPath)) return;
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
await autoLogin();
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
94
|
+
if (!gid) {
|
|
95
|
+
const groups = await this.getDict();
|
|
96
|
+
const groupName = await askGroup(groups.map((it) => it.name));
|
|
97
|
+
gid = groups.find((it) => it.name == groupName)?.id;
|
|
98
|
+
}
|
|
99
|
+
if (!gid) {
|
|
100
|
+
logger.error(t('lzc_cli.lib.pre_publish.publish_gid_not_exist_tips', '请选择内测组'));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!changelog) {
|
|
104
|
+
const answer = await askChangeLog();
|
|
105
|
+
changelog = answer.changelog;
|
|
106
|
+
}
|
|
107
|
+
changelog = changelog.trim(); // clean space ^:)
|
|
108
|
+
logger.info(t('lzc_cli.lib.pre_publish.publish_pending_tips', '正在提交内测...'));
|
|
109
|
+
const resp = await this.upload(gid, changelog, pkgPath);
|
|
110
|
+
if (resp.success) {
|
|
111
|
+
logger.info(t('lzc_cli.lib.pre_publish.publish_done_tips', '应用提交成功! 请在内测工具中查看'));
|
|
112
|
+
} else {
|
|
113
|
+
logger.error(t('lzc_cli.lib.pre_publish.publish_fail_tips', `应用提交失败: {{message}}`, { message: resp.msg }));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
115
116
|
}
|